Concordance is a distributed configuration service for the iGentAI platform. It provides strongly consistent key-value storage with real-time pub/sub notifications, built on embedded Raft consensus and SQLite. In musical terms, concordance means a state of agreement — this service ensures every node in the cluster agrees on the same configuration state.
Single Bun binary. Zero npm dependencies. One port for HTTP, WebSocket, and Raft peer traffic.
What It Stores
| Category | Namespace Pattern | Example |
|---|
| User preferences | tenant:{id}/user:{uid}/preferences | Theme, editor settings, notification prefs |
| Tenant settings | tenant:{id}/settings | Org-wide defaults, feature flags |
| Session metadata | tenant:{id}/sessions/{sid} | Active session state, context |
| Project definitions | tenant:{id}/projects/{pid} | Project config, agent assignments |
| Device registries | tenant:{id}/user:{uid}/devices/{did} | Push tokens, device capabilities |
| Encrypted credentials | tenant:{id}/credentials | OAuth tokens, API keys (encrypted at rest) |
| Automation definitions | tenant:{id}/automations | Workflow blueprints, trigger rules |
| Skill configs | tenant:{id}/skills | Skill parameters, enabled/disabled state |
| Integration configs | tenant:{id}/integrations | Slack, GitHub, Linear connection settings |
| Audit logs | tenant:{id}/audit | Configuration change history |
Key Properties
| Property | Detail |
|---|
| Consistency | Linearizable writes via Raft consensus (reads from local FSM state) |
| Durability | SQLite with PRAGMA synchronous=FULL for the Raft log |
| Real-time | WebSocket pub/sub pushes changes to subscribers within milliseconds |
| Multi-tenancy | All namespaces are tenant-scoped (tenant:{id}/...) |
| CAS support | Compare-and-swap writes prevent lost updates |
| TTL support | Optional expiresAt per entry for automatic expiration |
| Versioning | Monotonically increasing version per key for conflict detection |
| Snapshots | Full-state snapshots via bun:sqlite serialize/deserialize |
Architecture at a Glance
┌─────────────────────────────────────────┐
│ Concordance Node │
│ │
Diminuendo ──HTTP────►│ Bun.serve() (:4100) │
(gateway) PUT/GET │ ┌────────────────────────────────────┐ │
DELETE │ │ HTTP Router │ │
│ │ /api/v1/kv, /batch, /changes │ │
Diminuendo ──WS──────►│ │ /api/v1/cluster/* │ │
(gateway) JSON-RPC │ ├────────────────────────────────────┤ │
│ │ WebSocket Handler (/stream) │ │
Podium ──────HTTP────►│ │ kv/get, kv/set, watch/subscribe │ │
(agents) GET only │ ├────────────────────────────────────┤ │
│ │ Raft Peer Transport (/raft) │ │
◄───WS──│──│ RequestVote, AppendEntries │ │
Other nodes │ └─────────────┬──────────────────────┘ │
│ │ │
│ ┌──────▼───────┐ │
│ │ RaftNode │ │
│ │ (consensus) │ │
│ └──────┬───────┘ │
│ │ onApply │
│ ┌──────▼───────┐ │
│ │ FSM │ │
│ │ (state │ │
│ │ machine) │──► pub/sub │
│ └──────┬───────┘ broadcast │
│ │ │
│ ┌──────────┴──────────┐ │
│ │ │ │
│ ┌──▼───┐ ┌────▼──┐ │
│ │state │ │raft │ │
│ │ .db │ │ .db │ │
│ │(KV) │ │(log) │ │
│ └──────┘ └───────┘ │
└─────────────────────────────────────────┘
Who Uses It
Diminuendo gateway connects over both HTTP REST (writes) and WebSocket (reads + subscriptions). It authenticates with CONCORDANCE_API_KEY and has full read/write access. Diminuendo resolves client-facing ACP config/* scopes (like “user” or “tenant”) into full Concordance namespaces using the authenticated user’s identity.
Podium agents connect over HTTP REST with CONCORDANCE_AGENT_API_KEY for read-only access to configuration values they need at runtime (skill configs, integration settings, credentials).
Clients never talk to Concordance directly. They send ACP config/* JSON-RPC methods to Diminuendo, which resolves scopes to namespaces and proxies the request.
Authentication
Concordance uses Bearer token authentication with two distinct API keys:
| Key | Env Variable | Access | Used By |
|---|
| API key | CONCORDANCE_API_KEY | Full read/write | Diminuendo gateway |
| Agent key | CONCORDANCE_AGENT_API_KEY | Read-only | Podium agents |
All HTTP and WebSocket requests must include an Authorization: Bearer <key> header. Requests without a valid key receive 401 Unauthorized.
The API key is shared between Concordance and Diminuendo — set the same value in both services. The agent key gives agents read-only access to configuration; agents cannot modify config values.
In dev mode, CONCORDANCE_API_KEY defaults to "dev" and CONCORDANCE_AGENT_API_KEY defaults to "dev-agent". For production, always set strong, unique values.
Setup
Dev Mode (Automatic)
No manual setup required. When you run bun run dev in Diminuendo, it automatically:
- Spawns a single-node Concordance instance on
127.0.0.1:4100 with --bootstrap
- Uses default API keys (
dev / dev-agent)
- Stores data in
./data/concordance/
- Polls
/api/v1/health until ready (up to 5 seconds)
If CONCORDANCE_AGENT_API_KEY is not set, Diminuendo auto-generates one (prefixed cak_) and persists it to .env.local so it survives restarts.
Production
In production, Concordance runs as a separate 3-node Raft cluster. You must configure both Concordance and Diminuendo with matching keys:
On each Concordance node:
CONCORDANCE_API_KEY=your-strong-api-key # Full access (Diminuendo)
CONCORDANCE_AGENT_API_KEY=your-agent-key # Read-only (agents)
On Diminuendo:
CONCORDANCE_URL=http://concordance-leader:4100 # Cluster address
CONCORDANCE_API_KEY=your-strong-api-key # Must match Concordance
CONCORDANCE_AGENT_API_KEY=your-agent-key # Passed to agents via Podium secrets
On Podium agents — the agent key is injected automatically. Diminuendo passes CONCORDANCE_AGENT_API_KEY to Podium as part of the agent secrets bundle when creating instances. Agents receive it via secrets.json and use it to read config values at runtime.
See Configuration for the full list of environment variables and CLI arguments.
Data Flow
Client (ACP) Diminuendo Concordance
│ │ │
│ config/set │ │
│ {scope:"user", │ │
│ key:"theme", │ │
│ value:"dark"} │ │
├───────────────────────────►│ │
│ │ PUT /api/v1/kv/ │
│ │ tenant:acme/user:u1/ │
│ │ preferences/theme │
│ ├─────────────────────────────►│
│ │ │──► Raft propose
│ │ │──► quorum commit
│ │ │──► FSM apply
│ │ 200 OK │──► pub/sub
│ │◄─────────────────────────────┤
│ config/update │ │
│ {scope:"user", │ watch/change (WebSocket) │
│ key:"theme", │◄─────────────────────────────┤
│ value:"dark", │ │
│ version:2} │ │
│◄───────────────────────────┤ │
Repository Structure
diminuendo/concordance/
├── service/ # Concordance server process
│ ├── main.ts # Entry point, CLI args, wiring
│ ├── server.ts # Bun.serve() — HTTP + WebSocket + Raft on one port
│ ├── ws.ts # WebSocket JSON-RPC handler for clients
│ ├── fsm.ts # Finite State Machine — applies Raft entries to KV
│ ├── peers.ts # WebSocket peer connection manager
│ ├── config.ts # Configuration types and defaults
│ └── raft/
│ ├── node.ts # Core Raft consensus algorithm
│ ├── log.ts # SQLite-backed Raft log + stable store
│ ├── snapshot.ts # Snapshot creation and installation
│ └── types.ts # Raft message types and configuration
├── shared/ # Shared between Concordance service and Diminuendo
│ ├── types.ts # KvEntry, ChangeEvent, scope resolution
│ ├── protocol.ts # JSON-RPC types, WS/ACP method definitions
│ ├── schema.ts # SQLite DDL for state.db and raft.db
│ ├── store.ts # KvStore — SQLite-backed KV operations
│ └── index.ts # Barrel export
└── test/ # Test suite