Chronicle Timeline Server

Horizon Digital Economy Research

March 13, 2019

Document Version: v0.0.4

Server Version: v0.0.2

API Version: v1

Abstract

This document describes the Chronicle Timeline Server protocols, APIs and reference implementation.

Contents

 1 API
  1.1 Authentication
   1.1.1 User Authentication
   1.1.2 Token Authentication
   1.1.3 Token Scripts
   1.1.4 Generating a Signature
  1.2 Methods
   1.2.1 Create Timeline
   1.2.2 Create Timeline Access Token
   1.2.3 Read Timeline
   1.2.4 Clone Timeline
   1.2.5 Create Timeline Entry
   1.2.6 Create Timeline Entry (Chunked Upload)
   1.2.7 Create Timeline Entry Access Token
   1.2.8 Read Timeline Entries
   1.2.9 Read Timeline Entry
   1.2.10 Read Timeline Entry Content
   1.2.11 Update Timeline Entry
 Appendices
 A Document Revisions

List of Figures

1 API

1.1 Authentication

1.1.1 User Authentication

User authentication is achieved by signing a client request with an RSA private key, the signature may then be verified by the server with the corresponding public key. The basic user interface allows a user to either upload an RSA public key, or to generate a new RSA key pair (the private key is not stored on the server). Documentation on the basic user interface is pending. User authentication information is passed in the Authorization header:

Authorization: chronicle-user-hmac
auth_nonce="",
auth_signature="",
auth_signature_method="RSA-SHA512",
auth_timestamp="",
auth_username="",
auth_version="1.0",

1.1.2 Token Authentication

Token authentication is achieved by signing a client request with a secret key, the signature may then be verified by the server which maintains a copy of the secret key. The basic user interface allows a user to generate tokens that have grant the holder certain permissions (documentation pending). Token authentication information is passed in the Authorization header:

Authorization: chronicle-token-hmac
auth_nonce="",
auth_signature="",
auth_signature_method="SHA512",
auth_timestamp="",
auth_token_id="",
auth_version="1.0",

1.1.3 Token Scripts

Tokens are associated with scripts which can be used to create more complex authentication scenarios than just allow. Scripts are written in Javascript and are run after a request token has been validated. Two functions are exposed to the script:

Only one of authorize or reject may be called in a single script session, repeated calls will result in an exception. If neither is called the default behaviour is to reject the request.

It is possible for State to be maintained between script sessions. A variable named state is exposed to the script which contains the current state. Changes to state are not automatically saved, in order to save state the script must call the update_state(state) function. State must be JSON serializable and defaults to null.

As a simple example, a script could be used to create a token that could only be used a specific number of times. The below script, in combination with a state set initially to 10 would only allow the token to be used 10 times.

  if (state > 0) {
    update_state(state - 1);
    authorize();
  } else {
    reject('This token has expired');
  }

1.1.4 Generating a Signature

The following method is used to generate a signature:

  1. Begin with an empty string.
  2. Append the request method (in uppercase).
  3. Append an ampersand (&)
  4. Percent encode the base request url (without query parameters or fragments) and append to the string.
  5. Append an ampersand (&).
  6. Gather all of the url query parameters and all the auth_ parameters.
  7. Percent encode every key and every value.
  8. Sort alphabetically (ascending) on (encoded) key name, if there are duplicate entries for a key name, continue sorting on the (encoded) key value.
  9. Create a new empty string and, for each key/value pair:
    1. Append the endoded key.
    2. Append an equals sign (=).
    3. Append the encoded value.
    4. If there are items remaining, append an ampersand (&).
    5. Repeat until all key/value pairs are appended.
  10. Percent encode the new query string and append.
  11. Append an ampersand (&)
  12. Percent encode the request body and append.
  13. Percent encode the entire string and create a signature using the secret key (this is the RSA private key in the case of user authentication) and the SHA512 algorithm. PSS padding using the MGF1 mask generation function should be used with the SHA512 algorithm. The signature should be base64 encoded.

For more details on percent encoding refer to RFC 3986.

For more details on base64 encoding refer to RFC 4648.

1.2 Methods

1.2.1 Create Timeline

Path /timeline[/]

Method POST

Data Params The post body must conform to the schema below and have a content type of application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "shortDescription": {
      "description": "A brief description (e.g. title) of the timeline",
      "type": "string",
      "maxLength": 256
    },
    "longDescription": {
      "description": "A longer description of the timeline",
      "type": "string"
    }
  },
  "required": ["shortDescription"]
}

