TaskChampion

repository·main·Indexed 41 days ago

https://github.com/gothenburgbitfactory/taskchampion

A task storage and synchronization engine that powers Taskwarrior, providing Rust and C APIs for managing task replicas. It defines a formal specification for task synchronization protocols, including support for AEAD encryption (CHACHA20_POLY1305), snapshot management to reduce storage bloat, and a replica-based storage model using transaction-protected storage engines.

Tokens
21.4K
Snippets
49
Records
110
Agent score
51%

What's inside TaskChampion

  1. What is TaskChampion?

    main
    TaskChampion is a library that implements the task storage and synchronization logic used by Taskwarrior. It provides both Rust and C APIs, enabling developers to build applications that maintain and manipulate their own task replicas. It also defines a formal specification for tasks and synchronization protocols, which allows for alternative implementations of task servers or replicas to interoperate.
  2. Overview of TaskChampion

    main
    TaskChampion provides the task storage and synchronization logic used by Taskwarrior. It is designed to allow any application to maintain and manipulate its own replica of tasks. It provides both Rust and C APIs and includes a formal specification for tasks and synchronization protocols, which enables developers to build alternative implementations of task replicas or task servers.
  3. What is a TaskChampion Replica?

    main
    A Replica is the core abstraction in TaskChampion representing a local copy of a user's task data. Multiple replicas (e.g., on a laptop and a phone) can exist simultaneously and synchronize with one another to maintain consistency. You interact with the task database through the Replica type.
  4. Understand the Server-Replica Protocol

    main

    The Server-Replica Protocol is an abstract request/response transaction model used to synchronize task histories between clients (replicas) and a server.

    Core Concepts

    • Clients: Any replica accessing the same task history is considered a client. Multiple clients can replicate a single task history.
    • Server: Responsible for storing the task history as a branch-free sequence of versions and storing the latest snapshot. To the server, both versions and snapshots are opaque byte sequences.
    • Version Invariant: The protocol enforces a single chain of versions. Every version must have no more than one parent and one child, and exactly one version in the chain may have zero parents (the root) and exactly one version may have zero children (the tip).
  5. Read data from the Task Database

    main

    The Task Database provides read access to data within the replica's storage via methods on the Task Database struct.

    Note on Consistency: Each read operation is executed within its own transaction. Consequently, data may not be perfectly consistent between two separate read operations. For TaskChampion's typical use cases, this behavior is acceptable.

  6. Interoperability with Taskwarrior

    main
    TaskChampion is the core engine behind Taskwarrior (since version 3.0). Because TaskChampion provides a standardized specification for tasks and synchronization, you can use it to build third-party applications that interoperate with Taskwarrior. This interoperability can happen either by sharing the same task replica or by using the synchronization protocol.
  7. Synchronize Replicas with a Server

    main

    Synchronization is performed by a Replica against a server. To set up synchronization:

    1. Define a server using ServerConfig.
    2. Convert the configuration into a server instance using .into_server().await?.
    3. Call replica.sync(&mut server, force_sync).await? to perform the synchronization.
  8. Understand TaskChampion synchronization and replicas

    main

    TaskChampion supports synchronization of replicas that contain the same set of tasks.

    Key concepts:

    • Replica: A local instance of a task list. Replicas can perform all operations locally without an active connection to a sync server.
    • Synchronization: The process of sharing local operations between replicas once they connect to a sync server. This allows users to maintain and update the same task list across multiple devices without requiring a constant internet connection.
  9. How encryption and key derivation work in TaskChampion

    main

    TaskChampion uses an encryption secret of arbitrary length provided in the client configuration to protect data sent to the server (specifically versions and snapshots).

    Key Derivation The client derives a 32-byte encryption key from your secret using:

    • Algorithm: PBKDF2 with HMAC-SHA256
    • Iterations: 600,000
    • Salt: Implementation-dependent (varies by protocol context)

    Encryption Algorithm Data is encrypted using AEAD with the CHACHA20_POLY1305 algorithm. It is critical that a random nonce is generated for every operation, as reusing a nonce with the same key compromises security.

    Scope Encryption is applied to all data sent from the local host to the server. It is not used for local (on-disk) synchronization.

  10. The structure of encrypted byte-streams

    main

    When data is encrypted and prepared for transmission, it follows a specific byte-stream format. This format allows the client to identify the data version and the nonce required for decryption.

    The byte-stream structure is:

    OffsetFieldSizeDescription
    0version1 byteFormat version (currently always 1)
    1nonce12 bytesThe encryption nonce
    13ciphertextRemainingThe concatenated ciphertext and authentication tag

    Note: The ciphertext field follows the pattern used in BoringSSL's EVP_AEAD_CTX_seal, where the ciphertext and tags are concatenated into a single bytestring.

  11. How the TaskChampion synchronization model works

    main

    TaskChampion uses a synchronization model based on Operational Transformation (OT) to manage task data across disconnected replicas.

    Core Principles

    • Disconnected Replicas: Replicas never communicate directly; they synchronize via a central server.
    • Opaque Server: The server does not see task data; it only handles opaque blobs and metadata to manage synchronization.
    • Linearization: Synchronization aims to bring all replicas to a single, linear sequence of operations and a shared state.
    • Rebase, Don't Merge: Unlike Git, operations cannot be merged. Instead, local operations must be "rebased" onto the latest server version using OT.
    • No Force Push: Once an operation is sent to the server, it cannot be changed.

    The Replica Invariant

    A replica maintains its current state by applying its sequence of un-synchronized operations to its last known "base version" (the last version successfully synchronized with the server).