Flatfish manual

© 2020-2024 Phil Brooke and Green Pike Ltd

1 Summary

Flatfish is a simple ticketing system.

Flatfish primarily works on tickets. These can be grouped into one or more independent silos. There is no mechanism to move tickets between silos.

Executables are available for Linux and Windows. Supported modes of usage are

A variant for the first two modes provides a per-user HTTP daemon. It exposes a simple web server to provide a nicer interface via a web browser. This is safe only on single-user machines.

2 Caution

Use of this software is permitted only with a valid licence issued by Green Pike Ltd (see the “Licence” section below). No other usage is permitted. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

3 Incompatible changes

4 Tickets

Each ticket comprises

4.1 Status

Flatfish has 9 fixed statuses:

Rather than offer customisable status values, use the following tag and property features.

4.2 Tags

Tags are simple strings. They are either present on a ticket or not. They have no special meaning to Flatfish: their interpretation is entirely for the end-users.

The strings are constrained to remove some whitespace and are compared case-insensitively.

It is recommended to avoid using particular characters in tags (as well as property names and values), such as: : ^ = ] [ ! ~ * (colon, circumflex, equals, square brackets, exclamation mark, tilde, asterisk). These are used in search terms and a few other places. However, Flatfish will not stop you doing this.

4.3 Properties

Properties are key-value pairs. By default, a ticket may have multiple properties with the same key, with some exceptions (see the special cases below).

Keys and values have the same constraints as tags.

Usage recommendation: use these to complement the ticket status. For example, other ticket systems may use an “Assigned” status. In Flatfish, use an “Assigned” property.

4.4 Entries

JSON: mostly obvious.

4.5 Attachments

A JSON entry should be in the ticket; then each attachment is stored as a separate file.

4.6 History

JSON: mostly obvious.

5 Special cases

5.1 Special case 1 — merged and duplicate (status and properties)

Setting a status Merged or Duplicate requires a second ticket to be involved.

Flatfish will not allow the Merged, Duplicate or Closed_Via properties to be changed via the normal property commands.

A later change to the first ticket’s status will remove the properties to ensure consistency.

5.2 Special case 2 — ticket relations (properties)

Tickets can refer to other tickets:

Setting one of these properties on a ticket will automatically add the relevant matching property on the second ticket.

5.3 Special case 3 — scheduling, deadlines and review dates (properties) and search dates

The properties Scheduled, Deadline and Review require a date to be provided. The permitted formats are

5.4 Special case 4 — auto-reopen, and repeating schedules, deadlines and reviews (properties)

When a ticket is closed, if it contains any of the properties Scheduled_Repeats, Deadline_Repeats or Review_Repeats, it will be automatically re-opened and its status set to Open. This does not apply for closure via Merged or Duplicate.

For each of the properties Scheduled_Repeats, Deadline_Repeats and Review_Repeats, if there is a matching property Scheduled, Deadline and Review respectively, the matching property will be updated according to the following rules:

In all cases, if a date is advanced to a non-existent date, e.g., 30 Feb, then it will be constrained to the earliest existing date.

(This is directly inspired by the similar repeats functionality in the Emacs org-mode.)

Note that negative values are not allowed and will result in an error.

5.5 Special case 5 — deadline warnings (properties)

The property “Deadline_Warning” is a natural number (a whole number, 0 or greater). This is interpreted as how many days ahead to warn about an impending deadline.

There is no default value: a ticket without a deadline warning will not be specially displayed.

6 Ticket selection

6.1 Search keys

Tickets are selected via a text string. This search key is interpreted as follows.

6.2 Inserting dates into search keys

If a property search is requested and the key is one of the built-in date properties

or it’s one of the pseudo-properties

or the key is given in the configuration lists

then the value can be given as listed in Special case 3 (above).

Note that for the purposes of searching, “opened” and “last_update” are reduced to just the date portion (the time part is discarded).

6.3 Example

“p:assigned:” matches any ticket with a property with a key containing “assigned”.

“p^assigned:” matches any ticket a property with a key starting “assigned”.

“p^assigned:=phil:” matches any ticket with a property with a key starting “assigned” and value exactly matching “phil”.

“s:oa: p^assigned=phil:” matches any ticket with status Open or Abandoned and a property with a key starting “assigned” and value exactly matching “phil”.

“p:reported:]2020-01-02:” means any ticket with a property with a key containing the substring “reported” and that property having a value greater-than-or-equal-to 2020-01-02 (as a string).

