Skip to content

Commit 7ef4b1a

Browse files
hyperpolymathclaude
andcommitted
chore: close three open items — credential forwarding, minter removal, seed infra
1. Credential forwarding (Options A+B closed): Gap was already wired — CredentialDecryptor.extract/2 → dispatch → Invoker.invoke(extra_env) → subprocess env vars. Documented in STATE.a2ml. Option C (RGTV broker) remains future work. 2. Retire tools/cartridge-minter/ (Node.js, banned language): Deleted 10 files (Node.js + Rust sources). Updated references in: Justfile (Cargo check → launch-scaffolder), QUICKSTART-USER.adoc, llm-warmup-dev.md, llm-warmup-user.md. canonical tool is launch-scaffolder. 3. Seed node deployment infrastructure: - container/compose.prod.yaml: production Podman Compose using ghcr.io image; all 4 continental seed peers pre-configured; security hardened (read-only fs, no-new-privileges, tmpfs). - QUICKSTART-USER.adoc: added "Running a Production Node" section with podman-compose and Quadlet instructions. - container-publish.yml: fix stale label "99 → 112 cartridges". 173 ExUnit tests, 0 failures. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0ba1e5d commit 7ef4b1a

18 files changed

Lines changed: 136 additions & 4268 deletions

File tree

.github/workflows/container-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ jobs:
6464
--tag "${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.version }}" \
6565
--tag "${{ steps.meta.outputs.image }}:latest" \
6666
--label "org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}" \
67-
--label "org.opencontainers.image.description=Bundle of Joy MCP Server — 99 formally verified cartridges" \
67+
--label "org.opencontainers.image.description=Bundle of Joy MCP Server — 112 cartridges (111 Zig FFI + 1 JS)" \
6868
--label "org.opencontainers.image.licenses=PMPL-1.0-or-later" \
6969
--label "org.opencontainers.image.version=${{ steps.meta.outputs.version }}" \
7070
.

.machine_readable/6a2/STATE.a2ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ v-lang-files = 0 # all .v files removed 2026-04-12
5353
[open-gaps]
5454
# Ordered by impact on users hitting POST /cartridge/:name/invoke
5555
gap-1 = "PARTIALLY CLOSED 2026-04-25 — X-Trust-Level enforcement implemented (BojRest.TrustPolicy); keyed cartridges require authenticated/internal trust from non-loopback callers. Credential forwarding (Options A/B/C) still undecided."
56-
gap-2 = "Credential forwarding in federation — user API keys live on their node, not on volunteer nodes"
56+
gap-2 = "CLOSED for Options A+B 2026-04-25 — Option A (caller-supplied encrypted creds in request body) wired: CredentialDecryptor.extract/2 → dispatch → Invoker extra_env → subprocess env vars. Option B (node-level env vars) inherits from server process. Option C (RGTV broker) remains future work."
5757
gap-3 = "Load-aware inter-node routing not wired — invocations are local only"
58+
gap-5 = "Seed nodes not yet deployed — DNS records and actual infrastructure not provisioned; compose.prod.yaml and boj-community-node.container ready 2026-04-25"
5859
gap-4 = "CLOSED 2026-04-25 — Test coverage reached CRG C (165 tests: 10 properties + 155 regular, 0 failures)"
5960

6061
[critical-next-actions]
@@ -72,6 +73,7 @@ test-coverage = "CLOSED 2026-04-25 — 165 ExUnit tests; CRG C met"
7273

