Files
zeekayandHanzo Dev 4cbdfe4a9b kms is an app, so it builds its own zip.App instead of taking cloud's Deps
The coupling was one string. Mount(app, deps) took hanzoai/cloud's Deps and
read exactly two fields out of it: a logger, which luxfi/log already publishes
as a process default and which Embed has always used, and a data root.
Everything else in that struct crossed the boundary to be discarded. An init()
then pushed this package into cloud's registry so cloud could call Mount back.

That points the dependency the wrong way. It makes the graph circular, since
cloud imports kms in order to mount it, and it fixes the set of possible hosts
at one: two editions of hanzoai/cloud declare the same module path, so
cloud.Deps names a different type in each, and a package that takes it can be
composed by one of them and never the other.

kms.App(root) now builds the app and returns it, and a host composes it with
app.Use. Routes are absolute, so composition neither moves nor shadows them;
the bridge test runs through a host app with middleware in front of it to hold
that. Teardown travels with the app rather than with the process: the Embedded
server drains on a shutdown hook, and zip makes a parent drain the children it
composed, so kms.Shutdown and the package global it read are gone. The readyz
branch that answered 503 when that global was nil went with them, since a
failed Embed returns an error and no app at all.

The daemon read the host's config too, and that was a live bug: it bound
$CLOUD_LISTEN, default :8080, while its own image sets KMS_LISTEN=:8443 and its
HEALTHCHECK curls 8443. It now reads its own, through the one function that
resolves that address for both the daemon and Embed.

zip moves from v1.10.0 to v1.27.2, the version the host already selects,
because Use taking a Component is what makes an app composable at all.
middleware.Logger and the KMS_LOG_LEVEL=debug opt-in around it go with the
bump; zip logs every request itself now, so that report is no longer something
a binary can be missing.

Dropping cloud drops what it dragged in. goja, esbuild and a sourcemap parser
leave the graph: a secret store no longer links a JavaScript engine.

Both go.sum files carried a pre-retag hash for luxfi/vm v1.3.1 that no longer
matches the bits the proxy serves, which failed every build outside the
workspace. Corrected against the checksum database, which agrees with the
download.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-10 12:47:40 -07:00

5.3 KiB

Archived. The canonical KMS is luxfi/kms (ghcr.io/luxfi/kms). This repository is kept read-only for history, and because sdk/go v1.1.1 is still resolvable from it. Nothing new should depend on it. What follows describes the retired server.

Hanzo KMS

Hanzo KMS

Secrets, keys, and threshold signing for the Hanzo platform — per-org namespaces, IAM-gated, ZAP-native, MPC-backed. A thin Go server over the canonical luxfi/kms primitives.

Status License Go

What this is

Hanzo KMS is the canonical secret store and signing service for every Hanzo deployment. It holds the per-tenant DEKs that back Hanzo Base, the provider API keys the AI and gateway services consume, certificate material, and validator signing keys.

AI agents are first-class identities: every secret carries a policy that controls whether an agent may read it — auto-approve, requires-approval, or blocked — with a full per-agent audit trail.

All server logic lives in luxfi/kms. This module wires those primitives with Hanzo defaults (IAM at hanzo.id, encrypted-at-rest storage, S3 replication) and adds JWT verification, the audit ledger, version CAS, and header hygiene. It builds as its own app (kms.App), which any host composes, and also ships as a standalone daemon.

Quick start

Build from source — pure Go, no database toolchain required:

make kmsd kms          # builds ./kmsd (daemon) and ./kms (admin CLI)
KMS_ENV=dev ./kmsd     # HTTP on :8443, ZAP on :9999

Or run the container image (pin a released tag — never :latest):

docker run -p 8443:8443 ghcr.io/hanzoai/kms:vX.Y.Z

In any non-dev environment the daemon refuses to boot without full JWT config (KMS_EXPECTED_ISSUER, KMS_EXPECTED_AUDIENCE, KMS_JWKS_URL) — fail-closed by design.

AI access control

Your secrets, your rules. AI agents are first-class citizens — and so is your ability to block them.

  • Per-secret policies — mark any secret requires-approval; a read from any agent triggers a real-time approval prompt.
  • Auto-approve mode — move fast in development, escalate specific secrets to manual sign-off before production.
  • Identity tracking — see exactly which model, tool, or agent accessed which secret, and when.
  • Full audit trail — every AI-originated read is logged with agent identity, timestamp, and reason.
Secret: STRIPE_LIVE_KEY
  policy:  requires-approval
  reader:  agent via hanzo-mcp
  status:  waiting for approval → [approve] [deny]

API surface

Everything is served under /v1/kms — one canonical path per operation, no aliases, no /api/. Every endpoint requires a Hanzo IAM JWT (RS/ES/PS/EdDSA — never HS*, never none) or an explicit admin role.

Group Endpoints
Auth POST /v1/kms/auth/login — machine-identity client credentials → IAM token
Secrets (per-org) GET / POST / PATCH / DELETE /v1/kms/orgs/{org}/secrets/… — env is a first-class key component; writes require an explicit env; PATCH requires version CAS via If-Match
MPC keys POST /v1/kms/keys/generate · /{id}/sign · /{id}/rotate · GET /v1/kms/keys · /v1/kms/status — threshold BLS / round signing via luxfi/mpc
Health GET /healthz — liveness, no auth

A sub-100µs binary ZAP transport (default :9999) mirrors the HTTP surface for in-cluster callers under the identical JWT + role model. The Go client at sdk/go (HTTP with ZAP fallback) is what every other Hanzo service uses to fetch secrets at runtime.

Storage & durability

  • At rest — ZapDB (LSM) at $KMS_DATA_DIR; per-secret 256-bit DEK wrapped under the master key (AES-256-GCM).
  • Replication — age-encrypted incremental + snapshot backups streamed to S3 (off when unset).
  • Audit — buffered SQLite side-table; single writer, never blocks the request path.

Specs

  • HIP-0027 — KMS
  • HIP-0106 — Unified Cloud Binary (kms subsystem)
  • HIP-0302 — Encrypted SQLite + ZapDB durability (DEK source)

Security

Please do not open public GitHub issues for security vulnerabilities. Email [email protected] with a description and, ideally, a reproduction. We respond quickly.

License

MIT — see LICENSE. Portions are derived from Infisical (MIT, © 2022 Infisical Inc.); see NOTICE. The current request path is a thin wrapper over luxfi/kms; no original upstream server code remains on the wire.


Hanzo — the Open AI Cloud

Open source · every language · on-chain settlement. hanzo.ai · docs.hanzo.ai

SDKs in every language — Python (flagship) · TypeScript · Go · Rust · C++ · Swift · Kotlin · umbrella