“p=scheduled:]2020-09-07:” means a ticket with a property with the exact key “scheduled” and greater-than-or-equal-to 2020-09-07.

“p=scheduled:].:” means anything scheduled for today or later.

“p=last_update:]-2w:” means anything with a last_update date within the last two weeks.

7 Ticket sorting

Tickets are sorted according to a sort rule, comprising a sequence of letters, in order.

7.1 Simple sort keys

Example: dh!l – sort by deadline, then scheduled, then reversed last-history.

7.2 Custom sort keys

Custom sort keys take a single letter, a property key and a colon (“:”).

If the property appears multiple times, the behaviour is undefined. The use of unique_property_keys is advised.

7.3 Vrules order

If a property key is listed in the vrules_pkv_values validation rules (below, see “Validation rules aka vrules”), the property can be given as a sort key, prefixed and suffixed with “:”.

Example: !vpriority:est – sort by priority (inverted); then earliest of deadline, scheduled or review; then status; then title.

Example: s!vpriority: – sort by status, then inverted priority.

7.4 Pseudo-properties

Ticket listings show the date/time a ticket was opened and its last update. These are derived from the history of the ticket and cannot be directly changed by the user.

They can, however, be accessed for ticket selection and sorting. They act as properties with keys “Opened” and “Last_update”. Similarly, the pseudo-property “Earliest” has the value of the earliest of deadline, scheduled or review (if any).

8 CSV and JSON export

If a search (in the web interface) returns at least one ticket, the “CSV” button will be enabled. This will download a CSV file of tickets, although not all data is included. Notably, the list of entries is not included for performance reasons.

The “JSON” button returns the same data as the “CSV” button, but as JSON.

Finally, the “JSON (full)” button returns the full tickets. This is potentially slow and will require a read-lock for a longer period. The other two options can be fulfilled from the internal search cache.

For JSON, “jq” is recommended for post-processing and selection of data.

9 Linux dependencies

The Linux version is a dynamically-linked executable. On a Debian system, you most likely need the libgnat-12 package.

Zip package downloads require the zip package.

Also see “Script dependencies for ff_squish and ff_squish_email” below.

10 Command-line operations on tickets

The flatfish (Linux) and flatfish.exe (Windows) binaries provide command-line operations on silos and tickets.

Command name Abbrev Arguments
new_ticket nt 1. title, 2. creation rule, 3. summary
import_ticket it 1. number, 2. title, 3. creation rule, 4. summary
clone_ticket cl 1. source number
set_title st 1. number, 2. title
set_summary su 1. number, 2. summary
set_status ss 1. number, 2. status, 3*. other number (for Merged and Duplicate)
add_tag ag 1. number, 2. tag
remove_tag rg 1. number, 2. tag
add_entry ae 1. number, 2. comment
copy_file af 1. number, 2. file name, 3. comment
remove_file rf 1. number, 2. file number
show_ticket dt 1. number
remove_entry re 1. number, 2. entry/comment number
send_email not implemented yet
add_property ap 1. number, 2. key, 3. value
change_property cp 1. number, 2. key, 3. old value, 4. new value
remove_property_kv rk 1. number, 2. key
remove_property_k rkv 1. number, 2. key, 3. value
select_tickets lt 1. search key, 2. sort order
list_ticket_numbers ltn 1. search key, 2. sort order
count_tickets ct 1. search key…
list_tags lg 1. search key
list_properties_k lk 1. search key
list_properties_kv lkv 1. search key, 2. key
show_activity da 1. from-time (cf. special case 3), 2. to-time (ditto), 3. user (or empty, , any), 4. search key (or empty, , all)
show_calendar dc 1. from-time (cf. special case 3), 2. to-time (ditto), 3. search key (or empty, *, all)
help h not implemented yet