7374
[session-history]
7475
entries = [
76+
{ date = "2026-04-25", description = "Items 1+2+3 session: (1) Credential forwarding gaps A+B closed — chain fully wired (CredentialDecryptor → dispatch → Invoker extra_env → subprocess env vars). Option C (RGTV) future work. (2) tools/cartridge-minter/ DELETED — Node.js banned artefact. Justfile, QUICKSTART-USER.adoc, llm-warmup-dev.md, llm-warmup-user.md updated to reference launch-scaffolder. (3) Seed node infra: compose.prod.yaml created (production Podman Compose using ghcr.io image, all 4 seed peers pre-wired); QUICKSTART-USER.adoc seed node section added; container-publish.yml label updated 99→112 cartridges. container/boj-community-node.container + seed-nodes.toml already existed." },
7577
{ date = "2026-04-25", description = "Phase 9 auth (partial): (1) BojRest.TrustPolicy — maps auth.method→exposure (:public/:authenticated), checks X-Trust-Level header; loopback bypass. (2) Router wired: X-Trust-Level enforcement in invoke handler; X-Node-Identity audit logging. (3) trust_policy_test.exs (11 tests); 7 new router auth tests. (4) Justfile test/test-verbose rewritten as loops (111 cartridges, was hardcoded 17). Total: 173 ExUnit tests, 0 failures." },
7678
{ date = "2026-04-25", description = "FFI wiring complete — all 111 cartridges now have compiled .so + ffi key in cartridge.json. Scaffolded 12 remaining cartridges (6 with existing stub Zig source replaced with clean ADR-0006 impl: academic-workflow-mcp, bofig-mcp, ephapax-mcp, fireflag-mcp, hesiod-mcp, sanctify-mcp; 6 written from scratch: claude-agents-power-mcp, coderag-mcp, local-memory-mcp, notifyhub-mcp, opendatamcp, origenemcp). Each: *_ffi.zig (5-symbol ADR-0006 ABI + tool stubs) + build.zig + cartridge_shim.zig + canonical ffi block in cartridge.json with so_path=ffi/zig-out/lib/lib<module>.so. All 12 build clean, all 12 pass boj-invoke probe. 165 Elixir tests still 0 failures." },
7779
{ date = "2026-04-25", description = "CRG D→C test expansion: (1) Added invoker_test.exs (15 tests — cli_path resolution, exit-code classification via fake_boj_invoke fixture, successful probe/name/version/invoke, extra_env). (2) Added js_worker_pool_test.exs (9 tests — pool_size, consistent-hash routing, fallback, E2E). (3) Added catalog_properties_test.exs (10 StreamData properties — round-trips, structural invariants, CredentialDecryptor properties). (4) Added contract_test.exs (15 contract tests — Catalog↔Router, NodeKey↔CredentialDecryptor, Router↔Invoker dispatch). (5) Added aspect_test.exs (15 aspect tests — no-crash, content-type, security, idempotency). (6) Added benchmarks/boj_bench.exs (10 Benchee scenarios). (7) Extended catalog_test.exs + router_test.exs + node_key_test.exs + credential_decryptor_test.exs + js_invoker_test.exs with 80+ additional tests. (8) Fixed bofig-mcp, hesiod-mcp, academic-workflow-mcp cartridge.json (missing spdx/domain/tier/auth/so_path fields). Total: 165 tests (10 properties + 155 regular), 0 failures. Grade D→C achieved." },

Justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,7 @@ doctor:
11051105
echo ""
11061106
echo "Optional tools:"
11071107
check_optional "V (vlang)" v "deprecated/banned 2026-04-10"
1108-
check_optional "Cargo" cargo "needed for tools/cartridge-minter"
1108+
check_optional "Cargo" cargo "needed by launch-scaffolder (mint/provision/config)"
11091109
check_optional "cloudflared" cloudflared "needed for tunnel"
11101110
check_optional "panic-attack" panic-attack "pre-commit scanner"
11111111
check_optional "podman" podman "container builds"

QUICKSTART-USER.adoc

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Three-class architecture: Class 1 (simple CLI), Class 2 (orchestrator with webho
3434

3535
| Rust / Cargo (optional)
3636
| >= 1.80
37-
| For `tools/cartridge-minter` only
37+
| For `launch-scaffolder` (mint/provision/config cartridges)
3838
|===
3939

4040
Verify all tools:
@@ -177,10 +177,36 @@ elixir/ Elixir/BEAM REST server (Catalog, Router, JsWorkerPool)
177177
cartridges/ One dir per cartridge (112 total)
178178
database-mcp/ Example: Idris2 ABI + Zig FFI + mod.js adapter
179179
container/ Stapeln container ecosystem
180-
tools/cartridge-minter Rust CLI for minting new cartridges
180+
tools/ Cartridge tooling (provisioner, configurator, harness)
181181
.machine_readable/ State, policies, contractiles
182182
----
183183

184+
== Running a Production Node (Umoja Federation)
185+
186+
To run a community node that joins the Umoja seed network:
187+
188+
[source,bash]
189+
----
190+
# Pull the latest image
191+
podman-compose -f container/compose.prod.yaml pull
192+
193+
# Start (daemonised)
194+
podman-compose -f container/compose.prod.yaml up -d
195+
196+
# Check it is live
197+
curl http://localhost:7700/health
198+
----
199+
200+
The four continental seed nodes (`eu`, `de`, `us`, `ap` at `boj.hyperpolymath.dev:9999`)
201+
are pre-configured as bootstrap peers. Set `BOJ_NODE_ID` to give your node a stable
202+
identity in the gossip network.
203+
204+
For Podman Quadlet (systemd service), copy
205+
`container/boj-community-node.container` to
206+
`~/.config/containers/systemd/` and run `systemctl --user start boj-community-node`.
207+
208+
The four canonical seed nodes are declared in `container/seed-nodes.toml`.
209+
184210
== Further Reading
185211

186212
- `docs/ARCHITECTURE.md` -- 2D matrix design

container/compose.prod.yaml

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# SPDX-License-Identifier: PMPL-1.0-or-later
2+
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
3+
#
4+
# BoJ Server — production node compose (Podman Compose compatible)
5+
#
6+
# Runs a fully operational BoJ node from the pre-built ghcr.io image.
7+
# Suitable for Umoja seed nodes and community volunteer nodes.
8+
#
9+
# Usage:
10+
# # Pull latest image
11+
# podman-compose -f container/compose.prod.yaml pull
12+
#
13+
# # Start (daemonised)
14+
# podman-compose -f container/compose.prod.yaml up -d
15+
#
16+
# # View logs
17+
# podman-compose -f container/compose.prod.yaml logs -f boj-rest
18+
#
19+
# # Stop
20+
# podman-compose -f container/compose.prod.yaml down
21+
#
22+
# Seed node environment variables:
23+
# BOJ_NODE_ID Stable node name (defaults to hostname; set for seeds)
24+
# BOJ_SEED_NODES Comma-separated host:port pairs to bootstrap federation
25+
# Defaults to the four continental Umoja seed nodes.
26+
#
27+
# For credential-forwarded cartridges set the relevant env vars:
28+
# GITHUB_TOKEN, NOTIFYHUB_API_KEY, etc.
29+
# Callers can also supply credentials encrypted in the request body (Option A);
30+
# see docs/AUTH-DESIGN.adoc for the full credential forwarding design.
31+
32+
services:
33+
boj-rest:
34+
image: ghcr.io/hyperpolymath/boj-server:latest
35+
container_name: boj-node
36+
restart: unless-stopped
37+
ports:
38+
- "7700:7700"
39+
- "9999:9999/udp"
40+
volumes:
41+
- boj-node-data:/data:Z
42+
environment:
43+
# Server binding
44+
APP_HOST: "[::]"
45+
APP_PORT: "7700"
46+
APP_DATA_DIR: "/data"
47+
APP_LOG_FORMAT: "json"
48+
# Federation
49+
BOJ_QUIC: "1"
50+
BOJ_FEDERATION_PORT: "9999"
51+
# Override with a memorable name for seed nodes, e.g. "seed-eu-west"
52+
# BOJ_NODE_ID: ""
53+
# Bootstrap peers — defaults to all four Umoja seed nodes.
54+
# Override for private/staging networks.
55+
BOJ_SEED_NODES: "eu.boj.hyperpolymath.dev:9999,de.boj.hyperpolymath.dev:9999,us.boj.hyperpolymath.dev:9999,ap.boj.hyperpolymath.dev:9999"
56+
security_opt:
57+
- no-new-privileges:true
58+
read_only: true
59+
tmpfs:
60+
- /tmp:size=64m,noexec,nosuid,nodev
61+
healthcheck:
62+
test: ["CMD", "curl", "-sf", "http://localhost:7700/health"]
63+
interval: 30s
64+
timeout: 10s
65+
retries: 3
66+
start_period: 30s
67+
68+
capability-gateway:
69+
image: ghcr.io/hyperpolymath/boj-server:latest
70+
container_name: boj-gateway
71+
restart: unless-stopped
72+
entrypoint: ["/app/gateway/bin/http_capability_gateway", "start"]
73+
depends_on:
74+
boj-rest:
75+
condition: service_healthy
76+
ports:
77+
- "7800:7800"
78+
environment:
79+
GATEWAY_PORT: "7800"
80+
GATEWAY_UPSTREAM: "http://boj-rest:7700"
81+
BOJ_CARTRIDGES_ROOT: "/app/cartridges"
82+
GATEWAY_LOG_FORMAT: "json"
83+
security_opt:
84+
- no-new-privileges:true
85+
read_only: true
86+
tmpfs:
87+
- /tmp:size=32m,noexec,nosuid,nodev
88+
healthcheck:
89+
test: ["CMD", "curl", "-sf", "http://localhost:7800/health"]
90+
interval: 30s
91+
timeout: 10s
92+
retries: 3
93+
start_period: 15s
94+
95+
volumes:
96+
boj-node-data:
97+
driver: local

llm-warmup-dev.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,11 @@ web-ecosystem/
8484
lib/http_capability_gateway/
8585
policy_loader.ex load_from_boj_catalog/1 — auto-generates policy from cartridge.json
8686
87-
tools/cartridge-minter/ Rust CLI for minting new cartridges
88-
Cargo.toml
87+
tools/ Cartridge tooling (provisioner, configurator, harness)
88+
cartridge-provisioner/
89+
cartridge-configurator/
90+
panel-harness/
91+
# Note: cartridge-minter (Node.js, banned) removed 2026-04-25. Use launch-scaffolder.
8992
9093
panll/src/ PanLL panel (ReScript/TEA)
9194

llm-warmup-user.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ just doctor # Check toolchain
3636
## Prerequisites
3737

3838
Idris2 >= 0.7.0, Zig >= 0.13, V (vlang) >= 0.4.4, just >= 1.25.
39-
Optional: Cargo (for cartridge-minter tool), cloudflared (for tunnels).
39+
Optional: Cargo (for launch-scaffolder — mint/provision/config cartridges), cloudflared (for tunnels).
4040

4141
## Cartridges (70+)
4242

0 commit comments

Comments
 (0)