Creating a Taskserver Client

A Taskserver client is a todo-list manager. It may be as simple as a program that captures a single task, as complex as Taskwarrior, or anything in between. It can be a mobile client, a web application, or any other type of program.

This document describes how such a client would interact with the server.

A client to the Taskserver is a program that manages a task list, and wishes to exchange data with the server so that the task list may be shared.

In order to do this, a client must store tasks locally, upload local changes, download remote changes, and apply remote changes to the local tasks.

The client must consider that there may be no network connectivity, or no desire by the user to synchronize.

The client will need proper credentials to talk to the server.

Requirements

In this document, we adopt the convention discussed in Section 1.3.2 of RFC1122 of using the capitalized words MUST, REQUIRED, SHOULD, RECOMMENDED, MAY, and OPTIONAL to define the significance of each particular requirement specified in this document.

In brief: "MUST" (or "REQUIRED") means that the item is an absolute requirement of the specification; "SHOULD" (or "RECOMMENDED") means there may exist valid reasons for ignoring this item, but the full implications should be understood before doing so; and "MAY" (or "OPTIONAL") means that this item is optional, and may be omitted without careful consideration.

Taskserver Account

A Taskserver account must be created. This process creates a storage area, and generates the necessary credentials.

Credentials

A Taskserver client needs the following credentials in order to communicate with a server:

  • Server address and port
  • Organization name
  • User name
  • Password
  • Certificate
  • Key

The server address and port are the network location of the server. An example of this value is:

foo.example.com:53589

In addition to a DNS name, this can be an IPv4 or IPv6 address.

The organization name is an arbitrary grouping, and is typically 'PUBLIC', reflecting the individual nature of server accounts. Future capabilities will provide functionality that support groups of users, called an organization.

The user name is the full name. This will be the name used to identify other users in an organization, in a future release. Example 'John Doe'.

The password is a text string generated by the server at account creation time. It should be considered a secret.

The certificate is an X.509 PEM file generated by the server at account creation time. This is used for authentication. It should be considered a secret.

The key is an X.509 PEM file generated by the server at account creation time. This is used for encryption. It should be considered a secret.

These credentials need to be stored on the client, and used during the sync operation.

Description of a Taskserver Client

This section describes how a client might behave in order to facilitate integration with the Taskserver.

Encryption

The Taskserver only communicates using encryption. Therefore all user data is encrypted while in transit. The Taskserver currently uses GnuTLS to support this encryption, and therefore supports the following protocols:

  • SSL 3.0
  • TLS 1.0
  • TLS 1.1
  • TLS 1.2

The client may use any library that supports the above.

Configuration

The client needs to store configuration, which matches the credentials needed for Taskserver communication. See section 2.1 "Credentials".

The credentials may not be modified by the user without losing server access.

The server:port data may need to be changed automatically following a redirect response from the server. See section 5 "Server Errors".

Local Storage

The client needs to store task data locally. The client will need to be able to find tasks by their UUID and overwrite them. Uploaded and downloaded task changes will use the Taskwarrior Data Interchange Format.

Local Changes

Whenever local data is modified, that change MUST be synced with the server. But this does not have to occur immediately, in fact the client SHOULD NOT assume connectivity at any time.

A client SHOULD NOT also assume that the server is available. If the server is not available, the local changes should be retained, and the sync operation repeated later.

Ideally the client will give the user full control over sync operations. Automatically syncing after all local modifications is not recommended. If a client performs too many sync operations, the server MAY revoke the certificate.

Effectively, the client should maintain a separate list of tasks changed since the last successful sync operation.

Note that tasks have a "modified" attribute, which should be updated whenever a change is made. This attribute contributes to conflict resolution on the server.

Remote Changes

When a server sends remote changes to a client, in the response to a sync request, the changes have already been merged by the server, and therefore the client should simply store them intact.

