Skip to content

v0.3.1 — Plugin Host For Real, Webhook Orchestration, Python Interop

Latest

Choose a tag to compare

@TheGenXCoder TheGenXCoder released this 22 Apr 18:50
· 46 commits to main since this release

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-plugin adopted as the first well-vetted dependency under the new "few well-vetted deps" policy documented in AGENTS.md.
  • Subprocess lifecycleHost.Start(name) launches the plugin binary, performs the go-plugin handshake (magic cookie PLUGIN_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.proto via grpc_tools.protoc connect 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 testedTestPythonPlugin_ValidScopePassesValidation and invalid-scope companion both pass against the actual Python plugin at examples/plugins/python-honeytoken-validator/. Build tag: plugin_python_integration.
  • Full registryScopeValidator, ScopeAnalyzer, ScopeSerializer, and CredentialVender all routable by Kind via parallel Register* / Lookup* / *Kinds functions.
  • CLI subcommandsakms plugin install <path>, akms plugin list, akms plugin remove <name> in cmd/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:

  1. Parse + HMAC-validate the alert (unchanged from v0.3.0)
  2. FindByTokenHash looks up the credential in the audit ledger
  3. 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, update InvalidatedAt via the new AuditStore.UpdateInvalidatedAt method, audit event tagged revoked_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

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

  • Revoker interface: 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; produces ManualRevocationURL).

Notifier interface

  • Notifier.Notify(ctx, event) error — abstracts notification delivery.
  • ConsoleNotifier ships 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.crt

From source

go install github.com/agentkms/agentkms/cmd/agentkms@v0.3.1

CLI client

curl -sL kpm.catalyst9.ai/install | bash
kpm quickstart

Pair 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-grpc for regenerating plugin proto stubs (only needed if modifying api/plugin/v1/plugin.proto)

Breaking changes vs v0.3.0

  • AuditStore interface gains a required UpdateInvalidatedAt(ctx, credentialUUID, at) error method. Any external implementations of AuditStore must 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.protoc were never compatible with v0.3.0 and now are.

What's next

  • v0.3.2 (2-4 weeks): plugin capability advertisement via {binary}.manifest JSON (so plugins can declare which of the four services they implement); CredentialVender pipeline 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