THIS IS UNFINISHED FOR NOW. To help finish it, feel free to meail liw@liw.fi with questions if something's unclear to you.

Introduction

Distix is a ticketing system. It's different from most, though not unique:

  • It's purely email based. All tickets are reported via email and all discussion related to them is done via email. Normal email threading mechanisms (headers References and In-Reply-To) are used to check which ticket an email belongs so. Distix itself does not send email, and users to not need to mention ticket identifiers. In face, mostly users to not need to even know a ticketing system exists.

  • Tickets are stored in a git repository. Since git is a distribued version control system, this makes distix be a distributed ticketing system.

  • Tickets have some metadata (e.g., open/closed status), which is manipulated via a command line program. The metadata is also stored in git.

  • A set of static HTML pages may be generated from a distix ticket repository. The HTML may be published to allow people to read tickets more easily.

Distix is typically set up so that it has its own, hidden email address, and that address is subscribed to a mailing list. User then send email to the list, which results in the email reaching distix and being imported to a distix ticket repository. Responses to user emails would keep the mailing list in the cc header, meaning the responses also get imported by distix.

Architectural overview

All data about tickets are stored in a git repository. Emails are stored in a Maildir per ticket, each email in its own file. Metadata is stored in a YAML file as key/value pairs. This structure makes it very easy to avoid git merge conflicts, and also to resolve any conflicts that do happen.

The distix command line program manipulates the git repository directly, including making commits. Distix admins only need to use git directly to pus h/pull changes, if there are more than one instance of the repository.

The distix ticket repository is laid out like this:

repo/
    repo.yaml               metadata about the repository
    tickets/
        ticket_id/          a diretory for each ticket
            ticket.yaml     metadata about the ticket
            Maildir/        where all ticket emails are stored

Ticket ids

New tickets are assigned a random id, using UUID4. This makes collisions super-unlikely when tickets are created in different instances of the ticket repository and then merged.

However, since long hexadecimals ids are cumbersome for humans, the UI accepts any unique prefix of a ticket id, and additionally allows expressing it using PGP code words. The prefixes or code words are translated into full ids at the UI extranal boundary, and only full ids are used internally.

Metadata

Metadata is expressed using key, value pairs. It is OK for there to be multiple instances of a key to cover use cases such as CVE number related to a ticket. If it makes semantic sense to only have at most one instance of a key, then the code needs to remove all other instances when adding a key, value pair, or when merging changes.

Metadata is stored in a YAML file using the obvious form:

key1:
- value1
key2:
- value2
- value3

Any string value that can be expressed in YAML is OK.

An interactive management web interface?

  • a service that provides a frontend and an api backend (with authn) for doing what command line app does, intended to be easier to use interactively and for writing ones own automation

This chapter discusses a possible future change to distix, and how it might be implemented.

Motivation

The distix command line client works, but can be a bit tedious to use. As an example, closing tickets requires iterting over "list ticket", "review the discussion of a ticket", and "close ticket" commands, with some copy-pasting or typing of ticket ids. Doing that kind of thing using a UI better suited for it would be good. The obvious choice is a web application.

In addition an organisation might want to build some automation of its own around the ticketing system to handle parts of its ticket managing workflow better. This can be done by manipulating the ticket git repository directly, but may be easier to using an HTTP API.

Both of these can be implemented by adding a "distix web API" or "distix service" on top of the git repository, and a frontend to implement an interactive web application using the API.

Sketch of the API

I like RESTful APIs. This is a sketch for one which is centered about the main concepts in a distix ticket repository.

Authentication

Authentication and authorization will initially be quite simple and implemented by the distix service itself. Later, an identity provider may be added, but those tend to be big, ugly, difficult pieces of software and distix needs to be really simple for now. The client software (or user via the client software) authenticates to the service, using a simple username/password combination via HTTP Basic Auth. In response, the client will get a bearer token, which it will add to all other API requests.

The bearer token will be a signed JWT token.

API calls

endpoint description
POST /authn Authenticate using Basic Auth, get JWT bearer token.
GET /meta Get repository metadata.
PUT /meta Update (all of) repository metadata.
GET /tickets Get list of ticket ids.
GET /tickets/ID/meta Get a ticket's metadata.
PUT /tickets/ID/meta Update a ticket's metadata.
GET /tickets/ID/msgs Get list of a ticket's emails.
GET /tickets/ID/msgs/MSGID Get an email.

Note that only metadata may be changed. New tickets may not be reported, nor can new messages be added. It's not possible to delete anything. The API will be grown as needed, however, so these limitations may be lifted if there's actual use cases.

Metadata in the API is expressed using JSON to be more convenient for most web programmers. Messages are expressed using RFC2822 (details to be fixed). Standard HTTP methods and status codes are used.

Message ids for emails in a ticket refer to the basename of messages in the Maildir in the ticket repository, not the Message-Id header.

Sketch of the web UI

Personas for use cases

A user is anyone who wants to look at tickets. They do not need to log in.

An admin is someone who manages the ticket repository, and closes tickets that have been handled and need no further attention anymore. Admins need to be logged in to make any changes.

Use case: User reviews open tickets

As a user, I want to review what tickets are currently open, in order to not report a duplicate ticket:

  1. I open the distix instance's website, which I've found from a project's or company's normal website.
  2. I see a list of open tickets, with ticket id, latest modificaion date, and a title (short summary of ticket) for each ticket.
  3. I read the list of tickets, and open any ticket (by clicking on ticket id or summary) to read all messages about the ticket.

Use case: Admin closes tickets

As an admin, I want to close a ticket that needs no further attention, in order to remove it from the list of open tickets:

  1. I open the list of open tickets.
  2. I review tickets (opening them as necessary), to find a ticket that can be closed.
  3. In the ticket view, I click on the "close ticket" button or other user interface element.
  4. If I'm not yet logged in, the service requests I do log in.
  5. I log in.
  6. The service marks the ticket as closed.
  7. If I to back to the list of open tickets, the ticket I just closed isn't there.