Success Response A successful request will return status code 201 Created. The response body will return the ID of the created timeline formatted as JSON according to the schema below. The content-type of the response will be application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "description": "The ID of the created timeline",
      "type": "integer"
    },
  },
  "required": ["id"]
}

Error Response To be finalized, anything other than a 201 Created response code should be considered an error.

Sample Call Using curl:

curl -X POST -H "Content-Type: application/json" -d "{\"shortDescription\":\"My Timeline\"}" "https://timeline.chronicle.horizon.ac.uk/api/v1/timeline"

1.2.2 Create Timeline Access Token

Path /timeline/{timeline id}/token[/]

Method POST

Data Params The post body must conform to the schema below and have a content type of application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "secret": {
      "description": "The secret key",
      "type": "string",
      "maxLength": 64
    },
    "description": {
      "description": "A description of the access token",
      "type": "string",
      "maxLength": 256
    },
    "script": {
      "description": "The script to run when access using the token is requested",
      "type": "string"
    },
    "state": {
      "description": "Initial state attached to the access token",
      "type": "string"
    },
    "allowRead": {
      "description": "Allow access token to be used to read the timeline",
      "type": "boolean",
      "default": false
    },
    "allowReadEntries": {
      "description": "Allow access token to be used to read the timeline entries",
      "type": "boolean",
      "default": false
    },
    "allowEditEntries": {
      "description": "Allow access token to be used to edit the timeline entries",
      "type": "boolean",
      "default": false
    },
    "allowAddEntry": {
      "description": "Allow access token to be used to add an entry",
      "type": "boolean",
      "default": false
    },
    "allowClone": {
      "description": "Allow access token to be used to clone the timeline",
      "type": "boolean",
      "default": false
    }
  },
  "required": ["description", "script"]
}

Success Response A successful request will return status code 201 Created. The response body will return the created access token formatted as JSON according to the schema below. The content-type of the response will be application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "description": "The ID of the created access token",
      "type": "integer"
    },
    "secret" {
      "description": "The access token secret",
      "type": "string",
      "maxLength": 64
    }
  },
  "required": ["id", "secret"]
}

Error Response To be finalized, anything other than a 201 Created response code should be considered an error.

1.2.3 Read Timeline

Path /timeline/{timeline id}[/]

Method GET

Success Response A successful request will return status code 200 OK. The response body will return the ID of the created timeline formatted as JSON according to the schema below. The content-type of the response will be application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "description": "The timeline ID",
      "type": "integer"
    },
    "createdAt": {
      "description": "The date and time that the timeline was created at",
      "type": "string",
      "format": "date-time"
    },
    "shortDescription": {
      "description": "A brief description (e.g. title) of the timeline",
      "type": "string"
    },
    "longDescription": {
      "description": "A longer description of the timeline",
      "type": "string"
    },
    "entries": {
      "description": "The timeline entries",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "description": "The timeline entry ID",
            "type": "integer"
          },
          "createdAt": {
            "description": "The date and time that the entry was created at",
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "createdAt"
        ]
      }
    }
  },
  "required": [
    "id",
    "createdAt",
    "shortDescription",
    "entries"
  ]
}

Error Response To be finalized, anything other than a 200 OK response code should be considered an error.

Sample Call Using curl:

curl "https://timeline.chronicle.horizon.ac.uk/api/v1/timeline/1"

1.2.4 Clone Timeline

Path /timeline/{timeline id}/clone[/]

Method POST

Data Params The post body must be empty and have a content type of application/json.

Success Response A successful request will return status code 201 Created. The response body will return the ID of the created timeline formatted as JSON according to the schema below. The content-type of the response will be application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "description": "The ID of the created timeline",
      "type": "integer"
    },
  },
  "required": ["id"]
}

Error Response To be finalized, anything other than a 201 Created response code should be considered an error.

Sample Call Using curl:

curl -X POST -H "Content-Type: application/json" -d "" "https://timeline.chronicle.horizon.ac.uk/api/v1/timeline/1/clone"

1.2.5 Create Timeline Entry

Path /timeline/{timeline id}/entry[/]

Method POST

