Epimonos Project Bus

Epimonos Project Bus is a small, generic coordination service for auditable human/agent projects. It exposes a stateless MCP Streamable HTTP endpoint and keeps an ordered, append-only event trail alongside relational projections.

The core has no Sandbox, Epimonos product, billing, identity-provider, or backoffice domain logic. A project supplies its own actors, role assignments, work-package contents, decisions, evidence URIs, and repository references.

MVP capabilities

  • isolated projects and actors with one formal role per project;
  • issued, atomically claimed, and evidenced work packages;
  • independent review requests and verdicts;
  • product, architecture, operational, and gate decisions;
  • escalations and formal resolution;
  • commit and artifact references;
  • PM/PO gate closure and baseline-release events;
  • ordered cursor-based event synchronization;
  • idempotent mutations and concurrency-safe local writes;
  • transport-derived identity and role-based authorization;
  • database-level protection against event update and deletion.

Governance invariants

The service enforces these minimum separations:

  • a PA cannot record product, architecture, operational, or gate decisions;
  • only a PO can record a product decision;
  • only a PM or PO can close a gate or release a baseline;
  • the actor who claimed/submitted a result cannot review it;
  • a gate cannot accept a result without an independent APPROVE review;
  • an actor who submitted a result cannot accept it;
  • a baseline can reference only accepted work packages.

These are technical guardrails, not a replacement for the project role contracts or the PM's tolerance and escalation policy.

Quick start

Python 3.12 is the only runtime dependency.

export PYTHONPATH=src
export PROJECT_BUS_BOOTSTRAP_TOKEN='replace-this-with-long-secret'
python -m project_bus --database ./project-bus.db --host 127.0.0.1 --port 8080

Health endpoint:

curl http://127.0.0.1:8080/healthz

Initialize MCP:

curl http://127.0.0.1:8080/mcp \
  -H 'Content-Type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'

Create a project:

curl http://127.0.0.1:8080/mcp \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer replace-this-with-long-secret' \
  --data '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"create_project","arguments":{"project_id":"example","name":"Example","idempotency_key":"bootstrap-example-v1"}}}'

Use register_actor with the bootstrap identity to appoint a PO. Configure the actor's bearer credential through PROJECT_BUS_TOKENS_JSON, then let the PO/PM register the remaining members. Actor identity is always taken from the authenticated bearer credential; callers cannot supply an acting identity in tool arguments.

Example credential configuration:

export PROJECT_BUS_TOKENS_JSON='{
  "long-random-po-token": {
    "actor_id": "po-1",
    "auth_subject": "po-1",
    "display_name": "Product Owner"
  }
}'

The identity must match an actor registered in the target project. Environment changes require a process restart in this MVP.

MCP client configuration

For Claude Code:

claude mcp add \
  --scope project \
  --transport http \
  epimonos-project-bus \
  https://project-bus.example/mcp

For a local-only development server, use the local HTTP URL. Credentials belong in the client/user secret store, never in .mcp.json or Git.

Configuration

Variable Default Meaning
PROJECT_BUS_DATABASE project-bus.db SQLite database path
PROJECT_BUS_MIGRATIONS source-tree discovery Migration directory
PROJECT_BUS_HOST 127.0.0.1 Bind address
PROJECT_BUS_PORT 8080 HTTP port
PROJECT_BUS_BOOTSTRAP_TOKEN required, minimum 24 characters SYSTEM bearer token
PROJECT_BUS_TOKENS_JSON empty Static bearer-token identity map
PROJECT_BUS_ALLOWED_ORIGINS empty Comma-separated exact browser origins
PROJECT_BUS_LOG_LEVEL INFO Python log level

Never expose the bootstrap token. On an internet-facing deployment, terminate TLS at a trusted reverse proxy and set a strict origin allowlist.

Test

PYTHONPATH=src python -m unittest discover -v

The suite uses only temporary databases and includes concurrent writer tests.

Local persistence and production profile

SQLite runs in WAL mode and every mutation uses BEGIN IMMEDIATE. This gives a dependable single-process/single-node MVP and prevents claim and invariant check races. The append-only event table is protected with UPDATE and DELETE rejection triggers.

Production differences are intentionally explicit:

Concern MVP Production target
Database SQLite/WAL, one node PostgreSQL 16+, transactions and row locks
Identity static bearer map OIDC/JWT or mTLS workload identity
Secrets environment secret manager, rotation, revocation
Transport plain HTTP capable TLS-only reverse proxy/service mesh
Scaling one server process multiple stateless MCP instances
Audit durability local DB/backup PITR, replicas, external immutable export
Availability process supervisor orchestrator probes, SLOs, alerting
Abuse control body cap/origin policy edge rate limits, quotas, WAF where useful

The persistence boundary is deliberately small (Database plus SQL in the service), but this release does not contain a PostgreSQL adapter. SQLite must not be mounted on NFS or used for active-active replicas.

Repository guide

  • src/project_bus/ — domain service, auth abstraction, MCP and HTTP adapter;
  • migrations/ — ordered relational schema;
  • tests/ — service, concurrency, governance, and HTTP contract tests;
  • docs/ — architecture, tool contract, threat model, production notes;
  • deploy/ — container and Compose example;
  • work-packages/ — governed implementation and activation scopes;
  • evidence/ — WP-PA-001 verification and independent-review handoff.

See docs/TOOL_CONTRACT.md before integrating a new actor and docs/THREAT_MODEL.md before deployment. Sandbox activation is governed by docs/SANDBOX_ACTIVATION_RUNBOOK.md.

S
Description
No description provided
Readme MIT 110 KiB
Languages
Python 99.4%
Dockerfile 0.6%