Architecture
Cavalry runs as three long-lived processes backed by Postgres and an S3- compatible object store. Each process has a distinct failure-isolation profile; you can scale them independently.
Processes
- apps/web — Next.js control plane. Serves the UI, the tRPC API, and inbound webhooks (GitHub App, Slack interactions).
- apps/gateway — Hono HTTP service. Every install flows through here. Evaluates policy, serves cached artifacts, proxies upstream registries, and exposes the MCP endpoint.
- services/worker — pg-boss-backed background runner for git syncs, audit webhook delivery, and Slack approval posts.
Shared infrastructure
- PostgreSQL 16 — single source of truth for all metadata. pg-boss creates its own schema; Cavalry uses the
publicschema. - S3-compatible storage — content-addressed tarballs for every published and proxied skill. MinIO works locally.
Data flow: developer installs a skill
- Developer runs
cavalry install tessl:stripe/stripe. - CLI resolves the token + gateway URL, sends GET to
/v1/proxy/tessl/stripe/stripe/:version/artifact. - Gateway authenticates the token, loads the org's policies, and calls the pure policy engine. On deny it returns 403 with problem+json; on pending approval it creates an approval row and returns 202; on allow it proceeds.
- Cache hit? Serve from storage. Cache miss? Fetch upstream, content-address, store, record install + audit event.
- CLI streams the tar.gz into
.cavalry/skills/<ns>/<name>and verifies the sha256.
Data flow: git-backed skill sync
- Platform team installs the Cavalry GitHub App on their org.
- They connect a repo as a skill source; Cavalry probes
cavalry.yamland kicks off an initial sync. - Developer pushes a tag matching the configured pattern (
{skill}/v{version}by default). - Webhook verifies the HMAC signature, dedupes by delivery id, and enqueues a git-sync job.
- Worker: acquires a Postgres advisory lock, reads the skill directory via the provider API (no clone), builds a deterministic tarball, inserts an immutable skill_version row, emits
skill.published. - Force-pushed tags are detected and raise a
skill_repo.force_push_detectedsecurity event. The existing version is never re-derived.
Security boundaries
- Cavalry never writes to customer git repositories on the content path. Any UI-driven edit opens a pull request.
- Installs are always served from content-addressed storage. A git or upstream outage does not affect previously-synced installs.
- skill_versions are immutable. Once inserted, they are never updated. Force-pushes raise an alert instead of rewriting history.
- Secrets (registry tokens, Slack bot tokens, webhook signing keys) are envelope-encrypted at rest via AES-256-GCM keyed off
CAVALRY_ENCRYPTION_KEY.