Data Params The post body must conform to the schema below and have a content type of application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "mimeType": {
      "description": "The MIME type of the content",
      "type": "string"
    },
    "content": {
      "description": "The entry content, base64 encoded",
      "type": "string",
      "contentEncoding": "base64"
    },
    "metadata": {
      "description": "Associated metadata in key/value pairs",
      "type": "array",
      "items" {
        "type": "object",
        "properties": {
          "key" {
            "description": "Metadata key",
            "type": "string",
            "maxLength": 256
          },
          "value" {
            "description": "Metadata value",
            "type": "string",
            "maxLength": 256
          }
        },
        "required": [
          "key",
          "value"
        ]
      }
    }
  },
  "required": [
    "mimeType",
    "content"
  ]
}

Success Response A successful request will return status code 201 Created. The response body will return the ID of the created timeline formatted as JSON according to the schema below. The content-type of the response will be application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "description": "The ID of the created timeline entry",
      "type": "integer"
    },
  }
  "required": ["id"]
}

Error Response To be finalized, anything other than a 201 Created response code should be considered an error.

Sample Call Using curl:

curl -X POST -H "Content-Type: application/json" -d "{\"mimeType\":\"text/plain\", \"content\":\"aGVsbG8gd29ybGQ=\", \"metadata\":[{\"key\":\"a\",\"value\":\"b\"}]}" "https://timeline.chronicle.horizon.ac.uk/api/v1/timeline/1/entry"

1.2.6 Create Timeline Entry (Chunked Upload)

Step One Creating an Entry

Path /timeline/{timeline id}/entry[/]

Method POST

Data Params The post body must conform to the schema below and have a content type of application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "mimeType": {
      "description": "The MIME type of the content",
      "type": "string"
    },
    "keepOpen": {
      "description": "Signals that content will be uploaded in chunks",
      "type": "boolean",
      "const": "true"
    },
    "metadata": {
      "description": "Associated metadata in key/value pairs",
      "type": "array",
      "items" {
        "type": "object",
        "properties": {
          "key" {
            "description": "Metadata key",
            "type": "string",
            "maxLength": 256
          },
          "value" {
            "description": "Metadata value",
            "type": "string",
            "maxLength": 256
          }
        },
        "required": [
          "key",
          "value"
        ]
      }
    }
  },
  "required": [
    "mimeType",
    "keepOpen"
  ]
}

Success Response A successful request will return status code 201 Created. The response body will return the ID of the created timeline formatted as JSON according to the schema below. The content-type of the response will be application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "description": "The ID of the created timeline entry",
      "type": "integer"
    },
  }
  "required": ["id"]
}

Error Response To be finalized, anything other than a 201 Created response code should be considered an error.

Sample Call Using curl:

curl -X POST -H "Content-Type: application/json" -d "{\"mimeType\":\"text/plain\", \"keepOpen\":true, \"metadata\":[{\"key\":\"a\",\"value\":\"b\"}]}" "https://timeline.chronicle.horizon.ac.uk/api/v1/timeline/1/entry"

Step Two Uploading Content

Path /timeline/{timeline id}/entry/{entry id}/put[/]

Method PUT

Data Params The post body must contain the data you wish to put into the entry. Where the content is placed in the entry can be controlled with a Content-Range header. For more details on the Content-Range headerheader refer to RFC 2616.

Success Response A successful request will return status code 200 Ok. The response body will be empty.

Error Response To be finalized, anything other than a 200 Ok response code should be considered an error.

Step Three Finalising Content

Path /timeline/{timeline id}/entry/{entry id}/close[/]

Method PUT

Success Response A successful request will return status code 200 Ok. The response body will be empty.

Error Response To be finalized, anything other than a 200 Ok response code should be considered an error.

1.2.7 Create Timeline Entry Access Token

Path /timeline/{timeline id}/entry/{entry id}/token[/]

Method POST

Data Params The post body must conform to the schema below and have a content type of application/json.

  {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "properties": {
      "secret": {
        "description": "The secret key",
        "type": "string",
        "maxLength": 64
      },
      "description": {
        "description": "A description of the access token",
        "type": "string",
        "maxLength": 256
      },
      "script": {
        "description": "The script to run when access using the token is requested",
        "type": "string"
      },
      "state": {
        "description": "Initial state attached to the access token",
        "type": "string"
      },
      "allowRead": {
        "description": "Allow access token to be used to read the entry",
        "type": "boolean",
        "default": false
      },
      "allowEdit": {
        "description": "Allow access token to be used to edit the entry",
        "type": "boolean",
        "default": false
      }
    },
    "required": ["description", "script"]
  }

