C4 Level 2 -- Containers
The running services and how they communicate.

Containers
| Container |
Technology |
Purpose |
| Book-E |
Node.js, discord.js (Automate-E) |
Discord agent. Extracts data via Claude Haiku. Proposes actions and queries data through Event Store API. |
| Event Store API |
ASP.NET Core 10 |
Central event log. Append-only. Manages proposal → review → execute flow. Confidence scoring. All services read/write events through this API. |
| Accounting API |
ASP.NET Core 10 |
Folio/Fiken calls only. Executes approved accounting events. No event logic. |
| Cost API |
ASP.NET Core 10 |
Queries Anthropic, Google, Cloudflare usage APIs. Reports spending. |
| PostgreSQL |
PostgreSQL 16, StatefulSet |
Events, patterns, cost snapshots. Single source of truth. |
| Metabase |
metabase/metabase |
Dashboard for events, spending, audit trail. Read-only access to Postgres. |
| CronJob |
k8s CronJob, daily 07:00 |
Triggers compliance checks and cost reports. |
External Systems
| System |
Protocol |
Purpose |
| Folio API v2 |
REST, Bearer |
Bank accounts, transactions, receipt attachments |
| Fiken API v2 |
REST, Bearer |
Invoices, expenses, journal entries |
| Discord |
WebSocket |
#invoices channel + DMs |
| Claude Haiku |
Anthropic API |
Document extraction, conversation |
| Review-E |
Discord (async) |
Reviews low-confidence proposals |
| Anthropic Usage API |
REST |
Token usage and costs |
| Google Cloud API |
REST |
Gemini usage and costs |
| Cloudflare API |
REST |
Worker/Pages usage and costs |
Data Flow
| From |
To |
Data |
| Book-E |
Event Store API |
POST /events (proposals), GET /events (queries) |
| Review-E |
Event Store API |
POST /events/{id}/approve, POST /events/{id}/reject |
| Event Store API |
Accounting API |
Execute approved accounting events |
| Event Store API |
Cost API |
Execute cost queries |
| Accounting API |
Folio API |
/accounts, /events, /attachments |
| Accounting API |
Fiken API |
/invoices, /expenses, /journal-entries |
| Cost API |
Anthropic/Google/Cloudflare |
Usage data |
| Event Store API |
PostgreSQL |
Events, patterns |
| Metabase |
PostgreSQL |
Read-only dashboards |
| CronJob |
Event Store API |
/check/* endpoints |
Key Design Decision: Event Store as Separate Service
The Event Store API is separate from the Accounting API because:
- Multiple consumers — Book-E, Review-E, Accounting API, Cost API all need events
- Single responsibility — Event Store manages events. Accounting API calls Folio/Fiken. Cost API calls usage APIs.
- Immutability enforcement — One service enforces append-only rules
- Access control — One place controls who can write which event types
- Schema evolution — Change the events table without changing every consumer
Secret Distribution
| Secret |
Book-E |
Event Store API |
Accounting API |
Cost API |
| Discord token |
Yes |
— |
— |
— |
| Anthropic key (LLM) |
Yes |
— |
— |
— |
| Postgres creds |
— |
Yes |
— |
— |
| Folio token |
— |
— |
Yes |
— |
| Fiken token |
— |
— |
Yes |
— |
| Anthropic usage key |
— |
— |
— |
Yes |
| Google Cloud key |
— |
— |
— |
Yes |
| Cloudflare API token |
— |
— |
— |
Yes |