agentleFS
asymmetric-effortasymmetric-effort/convocate/CLAUDE.md

convocate

CLAUDE.md4 starsChanged 4 months agoMITView on GitHub

Convocate is an agentic software-engineering platform. This is a complete v2 rewrite. The repository is a monorepo with three primary services: Falls back to direct OpenBao userpass if SAML_SCIM_AGENT_URL not set. Same pattern on cluster-b with prod.convocate.net.

The file

We split this CLAUDE.md into the rules it gives an agent

7 rules. About 0 are common, 5 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  • could be automatic: a setting could enforce it
  1. Distinctive:

    All DNS is Cloudflare public DNS pointing to internal LAN IPs, accessed via Cloudflare ZTNA tunnel through cloudflared on svr00.

    line 88
  2. Distinctive:

    Every feature needs Playwright PDV: after deploy — done = deploy + PDV pass.

    line 168
  3. Very specific:

    Use published npm @asymmetric-effort/specifyjs — never clone/modify/vendor.

    line 178
  4. Distinctive:

    No recursion — use loops and explicit work-list patterns.

    line 186
  5. Very specific:

    Use gofmt for formatting.

    line 188
  6. Distinctive:

    Use Bun as the runtime and bundler.

    line 193
  7. Distinctive:

    All UI components use @asymmetric-effort/specifyjs.

    line 194

≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
CLAUDE.md

Convocate v2 — Project Instructions

Overview

Convocate is an agentic software-engineering platform. This is a complete v2 rewrite. The repository is a monorepo with three primary services:

  • Web UI — TypeScript + Bun + @asymmetric-effort/specifyjs SPA
  • API — Go 1.26+ REST server
  • SAML/SCIM Agent — Go SAML IdP + SCIM provisioner backed by OpenBao

Architecture

Application Containers (K8s)

ContainerLanguage/RuntimeBuild StageRuntime Stage
Web UIBun + SpecifyJSubuntu:26.04distroless
APIGo 1.26+ubuntu:26.04distroless
Redis—ubuntu:26.04distroless
PostgreSQL—ubuntu:26.04distroless

Infrastructure Services (svr00 Docker)

ServiceIPPurpose
OpenBao secrets-a192.168.3.160Secret store (dev/canary)
OpenBao secrets-b192.168.3.161Secret store (production)
Grafana-a192.168.3.162Monitoring dashboards (dev)
Grafana-b192.168.3.163Monitoring dashboards (prod)
Prometheus-a192.168.3.164Metrics collection (dev)
Prometheus-b192.168.3.165Metrics collection (prod)
VictoriaLogs-a192.168.3.166Log aggregation (dev)
VictoriaLogs-b192.168.3.167Log aggregation (prod)
saml-scim-agent-a192.168.3.168SAML/SCIM auth proxy (dev)
saml-scim-agent-b192.168.3.169SAML/SCIM auth proxy (prod)

K8s Clusters

ClusterNodesIPsRole
cluster-anode-a-0 through 5192.168.3.170–175Canary
cluster-bnode-b-0 through 5192.168.3.180–185Production
  • Traefik ingress controller on node-*-1 (hostPort 443), hostname-based routing
  • Cilium CNI with WireGuard encryption, replaces kube-proxy
  • External Secrets Operator for OpenBao integration

Authentication Flow

Browser → SPA login form → POST /api/v1/auth/login {username, password}
  → API calls saml-scim-agent /saml/login (SAML backend proxy)
  → saml-scim-agent authenticates against OpenBao userpass
  → Returns SAMLResponse with assertions (ed25519 or RSA signed)
  → API extracts identity, mints JWT (ES256)
  → Returns JWT to SPA
  → SPA stores in localStorage, sends as Bearer token on all requests

Falls back to direct OpenBao userpass if SAML_SCIM_AGENT_URL not set.

Routing (Traefik)

