Tent v0.3-WIP Documentation

Note well: There is no guarantee of API stability until Tent v1.0.

Please contribute by making Pull Requests and Issues on the GitHub repository.

Posts

Posts are the core of the Tent Protocol. Each piece of data in Tent, from a status message to application configuration, is stored in a post.

Posts are JSON, and consist of three logical components: metadata, content, and binary attachments.

Entity

Every post has an entity (set by the server on creation). The entity is the Entity URL that identifies the publisher of the post. If the entity changed URLs since the post was published, there will be an additional original_entity member that records the Entity URL that originally published the post before the change.

ID

The post id is generated by the server, and is a entity-local unique identifier. The combination of entity and id is used to retrieve a post.

Type

Each post has a type. The type is a URI that identifies the schema and semantics associated with a post. Types are HTTPS URIs and must have a fragment. Currently the URI is not used as a URL, but in the future it will be the location of the machine-readable post schema, so it must point at an internet-routable address that the creator has control over. The fragment is used to provide additional information and/or semantics, but does not indicate a different data schema. To create a new type, just start using it.

Examples

https://tent.io/types/status/v0#reply
https://tent.io/types/delete/v0#

Content

The content member of the POST JSON is where “data” lives. It contains an arbitrary JSON object that may contain all valid JSON types with the exception of floating point numbers. This object is expected to follow a consistent schema that is the same across all posts of the same type.

Versions

Each post has one or more versions. Versions are identified by the version.id member. The version ID is the hex-encoded first 256 bits of a SHA-512 of the canonical post JSON calculated by the server. Post versions list zero or more “parent versions”. Each version created after the first version of a post must reference at least one previous version of the same post. These parents form a directed acyclic graph of the history of a post and may also refer to other posts including posts published by other entities.

The version may also optionally have a version.message, this may be used as the version “commit message”.

Timestamps

Posts have four timestamps associated with them. Timestamps are stored as the number of milliseconds since the Unix epoch (not counting leap seconds), and do not have timezone information. The first, published_at may be set by the application when the first version of a post is created. It does not change in subsequent versions.

The second timestamp, received_at is set when a server receives the post. received_at is only exposed to applications, not other entities, and is set by the server receiving the post, not the publisher.

Each version also has version.received_at and version.published_at with the same semantics, but change for each version instead of each post.

Permissions

Each post version has a set of permissions associated with it. These permissions specify entities and groups of entities that can see the post. If the permissions.public flag is set to true, everyone can see the post. If false, only the entities listed in the permissions.entities and members of the groups listed in permissions.groups can see the post.

Permissions vary on a per-version basis, and the most recent version that the requester is permitted to see is shown.

Mentions

Mentions link to a specific entity, post, or version. A cross between the CC field of an email and a hyperlink, mentions allow posts to be linked and referenced. When a post is published that mentions an entity and she is permitted access, a notification is sent to her automatically. The posts feed allows rich querying based on mentions, and the list of posts that mention a given post can be retrieved easily.

Mentions have a mentions.public flag that may optionally be set to false, hiding the mention from all but the target entity. Unlike public mentions, private mentions may be added to existing post versions.

Refs

Refs reference another post or version. Typically used to embed content in a post, they allow apps to fetch posts and referenced posts in the same request.

Attachments

Attachments are files that are attached to posts. When a post is created, a multipart request that includes files can be made. These files are attached to the post and listed in the attachments array. They may also be copied from existing posts and versions by copying the object from the attachments array into the new post. Attachments are not copied to new versions by default.

A digest of each uploaded attachment is calculated and used as the unique identifier. This digest is the hex-encoded first 256 bits of a SHA-512 of the attachment data, and may also be used to verify that the attachment was not corrupted during download or upload.

Multiple attachments with the same name may be uploaded, as long as their content_type differs. This allows for type negotiation via the Accept request header using the post_attachment endpoint.

Post Schema