The long forms of the commands can have - or _ added anywhere (they will be ignored).

quiet can be given before the operation to reduce the amount of output. For example:

flatfish quiet ct 's:*'

11 Command-line admin operations on tickets

The ffadmin (Linux) and ffadmin.exe (Windows) binaries provide admin-type command-line operations on silos and tickets.

Command name Abbrev Arguments
create_silo 1. directory name for new silo
add_silo as 1. silo’s directory name
remove_silo rs 1. silo’s directory name
set_active_silo sas 1. silo’s directory name
show_silos ds none
build_cache none
dump_t_cache_n none
acl_check_crule acc 1. crule name, 2. username …
acl_check_tickets act 1. selection rule, 2. username …
acl_check_user_tickets acu 1. username, 2. ticket number …

As for the flatfish binary, the long forms of the commands can have - or _ added anywhere (they will be ignored).

12 FFUWS personal web server

The ffuws (Linux) and ffuws.exe (Windows) binaries is the “Flatfish user web server”. This allows a user to run a light (and mostly dumb) web server which only servers Flatfish tickets. It has a helper excecutable that should be installed in the same directory (ffuws_goblin / ffuws_goblin.exe) or in the executable path for this process. If this is the Linux version, to further scripts, ff_squish and `ff_squish_email, should also be installed for FFUWS.

On start-up, FFUWS will open your default browser. This saves you typing in a PIN. You can request FFUWS to re-open the browser by pressing “o” in the terminal window.

12.1 Command line arguments

If given no arguments, the server will run on port 7046 using the active silo.

If given exactly two arguments, the first argument is treated as the port to listen on and the second is the path to the silo.

12.2 Writeback and closing FFUWS

Flatfish tries to improve performance (intended for poorly performing file servers) by delaying writeback to caches. Try to close down FFUWS cleanly so that it can carry out these writebacks fully. Press “q” in the terminal window.

12.3 Additional commands to FFUWS

As well as “q” for quitting and “o” to open a browser, the following keys are also available:

13 FFWeb multiuser web server

The ffweb Linux binary (not available for Windows) is a multiuser server. It is intended that Apache or NGINX are used as a proxy to provide SSL/TLS. An example Apache stanza (for example, inside a VirtualHost) is

ProxyPreserveHost on
RequestHeader set X-Forwarded-Proto https
ProxyPass         "/" "http://the.ffweb.server:7001/"
ProxyPassReverse  "/" "http://the.ffweb.server:7001/"

As for ffuws, ffuws_goblin should be installed in an executable path, along with the scripts ff_squish and ff_squish_email.

It must be given exactly two arguments: the first argument is treated as the port to listen on and the second is the path to the silo.

It is recommended to run the binary in a persistent console environment such as screen.

The same additional commands for FFUWS apply to the FFWeb console (except “o” is not available).

14 FFWeb and FFUWS “/exapi” API

FFWeb (and FFUWS) will also accept calls from scripts to create new tickets. These calls should pass a JSON object with the title, crule and summary fields. Optionally, a list of tags and properties can also be given with the same format as for crules. The target POST URL is /exapi/newticket (“external ticket creation”). The username is set to “-EXAPI-”.

For authentication purposes, the caller must pass also pass an auth_token. This should be included the list of ex_auth_tokens in the server configuration file. A new ticket number will be returned (“new_number”) if successful.

Similarly, there is a POST URL /exapi/update which accepts operations such as updating the summary, title or adding an entry. (Parameter document to follow!)

As it is anticipated these will often be unauthenticated uses, a future implementation will include rate limiting to prevent abusive flooding.

15 Script dependencies for ff_squish and ff_squish_email

The scripts are helpers for the Linux version of FFUWS and FFWeb. They carry out various actions such as listing the contents of ZIP and 7z archives and extracting some information from emails.

They require (at least) the following software:

16 FFTurnstile authentication setup

Prior to running FFWeb, you will need to create an authentication database.

All usage of FFTurnstile is on the current directory. Other commands are

FFTurnstile is case-sensitive throughout.

To reset/change an existing user’s password, delete the user (deluser) then add them again (adduser).

17 Substitutions

At the moment, only one substitution is available.

${ is escaped by $${. Although why you’d want to search for that….

Substitutions can be used in the following places currently:

They must not be used in ACLs as these are initially parsed in a context when no user is known.

18 Environment variables

This applies to both the Flatfish and FFUWS programs.

Flatfish expects to be able to its configuration in ${HOME}/flatfish.json for Linux and ${USERPROFILE}/flatfish.json for Windows. Similarly, it expects to be able to write temporary files into /tmp for Linux and ${USERPROFILE}/AppData/Local/Temp for Windows.

You can override these by setting the following environment variables:

The environment variable FF_MESSAGELEVEL can be set to

to override the verbosity of messaging.

19 Silo creation

A silo is created using

flatfish create_silo /path/to/my/new/silo

The resulting structure contains

20 Licence

Flatfish requires a licence file that can only be provided by Green Pike Ltd. Email apps@green-pike.co.uk (but not send email to vermin@green-pike.co.uk or you’ll be treated as a spammer forever.) to request a licence. We may or may not charge for licences, and a free licence at one time is no guarantee or promise of future free licences.

The licence file is searched for (in order)

21 Locking

Earlier versions of Flatfish locked the state and individual tickets separately. Current versions using a multiple-reader, single-writer scheme with writers having priority. Locking of the lock_state file which mediates this is handled through file system locks. 50 attempts are made to obtain this lock, over 5 to 20 seconds, after which an error is reported.

In the event of an operation failing, the exception handler should clean up locks as it exits.

22 Maintenance modes and blocking

Sometimes it is desirable to stop the user web server running, e.g., for maintenance such as updating cache files or software updates. A file block_ffuws in the meta directory will cause existing FFUWS and FFWeb servers to stop and new ones will refuse to start.

Similarly, a file readonly in the meta directory will refuse exclusive locks and any writing.

23 Silo Configuration

23.1 Configuration testing

The binary ff_test_config_file (ff_test_config_file.exe) takes exactly one command-line argument, a silo configuration file. This means you can check your changes are valid before installing them into a live silo.

23.2 YAML input

Flatfish does not currently read YAML format files. However, the configuration files may be easier to work with using YAML. A standard Python3 installation can trivially convert between YAML and JSON.

23.2.1 Convert existing JSON config to YAML

Using Python3:

import yaml
import json
with open("config.json") as f:
    s1=f.read()

j1=json.loads(s1)
with open("config-out.yaml", "w") as f:
    yaml.safe_dump(j1, f, sort_keys=False)

23.2.2 Convert YAML config to a new JSON config

import yaml
import json
with open("config-input.yaml") as f:
    s2=f.read()

j2=yaml.safe_load(s2)
with open("config-output.json","w") as f:
    json.dump(j2, f, indent=2)

23.3 Ticket numbering

Two modes are currently available: simple numbering and a pseudo-random sequence (LCG).

Ticket numbers may contain only digits (0-9) and upper-case (ASCII) letters (A-Z).

23.3.1 Simple numbering

The configuration requires:

The internal state records simply the last number issued.

23.3.2 Pseudo-random

Tickets numbers can be generated by a Linear Congruential Generator (LCG).

M and C should be relatively prime. A-1 should be divisible by all prime factors of M. A-1 should also be divisible by 4 if M is divisible by 4.

In ticket_pattern, each “A” is 4 bits and each N is 3 bits. The total number of bits should match ticket_bit_length.

A random value will be assigned for the first ticket.

The internal state records simply the number of tickets issued (so it can be tested against the parameter M) and the last ticket number issued (numerically).

23.4 Common ticket numbering configuration

23.5 Creation rules aka crules

A ticket is created given three items:

The first rule given is the default.

A crule gives a set of default tags and properties. These can be used for triggering vrules and srules (see below). A short name and a description are also included for use in the web interface.

Syntax: crules is a list. Each item of the list is an object with the following keys

Note, tags, property keys and property values cannot be empty strings.

(Future feature: in the multiuser mode, crules will also be used for access control.)

The following empty rule is set as default:

"crules": [
    { "name":        "norule",
      "description": "Empty rule",
      "tags":       [],
      "properties": []  }
]

If a silo has any rules, it is not included. If this rule is desired, explicitly include it in the silo configuration.

Example of a rule for a risk register: this sets a tag “risk” and two properties.

"crules": [
    ...
    { "name":         "riskregister",
      "description":  "Risk register entry",
      "tags":         [ "risk" ],
      "properties":   [ { "key":   "initial_risk",
                          "value": "medium"},
                        { "key":   "residual_risk",
                          "value": "medium" } ] }
]

23.6 acl_ug_groups and crules

A crule can have an optional key, acl_ug_groups, which takes a list of groups, e.g.,

"acl_ug_groups": [ "riskcreator" ]

The effect is to add acl_ug entries for the user and each named group in acl_ug_groups. See ACLs below.

23.7 Unique properties

By default, Flatfish will allow multiple properties with the same key. If you want to prevent this for a particular key, add the key(s) to the unique_property_keys configuration item.

Example:

"unique_property_keys": [ "Initial_Risk", "Residual_Risk" ]

The effect is to remove a conflicting key/value and add the new one.

23.8 Validation rules aka vrules

Validation rules enable silo-wide settings of consistency requirements in a ticket. For example, a ticket with tag “risk” should always have properties “initial_risk” and “residual_risk”. Similarly, the the two properties “initial_risk” and “residual_risk” should have one of the three values “low”, “medium” or “high”.

The selector rules are the same as for ticket selection.

"vrules_pk_required": [ { "selector": "g=risk", "key": "Initial_Risk" },
                        { "selector": "g=risk", "key": "Residual_Risk" } ],
"vrules_pkv_values":  [ { "key": "Initial_Risk",
                          "values": [ "low", "Medium", "HIGH" ] },
                         { "key": "Residual_Risk",
                           "values": [ "low", "Medium", "HIGH" ] } ],

23.9 Suggested tags and property keys

To support auto-completion in the web interface, Flatfish has two configuration lists, suggested_tags and suggested_property_keys.

Example:

"suggested_tags": [ "Alpha", "Bravo" ],
"suggested_property_keys": [ "Assigned_To" ],
"suggested_property_kv": [ { "key": "Alpha",
                 "value": "able" },
               { "key": "Alpha",
                 "value": "zulu" },
               { "key": "Bravo",
                 "value": "baker" },
               { "key": "Bravo",
                 "value": "whisky" }]

Flatfish will also add

23.10 Date input aka irules

Property keys can be added to one, neither (but not both — behaviour is undefined) of these lists:

The former will always offer a date picker through the HTML interface.

The latter offers a toggle to offer a date picker. If not using the date picker, the additional date input methods from special case 3 (above) are permitted. The format is checked when adding/changing these properties.

23.11 Styling rules aka srules

Styling rules allow for

These are broken into multiple lists:

Colours apply only to the web interface, not the text interface. They are specified as a pair of HTML/CSS colours, fg (for foreground) and background.

Example:

"srules_t_case":      [ "Risk", "Incident", "DaFt_cAsE" ],
"srules_pk_case":     [ "Initial_Risk", "Residual_Risk" ],
"srules_pkv_case":    [ { "key": "Initial_Risk",
                         "values": [ "low", "Medium", "HIGH" ] },
                         { "key": "Residual_Risk",
                          "values": [ "low", "Medium", "HIGH" ] } ],
"srules_t_colour":    [ { "tag": "Incident", "fg": "white", "bg":"red" },
                   { "tag": "Risk", "fg": "black", "bg":"yellow" } ],
"srules_pk_colour":   [ { "key": "Opened_By", "fg": "white", "bg":"blue" } ],
"srules_pkv_colour":  [ { "key": "Initial_Risk", "value": "low", "fg": "white", "bg":"blue" },
                        { "key": "Initial_Risk", "value": "medium", "fg": "black", "bg":"orange" },
                        { "key": "Initial_Risk", "value": "high", "fg": "white", "bg":"red" },
            { "key": "Residual_Risk", "value": "low", "fg": "white", "bg":"blue" },
                        { "key": "Residual_Risk", "value": "medium", "fg": "black", "bg":"orange" },
                        { "key": "Residual_Risk", "value": "high", "fg": "white", "bg":"red" }],
"srules_t_priority":  [ "Risk", "Incident" ],
"srules_pk_priority": [ "Initial_Risk", "Residual_Risk" ]

Notes:

23.12 Silo searches

A silo can have searches defined specific for that silo in the “searches” object.

Example:

"searches":           [ { "description": "List open tickets by (inverted) priority, earliest deadline/scheduled/review, then status, then title",
                          "selector":    "s:*",
                          "sort":        "!ppriority:est" } ]

The example above provides a search that is sent to the /list URL.

The /calendar and /activity URLs can also be added to the predefined searches by setting type to calendar or activity. Both require date1 and date2 fields (for date from and to). /activity also requires a username which should be a single username or any. Finally, the sort field is ignored for both and may be omitted.

23.13 ACLs

23.13.1 General

23.13.2 Debug

acl_debug can be set true or false in the silo configuration to generate debugging output.

23.13.3 Groups

acl_groups is a map from group names to lists of usernames, e.g.,

"acl_groups": { "admins": [ "paul" ],
        "riskmanagers": [ "paul" ],
        "privusers": [ "paul" ],
        "privread": [ "paul" ],
        "users":  [ "paul", "alice", "bob" ],
        "defaultread": [ "paul" ],
        "riskcreator": [] }

23.13.4 Silo operations

Silo operations are always allowed. These include silo creation, adding, removal, set active, show as well as build cache.

23.13.5 Creation ACLs

acl_creation is a list of blocks containing a name, optional group (or notgroup), optional crule (or notcrule) and a decision which must be allow or deny. Example:

"acl_creation": [
{ "name":  "allowrisks",
  "group": "riskmanagers",
  "crule": "riskregister",
  "decision": "allow"
},
{ "name": "denyrisks",
  "crule": "riskregister",
  "decision": "deny",
  "explain": "Only risk managers are allowed to add risk tickets."
},
{ "name": "defaultallowcreation",
  "decision": "allow"
}
]

An optional explain clause can be given to provide information when this rule matches.

If neither group not notgroup are present, then it matches all users. If notgroup is present, then the group match is inverted. Similar behaviour applies to crule and notcrule.

The clone creation ACL must be available to a user to clone tickets and the donor ticket must have at least the read permission (below).

23.13.6 Ticket permissions

Char Permission Meaning
l list Allows ticket to be revealed in list/search operations, include api/slt.
r read Allows ticket to be read, including api/thl and attachments
t title Change title
u summary Change summary
e entry Allows entries to be made to ticket
a attachments Allows attachments to be added to ticket
h hide Allows entries/attachments to be hidden
x transitions Allows changes to status, tags, properties, incl. acl_* properties
! hidden An anti-permission. If an operation is denied and this anti-permission is present, the ticket is effectively non-existent. This has to be specified as things mysteriously disappearing can be hard work to debug.
i vIew Equvalent to lr
o sOme Equivalent to lrea
m most Equivalent to lrtueax, i.e., all but not h
v eVery Equivalent to mh

23.13.7 Tickets: acl_ug property

The special acl_ug property takes a value of the form user:group. This adds user to group for the purposes of evaluating this ticket. This gives a means of adding user(s) to group(s) on individual tickets.

E.g., acl_ug="phil:submitter" would mean phil is in the submitter group when evaluating rules for this ticket.

acl_ug can be set during creation of a ticket, and by someone with x permission.

23.13.8 Ticket ACLs

acl_ticket is a list of blocks containing name, optional group/notgroup (similar to creation ACLs), a selector (as for ticket search selection) and a decision made up other characters from ticket permissions above. explain is optional again. Example:

"acl_ticket": [
{ "name": "confidential items",
  "group": "privusers",
  "selector": "g:CONFIDENTIAL:",
  "decision": "v"
},
{ "name": "read-only confidential",
  "group": "privread",
  "selector": "g:CONFIDENTIAL:",
  "decision": "lr",
  "explain": "This group may read tickets, not change them."
},
{ "name": "hide super confidential",
  "selector": "g:CONFIDENTIAL: g:REALLYCONFIDENTIAL:",
  "decision": ""
},
{ "name": "hide confidential",
  "selector": "g:CONFIDENTIAL:",
  "decision": "l",
  "explain": "Ticket is restricted to privusers group."
},
{ "name": "allow default read",
  "selector": "all",
  "decision": "v"
}
]

23.14 Batch operation ACL

The configuration key acl_batch takes a list of user names. If not present, any user may use the batch interface. If present, only those users in the list of users may user it.

23.15 serverconfig.json

The following items are defined in a separate serverconfig.json file, not the main silo config.json file.

23.15.1 External authentication tokens

ex_auth_tokens is a list of strings, any of which will be accepted by the /exapi API. If no tokens are defined, this API will be inoperable.

23.15.2 Request header checks

If use_request_headers is set to true, then authn_request_headers should be set to a list of secrets. The reverse proxy should ensure that a header with name X-Flatfish-Authn is set to one of those secrets, e.g.,

RequestHeader set X-Flatfish-Authn thesecret

Requests without a matching secret will be treated as an error.

Requests with a matching secret will look for the optional header X-Flatfish-Path which can be used to set a subpath in the proxy. E.g.,

RequestHeader set X-Flatfish-Path /path/to/flatfish

The path should not end with a trailing /. If absent, it is treated as an empty string.

This allows the use of subpaths in a proxy configuration, e.g.,

  <Location "/fw">
    ProxyPreserveHost on
    RequestHeader set X-Forwarded-Proto https
    RequestHeader set X-Flatfish-Authn "somesecret"
    RequestHeader set X-Flatfish-Path "/fw"
    ProxyPass         "http://localhost:7001"
    ProxyPassReverse  "http://localhost:7001"
  </Location>

Warning! A trailing / in the ProxyPass/ProxyPassReverse directives will cause weird behaviour.

23.15.3 Size overrides

Two values may be set in serverconfig.json.

23.16 Ex_auth_tokens and request header checks together

If use_request_headers is set to true then any caller of the /exapi API will also have to set a valid X-Flatfish-Authn request header.

24 Overriding CSS

If a file extra.css exists in the silo’s meta directory, this file will be appended to the default CSS. This allows for overriding of CSS text, e.g.,

div.attcontent {
font-size: initial;
font-family: initial;
background-color: #eeeeee !important;
}

25 User configuration files

On Linux, a file ${HOME}/.flatfish is expected, with a list of ticket silos. Each non-empty line should contain the absolute path to a silo root.

On Windows, this file is placed in the $USERPROFILE directory and named flatfish.json.

Changes to this file should be made via the flatfish application.

26 Acknowledgements

26.1 Ada and C

This software is developed and built on Debian Linux using the GNU C compiler collection, including the GNAT Ada compiler and some related Ada components. These are released under GPL3, with the GCC RUNTIME LIBRARY EXCEPTION. Many people have contributed to these projects, thank you!

26.2 Libsodium

The libsodium library is used in Flatfish — thank you for making this software available. The libsodium licence is:

ISC License

Copyright (c) 2013-2020 Frank Denis

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

26.3 Clipboard.js

Clipboard.js is used in Flatfish — thank you for making this software available. The licence file for this is:

The MIT License (MIT)

Copyright © 2024 Zeno Rocha hi@zenorocha.com

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

26.4 Dart

Dart is released under a 3-clause BSD licence. Although we do not redistribute it as part of Flatfish, it is used to build the front-end Javascript. We thank the many contributors to Dart.

27 Assumptions and oddities