mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Import design docs (RFCs)
This commit is contained in:
parent
07493d5fa6
commit
8747cc9f94
15 changed files with 3259 additions and 0 deletions
444
docs/rfcs/client.md
Normal file
444
docs/rfcs/client.md
Normal file
|
@ -0,0 +1,444 @@
|
|||
---
|
||||
title: "Taskwarrior - Creating a Taskserver Client"
|
||||
---
|
||||
|
||||
|
||||
# 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](https://tools.ietf.org/html/rfc1122#page-16) 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](https://gnutls.org) 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](/docs/design/task).
|
||||
|
||||
|
||||
## 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](/docs/design/request). 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](/docs/design/request). 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](/docs/design/task)), 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](/docs/design/task)).
|
||||
|
||||
|
||||
## 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](/docs/design/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](/docs/design/request) 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](/docs/design/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
|
Loading…
Add table
Add a link
Reference in a new issue