Success Response A successful request will return status code 201 Created. The response body will return the ID of the created timeline formatted as JSON according to the schema below. The content-type of the response will be application/json.

  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "description": "The ID of the created access token",
      "type": "integer"
    },
    "secret" {
      "description": "The access token secret",
      "type": "string",
      "maxLength": 64
    }
  },
  "required": ["id", "secret"]
}

Error Response To be finalized, anything other than a 201 Created response code should be considered an error.

1.2.8 Read Timeline Entries

Path /timeline/{timeline id}/entry[/]

Method GET

Success Response A successful request will return status code 200 OK. The content-type of the response will be application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "id": {
        "description": "The timeline entry ID",
        "type": "integer"
      },
      "createdAt": {
        "description": "The date and time that the timeline entry was created at",
        "type": "string",
        "format": "date-time"
      },
      "mimeType": {
        "description": "The MIME type of the content",
        "type": "string"
      }
    },
    "required": [
      "id",
      "createdAt",
      "mimeType"
    ]
  }
}

Error Response To be finalized, anything other than a 200 OK response code should be considered an error.

Sample Call Using curl:

curl "https://timeline.chronicle.horizon.ac.uk/api/v1/timeline/1/entry"

1.2.9 Read Timeline Entry

Path /timeline/{timeline id}/entry/{entry id}[/]

Method GET

Success Response A successful request will return status code 200 OK. The content-type of the response will be application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "id": {
      "description": "The timeline entry ID",
      "type": "integer"
    },
    "createdAt": {
      "description": "The date and time that the timeline entry was created at",
      "type": "string",
      "format": "date-time"
    },
    "mimeType": {
      "description": "The MIME type of the content",
      "type": "string"
    },
    "metadata": {
      "description": "Associated metadata in key/value pairs",
      "type": "array",
      "items" {
        "type": "object",
        "properties": {
          "key" {
            "description": "Metadata key",
            "type": "string",
            "maxLength": 256
          },
          "value" {
            "description": "Metadata value",
            "type": "string",
            "maxLength": 256
          }
        },
        "required": [
          "key",
          "value"
        ]
      }
    }
  },
  "required": [
    "id",
    "createdAt",
    "mimeType",
    "metadata"
  ]
}

Error Response To be finalized, anything other than a 200 OK response code should be considered an error.

Sample Call Using curl:

curl "https://timeline.chronicle.horizon.ac.uk/api/v1/timeline/1/entry/1"

1.2.10 Read Timeline Entry Content

Path /timeline/{timeline id}/entry/{entry id}/content[/]

Method GET

Success Response A successful request will return status code 200 OK. The content-type of the response will be the MIME type of the entry content, the response body will contain the content.

Error Response To be finalized, anything other than a 200 OK response code should be considered an error.

Sample Call Using curl:

curl "https://timeline.chronicle.horizon.ac.uk/api/v1/timeline/1/entry/1/content"

1.2.11 Update Timeline Entry

Path /timeline/{timeline id}/entry/{entry id}[/]

Method PUT

Data Params The post body must conform to the schema below and have a content type of application/json.

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "metadata": {
      "description": "Associated metadata in key/value pairs",
      "type": "array",
      "items" {
        "type": "object",
        "properties": {
          "key" {
            "description": "Metadata key",
            "type": "string",
            "maxLength": 256
          },
          "value" {
            "description": "Metadata value",
            "type": "string",
            "maxLength": 256
          }
        },
        "required": [
          "key",
          "value"
        ]
      }
    }
  },
  "required": [
    "metadata"
  ]
}

Success Response A successful request will return status code 201 Created with an empty body.

Error Response To be finalized, anything other than a 201 Created response code should be considered an error.

Sample Call Using curl:

curl -X PUT -H "Content-Type: application/json" -d "{\"metadata\":[{\"key\":\"a\",\"value\":\"b\"}]}" "https://timeline.chronicle.horizon.ac.uk/api/v1/timeline/1/entry/1"

Notes

Appendices

A Document Revisions

Version v0.0.4

Version v0.0.3

Version v0.0.2

Version v0.0.1

Home | Terms & Conditions | Privacy Policy | Cookie Policy