Based on the UUID in the task, the client can determine whether a task is new (and should be added to the local list of tasks), or whether it represents a modification (and should overwrite it's existing entry).

The client MUST NOT perform any merges.

Sync Key

Whenever a sync is performed, the server responds by sending a sync key and any remote changes. The sync key is important, and should be included in the next sync request. The client is REQUIRED to store the sync key in every server response message.

If a client omits the sync key in a sync message, the response will be a complete set of all tasks and modifications.

Data Integrity

Although a task is guaranteed to contain at least 'entry', 'description' and 'uuid' attributes, it may also contain other known fields, and unknown user-defined fields. An example might be an attribute named 'estimate'.

If a task is received via sync that contains an attribute named 'estimate', then a client has the responsibility of preserving the attribute intact. If that data is shown, then it is assumed to be of type 'string', which is the format used by JSON for all values.

Conversely, if a client wishes to add a custom attribute, it is guaranteed that the server and other clients will preserve that attribute.

Using this rule, two clients of differing capabilities can exchange data and still maintain custom attributes.

This is a requirement. Any client that does not obey this requirement is broken.

Synchronizing

Synchronizing with the Taskserver consists of a single transaction. Once an encrypted connection is made with the server, the client MUST compose a sync request message. This message includes credentials and local changes. The response message contains status and remote changes, which MUST be stored locally.

Establishing Encrypted Connection

All communication with the Taskserver is encrypted using the certificate and key provided to each user. Using the 'server' configuration setting, establish a connection.

Sync Request

See sync request message. A sync request MUST contain a sync key if one was provided by a previous sync. A sync request MUST contain a list of modified tasks, in JSON format (see Task JSON), if local modifications have been made.

Sync Response

A sync response WILL contain a 'code' and 'status' header variable, WILL contain a sync key in the payload, and MAY contain a list of tasks from the server in JSON format (see Task JSON).

Server Messages

There are cases when the server needs to inform the user of some condition. This may be anticipated server downtime, for example. The response message is typically not present, but may be present in the header, containing a string:

...
message: Scheduled maintenance 2013-07-14 08:00UTC for 10 minutes.
...

If such a message is returned by the server, it SHOULD be made available to the user. This is a recommendation, not a requirement.

Server Errors

The server may generate many errors (See Protocol), but the following is a list of the ones most in need of special handling:

  • 200 Success
  • 201 No change
  • 301 Redirect
  • 430 Access denied
  • 431 Account suspended
  • 432 Account terminated
  • 5xx Error

The 200 indicates success, and that a change was recorded. The 201 indicates success but no changes were necessary. The 301 is a redirect message indicating that the client MUST re-request from a new server. The 43x series messages are account-related. Any 5xx series code is a server error of some kind. All errors consist of a code and a status message:

code: 200
status: Success

Examples

Here are examples of properly formatted request and response messages. Note that the messages are indented for clarity in this document, but is not the case in a properly formatted message. Also note that newline characters U+000D are not shown, but are implied by the separate lines. Because some messages have trailing newline characters, the text is delimited by the 'cut' markers:

foo

The example above illustrates text consisting of:

U+0066   f
U+006F   o
U+006F   o
U+000D   newline
U+000D   newline

Note that these values are left unspecified, but should be clear from the context, and the message format spec:

<size>
<organization>
<user>
<password>

First Sync

The first time a client syncs, there is (perhaps) no data to upload, and no sync key from a previous sync.

<size>type: sync
org: <organization>
user: <user>
key: <password>
client: task 2.3.0
protocol: v1

Note the double newline character separating header from payload, with an empty payload.

Request: Sync No Data

Ordinarily when a client syncs, there is a sync key from the previous sync response to send. This example shows a sync with no local changes, but a sync key from a previous sync.

<size>type: sync
org: <organization>
user: <user>
key: <password>
client: task 2.3.0
protocol: v1

2e4685f8-34bc-4f9b-b7ed-399388e182e1

Request: Sync Data

This sync request shows a sync key from the previous sync, and a locally modified task.

<size>type: sync
org: <organization>
user: <user>
key: <password>
client: task 2.3.0
protocol: v1

2e4685f8-34bc-4f9b-b7ed-399388e182e1
{"description":"An example","uuid":"8ad2e3db-914d-4832-b0e6-72fa04f6e331",...}

Response: No Data

If a sync results in no downloads to the client, the response will look like this.

<size>type: response
client: taskd 1.0.0
protocol: v1
code: 200
status: Ok

45da7110-1bcc-4318-d33e-12267a774e0f

Note that there is a sync key which must be stored and used in the next sync request, but there are no remote changes to store.

Response: Remote Data

This shows a sync response providing a new sync key, and a remote change to two tasks.

<size>type: response
client: taskd 1.0.0
protocol: v1
code: 200
status: Ok

45da7110-1bcc-4318-d33e-12267a774e0f
{"description":"Test data","uuid":"8ad2e3db-914d-4832-b0e6-72fa04f6e331",...}
{"description":"Test data2","uuid":"3b6218f9-726a-44fc-aa63-889ff52be442",...}

Note that the sync key must be stored for the next sync request.

Note that the two changed tasks must be stored locally, and if the UUID in the tasks matches local tasks, then the local tasks must be overwritten.

Response: Error

<size>type: response
client: taskd 1.0.0
protocol: v1
code: 431
status: Account suspended

Note the double newline character separating header from payload, with an empty payload.

Response: Relocate

<size>type: response
client: taskd 1.0.0
protocol: v1
code: 301
status: Redirect
info: 

Note the 'info' field will contain a ':' string that should be used for all future sync requests. This indicates that a user account was moved to another server.

Note the double newline character separating header from payload, with an empty payload.

Response: Message

Occasionally the server will need to convey a message, and will include an additional header variable containing that message.

The server protocol states that the message SHOULD be shown to the user. This message will be used for system event messages, used rarely, and never used for advertising or promotion.

<size>type: response
client: taskd 1.0.0
protocol: v1
code: 200
status: Ok
message: Scheduled maintenance 2013-07-14 08:00UTC for 10 minutes.

45da7110-1bcc-4318-d33e-12267a774e0f

Note that the same message will likely be included in consecutive responses.

Reference Implementation

The Taskserver 1.1.0 codebase contains a reference implementation of an SSL/TLS client and server program, which communicate text strings.

taskd.git/src/tls/Makefile             # To build the example
taskd.git/src/tls/README               # How to run the example
taskd.git/src/tls/TLSClient.cpp        # TLS client code
taskd.git/src/tls/TLSClient.h
taskd.git/src/tls/TLSServer.cpp        # TLS Server code
taskd.git/src/tls/TLSServer.h
taskd.git/src/tls/c.cpp                # Client program
taskd.git/src/tls/s.cpp                # Server program
taskd.git/src/tls/text.cpp             # Text manipulation
taskd.git/src/tls/text.h               # Text manipulation

The Taskwarrior codebase, version 2.4.0, is the reference implementation.

task.git/src/TLSClient.cpp             # TLS client code
task.git/src/TLSClient.h
task.git/src/commands/CmdSync.cpp      # Sync implementation
task.git/src/commands/CmdSync.h