AgentKMS v0.3.1 — plugin host for real, webhook orchestration, Python multi-language plugins work.
v0.3.1 closes the gaps between the v0.3.0 release and what the blog series describes. The plugin host is no longer a stub — it's a genuine hashicorp/go-plugin subprocess isolator with standard protobuf gRPC codec, so Python plugins connect for real. The GitHub webhook handler now does the three-branch orchestration Part 6 of the blog describes (revoke, tag-as-detected-after-expiry, or escalate to manual). Audit-store idempotency is durable-store-safe.
Design series: blog.catalyst9.ai. Part 6 covers the webhook orchestration, Part 7 the plugin model.
Highlights
Plugin host — real subprocess isolation with standard protobuf
hashicorp/go-pluginadopted as the first well-vetted dependency under the new "few well-vetted deps" policy documented inAGENTS.md.- Subprocess lifecycle —
Host.Start(name)launches the plugin binary, performs the go-plugin handshake (magic cookiePLUGIN_MAGIC_COOKIE=agentkms_plugin_v1, protocol v1), health-pings every 30s, attempts one restart on failure. - Signature verification enforced at load time — Ed25519 signed binaries only; tampered or unsigned plugin fails before the subprocess launches.
- Standard protobuf codec — gRPC uses the default proto codec. Python plugins built from the published
plugin.protoviagrpc_tools.protocconnect without any Go-side customization. (v0.3.0 shipped a custom JSON codec that broke this; fixed in v0.3.1.) - Python reference plugin end-to-end tested —
TestPythonPlugin_ValidScopePassesValidationand invalid-scope companion both pass against the actual Python plugin atexamples/plugins/python-honeytoken-validator/. Build tag:plugin_python_integration. - Full registry —
ScopeValidator,ScopeAnalyzer,ScopeSerializer, andCredentialVenderall routable by Kind via parallelRegister*/Lookup*/*Kindsfunctions. - CLI subcommands —
akms plugin install <path>,akms plugin list,akms plugin remove <name>incmd/cli/main.go. Install copies the binary + signature sidecar ({binary}.sig) into the plugin directory and verifies before registering.
GitHub webhook orchestration — three-branch decision tree
POST /webhooks/github/secret-scanning now delivers the full workflow Part 6 describes:
- Parse + HMAC-validate the alert (unchanged from v0.3.0)
FindByTokenHashlooks up the credential in the audit ledger- Three branches:
- Already expired → audit event tagged
detected_after_expiry, notifier emits a low-urgency note, no provider call - Still live and programmatically revocable (fine-grained GitHub PAT via
DELETE /installation/token) → revoke, updateInvalidatedAtvia the newAuditStore.UpdateInvalidatedAtmethod, audit event taggedrevoked_on_detection, notifier escalates - Still live but not programmatically revocable (classic PAT, AWS STS) → notifier emits a high-urgency alert with pre-populated manual-revocation URL, audit event tagged
manual_revoke_required
- Already expired → audit event tagged
Audit store idempotency — durable-store safe
The v0.3.0 webhook orchestration relied on pointer-mutation of the record returned from FindByTokenHash, which only worked for in-memory stores. A second webhook against a disk-backed store would see InvalidatedAt=zero and double-revoke. Fixed via the new AuditStore.UpdateInvalidatedAt(ctx, credentialUUID, at) interface method. Idempotency is now correctness for all backends — in-memory, NDJSON, SQL, KV.
Revocation provider abstraction
Revokerinterface:SupportsRevocation() bool+Revoke(ctx, record) (RevokeResult, error)GitHubPATRevoker(fine-grained PAT installation-token revocation),AWSSTSRevoker(no-op — tokens expire, reports cannot-revoke-early),NoopRevoker(fallback for kinds without programmatic revocation; producesManualRevocationURL).
Notifier interface
Notifier.Notify(ctx, event) error— abstracts notification delivery.ConsoleNotifierships in v0.3.1 — writes structured lines to stderr. Slack / email / webhook notifiers are v0.4.
Dependency policy codified
AGENTS.md now includes:
Foundation layer (credentials, crypto, audit, policy engine) stays zero-dep. Only the Go standard library.
Infrastructure layers (plugin host, observability, webhooks) may adopt battle-tested deps when necessary. Each addition requires justification + an entry here.
Approved deps
github.com/hashicorp/go-plugin— P-01, plugin subprocess host. Adopted v0.3.1.
Plus a build-time-dependencies section documenting protoc / protoc-gen-go / protoc-gen-go-grpc for regenerating plugin proto stubs.
Installation
Kubernetes / K3s (recommended)
helm install agentkms ./deploy/helm/agentkms --version 0.3.1 \
--set tls.certFile=/etc/agentkms/tls/tls.crt \
--set tls.keyFile=/etc/agentkms/tls/tls.key \
--set tls.caFile=/etc/agentkms/tls/ca.crtFrom source
go install github.com/agentkms/agentkms/cmd/agentkms@v0.3.1CLI client
curl -sL kpm.catalyst9.ai/install | bash
kpm quickstartPair with KPM v0.2.1 for the full --strict / --secure experience.
Requirements
- Go 1.21+ (build from source)
- Kubernetes or K3s for production
- mTLS PKI (CA, server cert, client certs) — see
docs/deployment/corp-vpc-guide.md - Build-time:
protoc+protoc-gen-go+protoc-gen-go-grpcfor regenerating plugin proto stubs (only needed if modifyingapi/plugin/v1/plugin.proto)
Breaking changes vs v0.3.0
AuditStoreinterface gains a requiredUpdateInvalidatedAt(ctx, credentialUUID, at) errormethod. Any external implementations ofAuditStoremust add it. In-repo implementations updated.- Plugin proto wire encoding changed from custom JSON codec to standard protobuf. Any plugins built against v0.3.0's internal Go stubs must be rebuilt against the regenerated stubs. Python plugins using
grpc_tools.protocwere never compatible with v0.3.0 and now are.
What's next
- v0.3.2 (2-4 weeks): plugin capability advertisement via
{binary}.manifestJSON (so plugins can declare which of the four services they implement);CredentialVenderpipeline wiring (serialize → vend step). - v0.3.x plugin registry (post-launch): community plugin discovery by name.
- v0.4 (longer): real secrets-backend PAT retrieval for GitHubPATRevoker; Slack/email notifiers.
Credits
- Plugin subprocess isolation via hashicorp/go-plugin
- MCP protocol per the Model Context Protocol specification
- License: Apache-2.0