Property Server App Type Description
id Required Import String The unique identifier of the post.
entity Required Import String The entity that published the post.
original_entity Optional Import String Original entity of post. Only present if entity moved.
published_at Required Optional Integer The date/time when the post was published in milliseconds since Unix epoch.
received_at Optional Import Integer The date/time when the post was received from the publishing server in milliseconds since Unix epoch.
version Required Optional Object Post Version object.
version.id Required Import String Post version identifier.
version.published_at Required Optional Integer The date/time when post version was published in milliseconds since Unix epoch.
version.received_at Optional Import Integer The date/time when the post version was received from the publishing server in milliseconds since Unix epoch.
version.parents Optional Optional Array of Objects Parent versions.
version.parents[].version Required Required String Post version identifier.
version.parents[].entity Optional Optional String Entity of parent post. Should only be present if different from the containing post entity.
version.parents[].original_entity Optional Import String Original entity of parent post. Should only be present if the value of entity changed.
version.parents[].post Optional Optional String Identifier of parent post. Should only be present if different from the containing post identifier.
version.message Optional Optional String Optional message describing changes made.
mentions Optional Optional Array of Objects The entities and posts that this post mentions.
mentions[].entity Optional Optional String The entity that is being mentioned.
mentions[].original_entity Optional Import String The original entity that is being mentioned. Only present if the entity changed.
mentions[].post Optional Optional String The unique identifier of the mentioned post.
mentions[].version Optional Optional String The version identifier of the mentioned post.
mentions[].type Optional Optional String Type URI of referenced post. Should be set unless the mentioned post is private and the mention is public.
mentions[].public Optional Optional Boolean Indicates whether mention is public or private. Default is true.
refs Optional Optional Array of Objects The posts that this post references.
refs[].entity Optional Optional String The publishing entity of the referenced post.
refs[].original_entity Optional Import String The original publishing entity of the referenced post. Only present if the entity changed.
refs[].post Required Required String The unique identfier of the referenced post.
refs[].version Optional Optional String The version identifier of the referenced post.
refs[].type Optional Optional String Type URI of referenced post. Should be set unless the referenced post is private.
licenses Optional Optional Array of Objects The licenses that the post is released under.
licenses[].url Required Required String URL of the license.
type Required Required String The post type URI.
content Optional Optional Object The post content.
attachments Optional Optional Array of Objects Attachments to the post.
attachments[].category Required Required String The category of the attachment.
attachments[].content_type Required Required String The media type of the attachment, in the same format as the Content-Type HTTP header.
attachments[].name Required Required String The name of the attachment. The name and media type combination must be unique to the post version.
attachments[].digest Required Import String Hex-encoded first 256 bits of the SHA-512 hash of the attachment.
attachments[].size Required Import Integer The size in bytes of the attachment.
app Optional Import Object The application that published the post.
app.id Optional Import String Identifier of the post containing the details about the app that created this post.
app.name Optional Import String The human readable name of the application.
app.url Optional Import String The URL of the application.
permissions Optional Optional Object The permissions that apply to the post. Should be omitted if public member is true.
permissions.public Required Optional Boolean Indicates whether the post is public, public posts have no access restrictions.
permissions.groups Optional Optional Array of Objects The groups that are permitted to see the post.
permissions.groups[].post Required Required String Post identifier of the group.
permissions.entities Optional Optional Array of Strings The entities that are permitted to see the post.

Canonical Post JSON

The canonical post JSON format provides meaningful and repeatable hashes of JSON-encoded posts.

The grammar for canonical JSON is a subset of the grammar at json.org:

object:
    {}
    { members }
 members:
   pair
   pair , members
pair:
   string : value
array:
   []
   [ elements ]
elements:
   value
   value , elements
value:
   string
   number
   object
   array
   true
   false
   null
string:
   ""
   " chars "
chars:
   char
   char chars
char:
   any byte except hex 22 (") or hex 5C (\)
   \\
   \"
number:
   int
int:
   digit
   digit1-9 digits
   - digit1-9
   - digit1-9 digits
digits:
   digit
   digit digits
  • Floating point numbers are not allowed.
  • Leading zeros and “minus zero” are not allowed.
  • All object keys must be quoted, and must appear in sorted order.
  • All whitespace is eliminated.
  • Trailing commas in members and elements are not allowed.
  • Only one ‘escape’ sequence is defined for strings, and it is only used for quote and backslash.
  • The permissions, app.id, received_at, version.received_at and version.id members are removed.
  • Elements of the mentions array with the public member set to false are removed.
  • All original_entity members (in the post object as well as mentions, refs, and version.parents array elements) are removed and their sibling entity members values are replaced with the original_entity value.
  • Empty members are removed. The members that may be empty are app, attachments, mentions, refs, content, licenses, version.parents, version.message, and version.
  • Optional members that contain redundant data are removed. Currently this is defined as the post and entity members of a version.parents, mentions, and refs array element when they refer to the identifier or entity of the post that contains them.

Based on a spec from the OLPC wiki.