Skip to content

C4 Level 2 -- Containers

The running services and how they communicate.

C4 Level 2 -- Containers

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:

  1. Multiple consumers — Book-E, Review-E, Accounting API, Cost API all need events
  2. Single responsibility — Event Store manages events. Accounting API calls Folio/Fiken. Cost API calls usage APIs.
  3. Immutability enforcement — One service enforces append-only rules
  4. Access control — One place controls who can write which event types
  5. 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