Skip to main content

Architecture

VaultysClaw is a pnpm/Turborepo monorepo plus one Go binary. The layering is deliberate and enforced by dependency direction: pure decision logic at the bottom, I/O at the top, and nothing pointing the wrong way.

The layering rule​

packages/policy and packages/trust have no database, no network, and no framework. They take already-verified inputs and return decisions.

This is not tidiness for its own sake. resolvePermission is the function a security audit will scrutinise hardest, and it is worth being able to point at one self-contained artefact with property-based tests over random certificate-set combinations — rather than at a function tangled into a web framework's request lifecycle.

The control plane fetches rows and acts on decisions. An SDK evaluates locally with no database in the loop. Both consume the same function.

The packages​

@vaultysclaw/policy​

Certificate wire format and signing. Owns signCert / openCert, the capability_request and capability_grant bodies, the AgentCapability enum, ResourceLimits, and single-certificate enforcement gates.

Also owns decodeCertUnsafe — decode without verifying, for display only, used by the console's certificate inspector to show a payload even when verification fails.

@vaultysclaw/trust​

resolvePermission(action, activeCerts, now) and the CertScope types. The multi-certificate ABAC decision function.

Kept separate from policy on purpose: resolving over a set of concurrent, overlapping, scoped certificates is a different responsibility with a different test shape — property and fuzz tests over random combinations, not gate-by-gate unit tests. Two invariants are asserted directly:

  • Revoking a certificate never grants more access.
  • Adding a certificate never removes access, except through an explicit scope-narrowing supersession.

It contains no signing or verification. It takes opened, verified payloads.

@vaultysclaw/shared​

Cross-package types and the webhook event catalog — the single source of truth for event types, labels, and groups, shared by both control-plane packages so they cannot fork.

@vaultysclaw/controlplane​

The rebuilt control plane: Next.js App Router, a WebSocket server, Prisma over Postgres, all in one custom-server process. This is the only package that persists anything or drives the pure packages with I/O.

Architectural notes worth knowing before reading the code:

  • Server Actions over DAOs, not a typed REST contract. There is no ts-rest layer and, today, no REST API surface at all.
  • The WebSocket server is a module-level singleton, which is what lets a Server Action reach the live connection map to deliver a certificate to a connected Actor.
  • The handshake state is in-process, not round-tripped through a session row — this is a long-lived process, not a stateless serverless function.

See Control plane.

@vaultysclaw/sdk and sdk-go​

The two SDKs: everything a third party needs to build an Actor. Identity, transport, the register → approval → certificate lifecycle, reconnection, and local permission decisions.

You instantiate an ActorRuntime; there is nothing to subclass, because the control plane dispatches no work.

The Go SDK additionally carries offline certificate verification (grant), signed rule sets (rules), and a full port of the permission resolver (authz) — both languages run the same /conformance vectors, and a divergence is a release blocker.

See Building an Actor.

@vaultysclaw/agent-runtime is the previous runtime

It targets the older control plane and cannot connect to this one. It remains in the repository, unchanged, because agent-controller and mcp-gateway still depend on it.

@vaultysclaw/webhook-dispatcher​

A standalone BullMQ worker. One worker fans every event out to both subscription kinds — signed webhooks and Apprise notification channels. It is not two pipelines.

It must be run as a separate process; the control plane enqueues, and if nothing consumes, events sit in the queue forever. The console has a health panel specifically to surface that, because reachability of Redis and Apprise does not answer "is anything actually consuming this queue".

vaultysclaw-sensor (Go)​

Three roles from one binary, each opt-in — enabling one is always a deliberate act, never a consequence of upgrading:

  • Observe — polls process and socket state, classifies AI and agent workloads from a data-driven rule catalog, and reports graded telemetry with confidence scores and reasons. Registers as sensor. Gated entirely on process_read.
  • Intercept — a CONNECT proxy that refuses traffic its signed rule set and certificate do not authorise. Registers as proxy. Decides offline from periodically-refreshed artefacts, with a durable audit spool that emits gap markers rather than silently dropping records when it overflows.
  • Supervise — launches a coding harness and decides every tool call locally from a signed grant and rule set. Registers as harness. Governs resource URIs where the proxy governs network destinations, which is why the two carry different halves of one signed rule-set format rather than two formats.

It contains a Go port of resolvePermission. Both implementations run the same committed conformance vectors, and a divergence between them is a release blocker.

@vaultysclaw/agent-controller and @vaultysclaw/mcp-gateway​

The reference implementations of the openclaw and mcp kinds respectively. Both still target the previous control plane via @vaultysclaw/agent-runtime; migrating them onto @vaultysclaw/sdk is outstanding work.

What the rebuild removed​

The rebuilt control plane lives alongside the older proof-of-concept (packages/control-plane), not in place of it. Nothing points production traffic at the rebuild until a cutover is deliberate.

The rebuild deleted, rather than reimplemented: the workflow engine, channel collaboration and chat, Teams and generic bridges, the in-app/email/push notification stack, the end-user settings area, and three parallel grant models that all collapsed into the one certificate ledger.

See What was removed, and why.