app.dev.convocate.net/           → UI service (SPA)
app.dev.convocate.net/api/v1/*   → API service (priority routing)
api.dev.convocate.net/*          → API service (direct)

Same pattern on cluster-b with prod.convocate.net.

DNS Layout

FQDNIPService
api.dev.convocate.net192.168.3.171API (cluster-a Traefik)
app.dev.convocate.net192.168.3.171UI (cluster-a Traefik)
api.prod.convocate.net192.168.3.181API (cluster-b Traefik)
app.prod.convocate.net192.168.3.181UI (cluster-b Traefik)
auth.asymmetric-effort.com192.168.3.161OpenBao secrets-b
dev-auth.asymmetric-effort.com192.168.3.160OpenBao secrets-a
grafana.asymmetric-effort.com192.168.3.163Grafana-b
dev.grafana.asymmetric-effort.com192.168.3.162Grafana-a
saml.asymmetric-effort.com192.168.3.169saml-scim-agent-b
dev.saml.asymmetric-effort.com192.168.3.168saml-scim-agent-a

All DNS is Cloudflare public DNS pointing to internal LAN IPs, accessed via Cloudflare ZTNA tunnel through cloudflared on svr00.

Storage tiering: file-based JSON first, Redis for key-value/sessions, PostgreSQL only when relational queries are truly necessary.

Authoritative Documents

  • API contract: openapi.yaml — the controlling authority for all API endpoints, schemas, and RBAC roles.
  • Specification: SPECIFICATION.md — product requirements and domain model.

Project Layout

src/api/              — Go API server (module: github.com/asymmetric-effort/convocate)
src/agent/            — Go agent (standalone module)
src/saml-scim-agent/  — Go SAML IdP + SCIM provisioner (standalone module)
src/ui/               — Bun + SpecifyJS SPA
  src/ui/cmd/serve/   — Go static file server for SPA
  src/ui/img/         — icon assets
infrastructure/
  bootstrap/          — Ansible roles for svr00 host services
  charts/             — Helm umbrella chart with sub-charts (api, ui, pg, redis, etc.)
  docker/             — Dockerfiles (all services)
  grafana/            — Grafana deploy playbook + provisioning
  k8s/                — Ansible roles/playbooks for K8s cluster provisioning
  prometheus/         — Prometheus deploy playbook
  saml-scim-agent/    — SAML/SCIM agent deploy playbook + PDV tests
  secrets/            — OpenBao deploy playbook + PDV tests
  victorialogs/       — VictoriaLogs deploy playbook + PDV tests
.github/workflows/    — CI/CD pipelines
test/pdv/             — PDV tests
build/                — build artifacts (gitignored)

Build & Run

# Local development (no containers needed)
cd src/ui && bun install && bun run dev    # UI on :8080
cd src/api && go run ./...                 # API on :8443

# Docker Compose (full stack)
docker compose up --build

Make Targets

TargetDescription
make cleanRemove all container images and built artifacts in build/, recreate build/
make lintRun all linters (Go, TypeScript, SQL, Markdown, Makefiles, JS/CSS/HTML, YAML, JSON, Dockerfiles)
make testRun all unit, integration and e2e tests including Playwright browser tests
make buildBuild all container images and GitHub Pages website artifacts
make coverRun code coverage and fail if below 98%

Hard Rules

These rules are non-negotiable. Do not weaken, bypass, or work around them.

Dependencies

  • Zero third-party dependencies unless explicitly approved (see Approved Dependencies below).
  • No pre-built app containers — only ubuntu/alpine/distroless base images. Third-party binaries (Traefik, cloudflared) must be extracted into approved base images.

Security

  • All secrets in OpenBao — never in env vars, config files, or repo.
  • Tokens in files with 0400 perms — never in environment variables.
  • No secrets in repo — leakdetector runs in CI + pre-commit hook. All secrets generated programmatically.
  • All tests use userpass auth like real users — no root tokens in tests.
  • ed25519-only SSH keys — all generated SSH keys must be ed25519. No RSA, no ECDSA. (SAML signing supports both ed25519 and RSA for interoperability.)
  • All auth via SAML through saml-scim-agent against OpenBao — no direct OIDC, no bypasses (exception: Grafana uses OIDC directly against OpenBao).
  • All VMs get owner's GitHub SSH keys (sam-caldwell.keys) + CI key.

Deployment

  • All services on tcp/443 — standard HTTPS port, no non-standard ports.
  • Cluster-a is canary (wipe OK), cluster-b is production (zero-downtime only).
  • Zero-downtime CI deploys only — no destructive ops in deploy workflows.
  • Not done unless both A and B PDV tests pass — deployment is incomplete until verified on both clusters.
  • All fixes via CI/CD — no manual SSH, no manual pipeline triggers unless user explicitly asks.
  • Every feature needs Playwright PDV after deploy — done = deploy + PDV pass.
  • All container deploy workflows require Docker Images prereq — deployment cannot proceed unless latest Docker Images pipeline passed.

Code Quality

  • 100% code complete — build ALL specified capabilities in first pass, don't iterate.
  • >=98% test coverage — happy + sad paths.
  • No recursion in Go — use loops and explicit work-list patterns.
  • CIS benchmark hardening required on svr00 bootstrap.

UI

  • Use published npm @asymmetric-effort/specifyjs — never clone/modify/vendor.

Coding Standards

Authoritative reference: http://coding-standards.asymmetric-effort.com/

Go

  • No recursion — use loops and explicit work-list patterns.
  • ed25519-only SSH keys.
  • Use gofmt for formatting.
  • Tests go in _test.go files alongside the code they test.

TypeScript

  • Use Bun as the runtime and bundler.
  • All UI components use @asymmetric-effort/specifyjs.

Approved Dependencies

PackageLanguagePurpose
@asymmetric-effort/specifyjsTSUI framework
@asymmetric-effort/nogginlessdomTSDOM library
@asymmetric-effort/yamllintTSYAML linter
@asymmetric-effort/jsonlintTSJSON linter
redis/go-redisGoRedis client
jackc/pgxGoPostgreSQL driver
openbao/openbaoGoSecret store client
k8s.io/client-goGoKubernetes API

Everything else must use language standard libraries. Do not add any dependency — including test frameworks, linters, or utility packages — without explicit approval.

API Conventions

  • All endpoints: /api/v1/<applet_shortname>/...
  • Applet shortnames: nmgr, amgr, pb, ide, repo, ac, sup, auth
  • Event channels: /api/v1/events/{applet}/{channel} (WebSocket)
  • Agent shell: /api/v1/amgr/agent/{agentId}/shell (WebSocket)
  • Bearer JWT auth (ES256); RBAC per operation; admin role implies all.
  • JSON request/response bodies.
  • List endpoints use cursor/offset pagination (Page<T>).
  • Timestamps are RFC 3339 UTC.

CI/CD Pipeline Architecture

Fetch Dependencies → Docker Images → {
  K8s Clusters (infrastructure)
  Deploy Applications (API + UI + PG + Redis via Helm)
  OpenBao (svr00 Docker)
  Grafana (svr00 Docker)
  VictoriaLogs (svr00 Docker)
  SAML/SCIM Agent (svr00 Docker)
  Bootstrap svr00 (full host config)
}

Docker Images trigger-deploys job detects which Dockerfiles changed and dispatches only the relevant downstream workflows. All downstream workflows verify Docker Images passed before deploying.

Deploy pattern: deploy-a (canary) → PDV → deploy-b (production) → smoke.

Infrastructure

  • svr00 (192.168.3.159): hypervisor host, Docker services, self-hosted runner
  • Self-hosted runner (192.168.3.90): GitHub Actions runner in Docker container
  • Cloudflared tunnel on svr00: Cloudflare ZTNA access to all services
  • Ansible: VM provisioning, K8s bootstrap, svr00 service deployment
  • Helm 3: K8s application deployment (umbrella chart with sub-charts)
  • Cilium 1.16.6: K8s CNI, WireGuard encryption, host firewall
  • Traefik v3.7: Ingress controller (Helm chart v41.0.2)
  • External Secrets Operator: OpenBao integration for K8s secrets

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.