Import design docs (RFCs)

This commit is contained in:
Dustin J. Mitchell 2022-03-05 23:17:51 +00:00 committed by Tomas Babej
parent 07493d5fa6
commit 8747cc9f94
15 changed files with 3259 additions and 0 deletions

444
docs/rfcs/client.md Normal file
View 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