feat(mail-ingest): read forwarded booking mails and add what passes the checks to its trip

Addresses per person and per trip (random base32 token, stored hashed and
encrypted), an intake every transport shares, and a job that reads each
mail once under a lease: filters without AI, machine-readable data always,
one AI request with the person's trips, the server's checks G1 to G9, then
one transaction per mail that adds what passed, keeps the rest in the inbox
with a reason, and notifies the forwarder and co-travellers. Undo within
7 days, manual apply, filing as documents, a prefilled form and a nightly
retention complete it; on a managed install the operator's switch decides.
This commit is contained in:
Maurice
2026-11-13 16:04:26 +01:00
parent 340454cfc7
commit de7de4b8de
36 changed files with 4038 additions and 54 deletions
@@ -113,7 +113,10 @@ export const MAIL_INGEST_REASON_BY_LLM_OUTCOME: Readonly<Record<LlmParseOutcome,
too_large: 'too_large',
};
/** The server's checks on a booking read from a mail, as the inbox lists them (plan G1 to G8). */
/**
* The server's checks on a booking read from a mail, as the inbox lists them:
* plan G1 to G8, and G9, the trip holding the booking already.
*/
export const mailIngestCheckSchema = z.enum([
'schema',
'trip',
@@ -123,6 +126,7 @@ export const mailIngestCheckSchema = z.enum([
'in_text',
'assignment',
'cancellation',
'duplicate',
]);
export type MailIngestCheck = z.infer<typeof mailIngestCheckSchema>;