Merge branch 'docs/ai-roadmap'
CI / Backend tests (push) Waiting to run
CI / Frontend lint, typecheck, build (push) Waiting to run
CI / End-to-end tests (push) Blocked by required conditions
CI / Deploy tagged release (push) Blocked by required conditions

This commit is contained in:
2026-10-24 14:36:25 +02:00
+143 -5
View File
@@ -8,7 +8,8 @@ previous round (1.12.0 – 1.23.0). Where to pick up: [HANDOVER.md](./HANDOVER.m
**Theme for 2.0:** turn a feature-rich church app into a product that can be
sold — trustworthy (POPIA), flexible (multi-day events, several payment
providers), and maintainable (tests, CI, typed backend, versioned API).
providers), maintainable (tests, CI, typed backend, versioned API), and with
**AI helpers** as the headline feature (§15).
**Status (2026-10-23):** all features in this document are approved. Shipped
so far: 1.32.0 early-bird ribbon on event cards; 1.33.0 multi-day events
@@ -48,8 +49,10 @@ notifications. SnapScan and Zapper are dropped — Yoco and PayFast are enough (
12. [Multi-campus (one install per church)](#12-multi-campus-one-install-per-church)
13. [Central management platform (Hope Events Hub)](#13-central-management-platform-hope-events-hub)
14. [Foundations (platform work)](#14-foundations-platform-work)
15. [Suggested build order](#suggested-build-order)
16. [Decisions](#decisions-2026-10-22)
15. [AI helpers (2.0 headline)](#15-ai-helpers-20-headline)
16. [AI: later stages](#16-ai-later-stages)
17. [Suggested build order](#suggested-build-order)
18. [Decisions](#decisions-2026-10-22)
---
@@ -679,7 +682,8 @@ All later calls are signed with the install secret (HMAC) and go over HTTPS.
events people already paid for, and get its own data out (POPIA access
rights). Suspension blocks *new* activity only.
- **One plan for now.** Plan limits (e.g. number of campuses, WhatsApp) can
be carried in the token later.
be carried in the token later. The first per-licence limit comes with 2.0: the
**monthly AI cap in rand** (§15), kept and enforced on the Hub, since the Hub meters AI.
### Things to be aware of
@@ -703,6 +707,8 @@ model Install { id, customerId, licenceId, name, url, secretHash, version,
model Heartbeat { id, installId, receivedAt, version, health Json, stats Json }
// rolled up to daily after 30 days
model InstallEvent { id, installId, type, message, createdAt } // alerts, version changes
// 2.0, AI (§15): Licence gets aiMonthlyCapCents; usage per call, no prompt/response text
model AiUsage { id, installId, helper, model, inputTokens, outputTokens, costCents, createdAt }
```
---
@@ -724,6 +730,134 @@ keep adding to.
---
## 15. AI helpers (2.0 headline)
Small, one-button AI helpers in the places people already work. **No chat** in 2.0:
each helper is one request with a predictable cost, and a person always reviews
the result before anything is saved or sent.
**Who:** Supervisors and admins (the people who create events and read reports).
### The helpers
| Helper | Where | What it does |
|--------|-------|--------------|
| **Draft an event** | Event wizard, first step: "Describe your event" | *"Youth camp 14–16 March at Camp Wartburg, R450, 60 places, kids need consent"* → fills in title, description, dates/sessions, location, ticket options and prices, capacity, consent settings. The supervisor checks every field and saves as usual |
| **Summarise this report** | Every report (Reports page) | A few plain-language insights under the report: trends, outliers, comparisons with the previous period |
| **Draft a message** | Email / WhatsApp attendees, broadcasts | Turns a short note (*"remind them to bring a sleeping bag, bus leaves 7:30"*) into a friendly message in the right tone and length (shorter for WhatsApp), with placeholders like `{{name}}` |
| **Summarise feedback** | Post-event feedback results | Themes, what people liked, what to improve, notable comments |
| **Improve this text** | Event description, banner, message boxes | Rewrite for clarity, fix spelling, shorten |
Every helper shows **"AI suggestion — check before saving"**, can be undone, and
never saves, sends or publishes by itself.
### Provider and model
- **One provider: Claude (Anthropic), model Claude Haiku 5.5** — the cheapest
current model ($0.10 per million input tokens, $0.50 per million output, for
prompts under 100K tokens; prices as of 2026-10). Good enough for drafting and
summarising; a helper can move to a bigger model later if quality needs it.
- **Rough cost:** a helper call is ~2,000–10,000 tokens in and ~500 out, so well under
US$0.002 per click — about R1.50–R3 per thousand clicks. Fixed instructions are
prompt-cached, which makes repeat calls cheaper still.
- Structured output (a JSON schema) for "Draft an event", so the reply maps straight
onto the event form and is validated before it's shown.
### Key, caps and billing — through the Hub
Joshua provides the API key; churches don't need their own. The key must never sit on
an install (one leaked install would leak it for everyone), so:
- **Installs call AI through the Hub:** `POST /api/ai/complete` on the Hub, signed with
the install secret like the heartbeat. The Hub adds the key, calls Claude, and returns
the result. Still **install → Hub only** — the Hub never reaches into an install.
- **The Hub meters every call** in rand: tokens used × the model's price × an exchange rate
Joshua sets in the Hub (with an optional margin). Usage is kept per install per month.
- **Monthly rand cap per licence**, set by Joshua in the Hub to match what the church pays
(e.g. R0 = AI off, R50, R200). The licence's cap is the first per-plan limit. At 80% the
install's admins get a warning email; at 100% the helpers are switched off until the next
month (or until Joshua raises the cap). Optional per-user daily limit against runaway use.
- **Admins see their usage** in Site settings → AI: used this month (R and number of uses),
the cap, a daily chart, use per helper and per person, and an on/off switch per helper.
- If the Hub or Claude is unavailable, the buttons say so; nothing else in the app is affected.
### POPIA
- Anthropic is added to the **operator register** (and Joshua's Hub, which relays the
requests) and to the privacy notice: processing outside South Africa (POPIA s72),
for drafting and summarising only.
- **Send as little personal information as possible:** reports and feedback are sent as
counts, totals and anonymised comments — no names, contact details, medical or
children's information. Drafting an event or a message needs none.
- The Hub stores **no prompt or response text** — only the install, helper, tokens, cost
and time. Check Anthropic's commercial terms on retention and training before launch.
- Uses that include personal information (e.g. feedback comments) go in the access log.
### Plumbing
- Install: `backend/src/ai/` — one client for the Hub's AI endpoint, one prompt + schema
per helper, usage shown from the Hub. Feature flag per helper, all off when the licence
has no AI or the Hub isn't connected.
- Hub: the AI proxy, metering, caps, warnings, an exchange-rate setting, and a per-install
usage view for Joshua (alongside the existing install detail page).
- A small **eval set** (example event descriptions, reports, notes, with what a good answer
looks like) to check quality when changing the prompt or model.
- Help content, audit log entries (AI settings changed), CHANGELOG, FEATURES.md, SETTINGS.md.
---
## 16. AI: later stages
Ideas for after 2.0, in rough order. **Not tied to versions** — each is decided when it's
picked up, and all of them reuse the Hub proxy, metering and caps from §15.
### Ask AI (read-only assistant)
A chat panel for supervisors and admins: *"How many paid for Camp compared with last
year?"*, *"Which events this month are under half full?"*, *"Who hasn't paid yet for
Men's Breakfast?"*.
- The AI can only call **tools the app defines** — the existing stats and report queries,
"find an event", "registrations by week" — never its own SQL. It runs with the
logged-in person's permissions, so it sees nothing they couldn't.
- Answers show the numbers they're based on and link to the matching report.
- Costs more per question than a button (several tool calls), so it counts against the same
cap; may need a bigger model for harder questions.
### Help and navigation assistant
*"How do I add a coupon?"*, *"Where do I see who checked in?"* → a short answer from the
in-app help content (`frontend/src/content/help/`) with a link straight to the right page.
No personal information involved, so it's cheap and simple — could also be offered to
ordinary users.
### Actions with confirmation
The Ask assistant can also *do* things — create an event draft, schedule a reminder, offer
waitlist places, record a cash payment — always as **"here's what I'll do → Confirm"**, with
each confirmed action in the audit log.
### More helpers
Smaller one-button additions as they come up: suggest an event's price tiers from past
events, write a post-event thank-you, draft certificate wording, translate a message into
Afrikaans (ties in with §10), flag unusual payments for the cashup.
### Self-hosted AI (long term)
Run an open-weight model on Joshua's own GPU server instead of a paid API, once usage and
income justify the hardware:
- Because every install already talks to the **Hub's** AI endpoint, moving to self-hosting
is a change on the Hub only — the Hub gets a provider adapter (Claude now, self-hosted
later, or both: simple helpers self-hosted, harder questions on Claude).
- **POPIA bonus:** the data can stay in South Africa — no cross-border transfer.
- **When it makes sense:** compare the monthly API bill with the cost of a GPU server
(hardware or cloud rental, power, upkeep), and check the self-hosted model against the
eval set from §15 before switching any helper over.
---
## Suggested build order
| Phase | Version | Features | Why |
@@ -740,7 +874,7 @@ keep adding to.
| 9 | 1.45.0 – 1.47.0 | Event series & cloning, Wallet passes, Outbound webhooks | Smaller, independent wins |
| 10 | 1.48.0 – 1.50.0 | Admin dashboard/Ctrl+K/bulk actions, Afrikaans, Accessibility pass | Polish before the big release |
| 11 | 1.51.0 | TypeScript backend + OpenAPI + `/api/v2` alongside v1 | The breaking-change groundwork |
| 12 | **2.0.0** | v1 API removed, migration guide, marketing site/docs for selling | The release |
| 12 | **2.0.0** | **AI helpers** (§15 — headline feature: draft an event, summarise reports and feedback, draft messages, improve text; through the Hub with a rand cap per licence), v1 API removed, migration guide, marketing site/docs for selling | The release. AI needs the Hub (phase 6) for the key, metering and caps |
Each phase should add matching help content (`frontend/src/content/help/`),
audit log entries, Jest tests, a CHANGELOG entry, and updates to FEATURES.md
@@ -773,6 +907,10 @@ feature.
| — | Grace period / suspension | 14-day grace; suspended = read-only (tickets still scan, data export still works) (2026-10-23) |
| — | Income in the heartbeat | Included, as **ranges** only (R0–R1 000, R1 001–R5 000, …), never exact amounts (2026-10-23) |
| — | Licence plans | One plan for now (2026-10-23) |
| — | AI in 2.0 | The **headline feature of 2.0**: one-button helpers only (draft an event, summarise reports and feedback, draft messages, improve text) — no chat yet (2026-10-24) |
| — | AI provider and key | One provider, **Claude** (Haiku 5.5 to start, for cost). Joshua provides the key; installs call AI **through the Hub**, which holds the key and meters usage (2026-10-24) |
| — | AI cost limits | A **monthly rand cap per install**, set in the Hub per licence to match what the church pays; admins see their usage in Site settings → AI (2026-10-24) |
| — | AI later | Ask AI (read-only, tools only), help/navigation assistant, actions with confirmation, more helpers, and long-term **self-hosted** AI behind the same Hub endpoint — not tied to versions (2026-10-24) |
| — | POPIA: message kinds | Bulk messages are either **Event updates** (to registrants — still sent after unsubscribing) or **News & announcements** (marketing — opt-in, one-click unsubscribe). Every bulk email links to the preferences (2026-10-23) |
| — | POPIA: existing users | Kept opted in to news (logged as "existing account"), asked once at their next login to confirm or opt out. New sign-ups choose with an unticked box (2026-10-23) |
| — | POPIA: deleting an account | A request: the account is deactivated at once, personal info is anonymised when an admin approves. Waits while the person has an open registration for an upcoming event (2026-10-23) |