# ticket — brief

<!-- The genesis document: what this is, why it exists, who it's for, and what
     "done" looks like. Write-once-read-always. Keep it thin — it is always
     loaded. Detailed how-it-works goes in .logs/planning/ or docs. -->

**What:** An email-first ticketing system at `ticket.bowden.works` (port 3157):
tickets, replies, status, and time per ticket. Most tickets are born from
emails rian forwards in; an AI files each one (which project, new ticket or
progress on an existing one) and the reading/writing effort of every email is
credited to the ticket as estimated time. Built as a **caddie drop-in** on the
standard stack (seams now, drop-ins when caddie M2 lands).
**Why:** Clients email; they will not open a ticket. Today that work and its
time go unrecorded. Forward-and-forget should produce a filed ticket and a
time entry with no typing.
**Who:** rian + agency staff (app-wide levels, all projects); external client
BW accounts per project from M3; the AI as a logged, schema-bound triage
actor; email participants without accounts as first-class message authors.
**Status:** Idea phase → plan drafted 2026-09-02 (`.logs/planning/01-plan.md`,
decisions are proposals awaiting rian). Scaffold deployed at 0.1.0; no product
code. Expected to port its time data into `with` later — identifiers kept
right from M0, nothing else built for it now.

## Where everything is
| Role | Lives in |
|---|---|
| The plan: domain model, email pipeline, time model, milestones, gates | `.logs/planning/01-plan.md` |
| Running feedback to caddie + standards status | `.logs/planning/02-caddie-feedback.md` |
| "Did a caddie standard change?" | `tools/caddie-watch.sh` (run at session start) |
| Session handoff (what next) | `.logs/handoff.md` |
| Project constitution | `agents.md` |
| Human reference material | `notes/` |

## Stack
React SPA + FastAPI, one Python process (the BW-app scaffold), **Postgres 17
sidecar from day one** (internal network, no published port) with the auth
kit's store in `bw_store_sqlalchemy` managed mode (PACKS.md); SQLAlchemy 2.0 +
Alembic; append-only event tables. Kit instance noun: **project**
(`bw-app.toml`). Front-end chrome from the vendored `caddie-ui` pack; the
conversation layer from caddie's interaction embryo. AI triage: Claude
(`claude-opus-5`, structured outputs, no tools). Standards dispatch:
`coding.md` → `react.md` → `frontend.md`; caddie-app requirements:
`/srv/apps/caddie/.logs/planning/05-building-a-caddie-app.md`.

## Not doing
Invoicing, rates, budgets (that is `with`) · SLA/escalation engine · IMAP or
Gmail mailbox polling (a standing read-my-mail credential is rejected; the
Gmail add-on comes later) · public no-login ticket portal · AI-written replies
to clients · embed mode · chat-channel delivery · a second conversation
surface beside the Interaction Standard thread.

## Known gaps
- The caddie drop-ins (`caddie_tool.py`, `caddieHost.ts`) and a vendorable
  interaction kit do not exist yet; ticket builds seams and copies the embryo.
- Receiving layer for inbound mail undecided (Cloudflare Email Routing vs
  Resend inbound) — needs rian and a security review.
- The reading-time estimator is a proposal with uncalibrated constants.
- First app on this box to call the Claude API: no substrate convention for
  the key yet (logged in `v8-feedback.md`).
