## Overview

Welcome to the CHAPPS REST API.  It is implemented in Python using
FastAPI and SQLAlchemy.

This document starts with a brief synopsis of the meaning and
interactions of the various config objects managed by this API,
followed by a discussion of the naming conventions used througout the
API documentation, and finally a list the various categories of API
routes.  The API routes themselves are documented in the sections
which follow.  (These do not appear in the README-API.md file as they
are generated automatically.)

Live documentation is generated automatically via FastAPI, compiled
from various sources including the README-API.md document, API section
descriptions, and Python function docstrings.  Since some of the
Python functions used as API route handlers are generated by factories,
there may be occasional lapses of grammar, etc.  Please excuse any
awkwardness; where the documentation is ambiguous,
please feel free to file an issue about it.

## Configuration Synopsis

In order to control the flow of email which corresponds to a
particular user or domain, CHAPPS needs to know how those two kinds of
entities are connected to one another.  Additionally, as a fallback
for domain matching, entire email addresses may be associated with a
user, to permit that user to send mail with the MAIL FROM set to that
email.  Settings on Domain records indicate whether to perform SPF
enforcement and/or Greylisting upon inbound emails destined for the
named domain.

**Please note:** Our best current recommendation is to use greylisting
as a component of SPF enforcement, but not to turn it on as a general
blanket policy for a domain.  That is to say, set domains to enforce
SPF but not to greylist.  The SPF enforcement routine uses greylisting
when an incoming SPF soft-fails its SPF check.

For better control of unwanted email, considering enforcing DMARC as
well.  The SPF module included in CHAPPS attaches the SPF-check header
to all emails it encounters, in order to ensure that it is present for
DMARC.  We have no immediate plans to incorporate DMARC enforcement
into CHAPPS, but the future is large.

### The Rules

A **user** object may only have one **quota** object associated to it.

The **user** to **domain** and **user** to **email** mappings are both
many-to-many.

If a **user** is associated to a **domain**, CHAPPS will allow that
**user** to send email which has a MAIL FROM address that matches it
exactly from the `@`-sign to the end.

If a **user** has no matching **domain** associations, and the entire
MAIL FROM address exactly matches an associated **email** record, then
CHAPPS will permit that email.

If a **domain** has the `check_spf` flag (attribute) set to True, then
when email arrives which is destined for that exact domain, it will be
processed according to the SPF enforcement policy, the interesting
part of which is that if it receives `SoftFail` it will be greylisted.

If a **domain** has the `greylist` flag set to True, then when email
arrives for that exact domain, it will be processed according to the
greylisting policy.

If a **domain** had both flags set, SPF checking is performed first,
and if the email receives "Pass" from the SPF check, it gets
greylisted anyway.  This configuration is not recommended.

Any email handled by a service incorporating an SPF policy handler
will be marked with the SPF check header, regardless of whether SPF is
being enforced.  This is for downstream compatibility with DMARC and
other services/milters which might like to look at a `Received-SPF:`
header.

### Implementation notes

An email quota as implemented here is a count of outbound messages per
24hr.  All objects have auto-incrementing integer `id` attributes and
string `name` attributes.

The **quota** object has an additional integer `quota` attribute,
while the **domain** object has two optional flags: `check_spf` and
`greylist`, which control how the inbound service handles emails for a
given domain.

## Conventions

 The primary answer to a query is always returned in the element named
`response`.  So for example, when GETting a **user** object, that object
is the value of the `response` key, and there may be ancillary keys
named for its associations, which are `quota`, `domains` and `emails`.

In general, a parameter named `q` indicates a string which will be
used in a basic substring match against the `name` attribute (column)
of the object.  The `skip` and `limit` parameters may be used to
paginate through what might sometimes be long lists of objects.
Since the objects are small in this case, the default is to skip none,
and to limit to 1000 rows returned.  In many cases this may mean that
the entire set of associated objects is returned: say, the list of
**user**s for a **domain** which has a lot of mailboxes.

If an object (**user**, **domain** or **email**) has more than 1000 of
another type associated to it (e.g. some **user** is authorized to
send from over 1000 **domain**s, or some **domain** has over 1000
authorized senders), there are special routes to list just those
associated objects for a particular source: "User List Domains" and
"Domain List Users".  There are similar methods for managing lists of
associated **email** objects too, for configuring the whole-email matching
function.

In the automatically-generated CRUD routes, the generic variable
`item_id` is used to refer to the object ID of the main object
concerned by the route in question.  In other words, an instance of
the object type named in the first node of the API route path will be
looked up by its ID using the value provided to `item_id`, and then
that object will be affected or reported by the API.  This seems
fairly intuitive but also worth stating since it is not worth the
effort to make the variable name match the name of the model.  Maybe
in a future revision.

In the examples, square brackets have been used to indicate portions
which may or may not occur; in general, **no brackets of any kind**
should actually be included in any names.

## Categories

API routes fall under a few different categories:
- **user** manipulation
- **email** manipulation
- **domain** manipulation
- **quota** manipulation
- live interaction with CHAPPS Redis environment
- system commands like rewriting CHAPPS config file, etc. (lumped in
  with live routes for now)
