Single source of truth for running the DieWan Accountability stack in
containers. This directory supersedes the per-repo start.sh/stop.sh and the
scattered development/demo/*.sh scripts for containerized runs (the host-mode
cargo run / dx serve workflow still works and is unchanged).
- Docker files:
docker/— one Dockerfile per service (plus the sharedDockerfile.rust-base). - Compose profiles:
compose/—infra/apps/demo. - Scripts:
scripts/—up/down/seed/health. - Environment:
env/.env.example— every variable the compose files read.
flowchart LR
subgraph infra[infra profile]
PG[(Postgres · 55432)]
end
subgraph apps[apps + demo profiles]
FEED[piteka-evidence-feed · 3200]
API[piteka-api / web · 3000]
TAPI[tuppira-api · 8081]
MCP[parwana-mcp · 3100]
HEM[hemion web · 8181]
end
ING([tuppira-ingest · live watcher · demo])
API -->|reads/writes live state| PG
FEED -->|reads evidence| PG
FEED -->|GET /feed ed25519-signed| ING
ING -->|normalize + persist| TAPI
TAPI -->|lineage read model| HEM
MCP -.->|read-only protocol inspection| HEM
The evidence chain is pull-only: Piteka stays the single GitHub webhook consumer and exports a signed feed; Tuppira consumes that feed rather than registering a competing webhook.
The topology above is the deployment view (containers, ports, data flow). For the organization-wide "you are here" view of the five repositories, see
development/ARCHITECTURE.md.
Key terms specific to running the stack:
| Term | Kind | Plain-English meaning | Real-world example |
|---|---|---|---|
| Profile | Keyword | A named slice of the stack to bring up: infra, apps, or demo. |
Docker Compose profiles — pick which services start together. |
| Mandate | Data structure | The pre-action authorization the demo trace approves and drills into. | A signed work order approving one specific deployment. |
| Receipt | Data structure | Evidence of what actually happened, exported by Piteka's feed. | A deploy log entry bound to the approval that authorized it. |
| Evidence | Keyword | The verifiable records the signed feed publishes and Tuppira ingests. | The signed documents in a case file, streamed as they're created. |
| Observation | Keyword | Tuppira's read-only indexing of the ingested evidence; it never authorizes. | A CCTV recorder filing each event as it arrives. |
| Lineage | Keyword | Tuppira's queryable trace of related observations, surfaced to Hemion. | A parcel-tracking view assembled from raw scan events. |
| Service | Port | Purpose |
|---|---|---|
| piteka-api / web | 3000 | Approval UI + REST API + /health |
| parwana-mcp | 3100 | Read-only protocol inspector (SSE /sse) |
| piteka-evidence-feed | 3200 | Signed evidence pull feed (/feed, /health) |
| tuppira-api | 8081 | Observation read model (/api/v1/...) |
| hemion (web) | 8181 | Developer console (static bundle) |
| postgres | 55432 | Piteka live-state authority |
All host port bindings are loopback-only (127.0.0.1) by default, matching the
existing Postgres policy.
| Profile | Brings up | Use when |
|---|---|---|
infra |
Postgres only | Running the apps on the host (cargo run / dx serve) — reproduces today's workflow. |
apps |
Postgres + all six app services | Full stack in containers, without the demo seed ingest. |
demo |
apps + continuous Piteka→Tuppira ingest, ordered start |
Demonstrating the live end-to-end accountability trace. |
cd deployment
./scripts/seed.sh # generate demo env/.env, feed seed, verifying key
./scripts/up.sh demo # build + start the full trace (ordered)
./scripts/health.sh demo # all services green + a live Tuppira lineage queryThen open:
- Piteka approval UI — http://127.0.0.1:3000/work-queue (there is no
/route; other views:/case-files,/executions,/verification,/settings) - Hemion console — http://127.0.0.1:8181/explorer shows the live accountability
feed and polls Tuppira every three seconds.
/explorer/tuppiraprovides the feed plus exact observation-lineage inspection. Both default to the local Tuppira API and demo tenant credentials. Piteka allows these local Hemion origins throughPITEKA_CORS_ORIGINS, enabling mandate and receipt drill-down.
Stop it (keeping the Postgres volume):
./scripts/down.sh demo # data survives
./scripts/down.sh demo -v # also wipe Postgres + Tuppira data volumesValidate that this runbook has not drifted from checked-in scripts, local
links, Compose variables, and env/.env.example:
python3 ../development/agent-workflow/check_documentation_drift.pyReproduce the legacy "infra in Docker, apps on host" workflow:
cd deployment
./scripts/up.sh infra
# …then run app repos on the host as before (piteka/start.sh, etc.)-
The shared builder base
docker/Dockerfile.rust-basecompiles parwana's dependency graph once (cargo-chef) so every Rust service image reuses it. Build it first:docker build -f deployment/docker/Dockerfile.rust-base -t diewan/rust-base:latest ..
(
scripts/up.shbuilds service images on demand; build the base once up front, or setRUST_BASEto a registry tag.) -
Pin the upstream Rust image by digest in CI:
--build-arg RUST_BASE_IMAGE=rust:1.95-slim-bookworm@sha256:<digest>. -
Toolchain is Rust 1.95 (
rust-toolchain.toml); all Rust builds are--locked.
Every variable the compose files read is documented in
env/.env.example. scripts/seed.sh writes a working
env/.env with demo values. Secrets (the ed25519 feed seed) live under
env/secrets/ and are git-ignored; all demo keys/tokens are non-production.
Honest limitations of the current foundation, tracked for follow-up. Items 1, 2 and 4 below are resolved as of the last update; they are kept here as a record of what was fixed.
Resolved. The bind is now configurable viapiteka-webbinds127.0.0.1:3000inside the containerPITEKA_WEB_BIND(default127.0.0.1:3000, mirroringPITEKA_FEED_BIND); the apps compose sets0.0.0.0:3000so the published loopback port is reachable from the host. The UI lives at/work-queue(no/route).Hemion web (WASM) build maturityResolved for the demo. The image buildsdx build --release --platform weband serves it (HTTP 200). The Tuppira explorer defaults its API URL tohttp://127.0.0.1:8081, and Tuppira allows that cross-origin call (cors_originsinconfig.testnet.tomllistshttp://127.0.0.1:8181+http://localhost:8181), so lineage queries work from the browser. Hemion's primary target remains desktop.- Demo evidence must exist. The evidence feed publishes receipts from
Postgres; a fresh volume is empty. The
demoprofile's seed and continuously runningtuppira-ingestpopulate it and ingest receipts created after startup; a freshdown -vwipe requires re-seeding. Richer scenario evidence is owned by the DEMO-01/DEMO-02 tickets. FullResolved. All six service images now build and run end-to-end here;docker buildverification is deferred./scripts/health.sh demois fully green including the live Tuppira lineage probe.
development/demo/README.md— host-mode demo runbook.development/demo/PITEKA_TUPPIRA_HEMION_TRACE.md— the trace this compose containerizes.CHANGELOG.md— deployment changelog.