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.
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.
ff_squish
and
ff_squish_email
”)Each ticket comprises
Flatfish has 9 fixed statuses:
Rather than offer customisable status values, use the following tag and property features.
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.
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.
JSON: mostly obvious.
A JSON entry should be in the ticket; then each attachment is stored as a separate file.
JSON: mostly obvious.
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.
Tickets which have been closed via merge will be (transitively) included in the view of their merged ticket. A light blue visibility switch is available in the top-right corner to control this behaviour. This is the main functional difference from tickets closed via duplicate.
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.
The properties Scheduled, Deadline and Review require a date to be provided. The permitted formats are
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.
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.
Tickets are selected via a text string. This search key is interpreted as follows.
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).
“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.
Tickets are sorted according to a sort rule, comprising a sequence of letters, in order.
Example: dh!l – sort by deadline, then scheduled, then reversed last-history.
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.
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.
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).
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.
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.
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:*'
forcedangerous
can be used to override the checks on
status and special properties.
nocache
can be used to speed up multiple operations from
the command-line, but the cache will need manually
rebuilding.
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).
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.
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.
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.
As well as “q” for quitting and “o” to open a browser, the following keys are also available:
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).
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.
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:
fromdos
(Debian package tofrodos)reformime
(maildrop)formail
(procmail)msgconvert
(libemail-outlook-message-perl)unzip
(unzip)7z
(p7zip-full)pdfinfo
(poppler-utils)extract_msg
, installed via
pip3 install extract-msg
(on Debian, install the
python3-pip
package first)Prior to running FFWeb, you will need to create an authentication database.
ffturnstile createdb
All usage of FFTurnstile is on the current directory. Other commands are
adduser _name_ _password_
deluser _name_
listusers
FFTurnstile is case-sensitive throughout.
To reset/change an existing user’s password, delete the user
(deluser
) then add them again (adduser
).
At the moment, only two substitutions are available.
${userid}
is replaced by the current username. Usable
in
${value}
– see render
some values as hyperlinks${
is escaped by $${
. Although why you’d
want to search for that….
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:
FF_USERCONFIG
should point to your user configuration,
e.g., FF_USERCONFIG=/somewhere/flatfish.json
.FF_TEMPDIR
should point to a suitable directory for
temporary files, e.g.,
$env:FF_TEMPDIR=\stupid\windows\config
.The environment variable FF_MESSAGELEVEL
can be set
to
to override the verbosity of messaging.
A silo is created using
flatfish create_silo /path/to/my/new/silo
The resulting structure contains
Flatfish requires a licence file that can only be provided by Green Pike Ltd. Email apps@green-pike.co.uk
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)
FF_LICENCE
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.
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.
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.
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.
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)
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)
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).
The configuration requires:
The internal state records simply the last number issued.
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).
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" } ] }
]
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.
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.
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" ] } ],
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
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.
Styling rules allow for
These are broken into multiple lists:
srules_t_case
is a list of tags and their preferred
casing.srules_pk_case
is a list of property keys and their
preferred casing.srules_pkv_case
is a list of objects comprising a
property key and the preferred casing of the values in a list.srules_t_colour
is a list of tags and colours.srules_pk_colour
is a list of property keys and
colours.srules_pkv_colour
is a list of property key/value pairs
and colours.srules_t_priority
is a list of tags. If present on a
ticket, these tags will be listed first and in the given order.srules_pk_priority
is a list of property keys. If
present on a ticket, these properties will be listed first and in the
given order.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:
The configuration list render_p_as_hyperlinks
comprises
pairs of property keys and substitutions using
${value}
.
Example:
"render_p_as_hyperlinks": [ { "key": "www",
"target": "${value}" },
{ "key": "wikipedia",
"target": "https://en.wikipedia.org/wiki/${value}" } ]
This results in the value being displayed as a hyperlink with the given target.
(This was a new feature in release 93.)
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.
acl_debug
can be set true or false in the silo
configuration to generate debugging output.
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": [] }
Silo operations are always allowed. These include silo creation, adding, removal, set active, show as well as build cache.
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).
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 |
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.
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"
}
]
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.
serverconfig.json
The following items are defined in a separate
serverconfig.json
file, not the main silo
config.json
file.
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.
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.
Two values may be set in serverconfig.json
.
max_upload_size
– the default is 100 * 1024 * 1024 = 104857600, i.e., 100
MiBmax_squish_attachments_cache
– the default is 15 * 1024 * 1024 = 15728640If 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.
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;
}
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.
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!
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.
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.
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.
There is no official roadmap. New features are primarily added because they suit the author’s personal agenda.
Requests will be considered, and most will be chargeable. Email Green Pike Ltd to discuss such requests.
…there is a long list of possible feature changes held privately.