Skip to content

plugin-secrets

Placement runtime (out-of-process over gRPC)
Source github.com/opencharly/charly/candy/plugin-secrets
Version 2026.178.2100
Candy plugin-secrets

This plugin is not listed in charly/charly.yml’s compiled_plugins:. It is not part of the shipped binary: charly builds and loads it out-of-process over gRPC when a plan references one of its words (the coexist path).

The reserved words this plugin serves:

  • secrets — command class
  • credential — verb class

OUT-OF-TREE charly plugin serving the ENTIRE secrets subsystem — a standalone Go module (go.mod + main.go) that owns the credential store (Secret Service / config-file backends, the iteration-capable godbus client) AND the GPG .secrets surface, so github.com/zalando/go-keyring lives HERE, out of charly’s core binary entirely (the C2 dep-shed removed go-keyring from charly/go.mod). charly’s loader fetches this candy’s repo, go-builds the provider binary on the HOST, and serves it OUT-OF-PROCESS via LocalTransport — or runs the host-installed /usr/lib/charly/plugins binary on a project-less host. It provides TWO capabilities:

  • verb:credential — the externalized CREDENTIAL STORE BACKEND (NOT a check verb). charly’s core pluginCredentialStore (charly/credential_plugin.go) forwards every CredentialStore method (get/set/delete/list/name), the env-less resolve (resolve → {value,source}), the doctor keyring health probe (health), and the keyring re-probe (reset) over go-plugin gRPC. Every core credential consumer (enc.go / secrets.go / layer_secrets.go / runtime_config.go / vnc_helpers.go) is UNCHANGED — it resolves secret_require / secret_accept / VNC / enc passphrases exactly as before.

  • command:secrets — charly secrets … (list / get / set / delete / import / export / migrate-secrets + the gpg subgroup), the externalized secrets CLI. charly DISPATCHES the command by syscall.Exec’ing this binary in CLI mode (sdk.Main → cliMain), so it owns real terminal stdio: secure password prompts (term.ReadPassword), $EDITOR for secrets gpg edit, and live gpg shell-outs all reach the real terminal.

verb:credential is served over gRPC (the provider registry); command:secrets is served via the CLI syscall.Exec path — so command:secrets is declared in plugin.providers (for the CLI-grammar prescan + baked manifest) but NOT advertised in Describe. The R10 consumer is a deploy that resolves a secret_require/secret_accept through the externalized store (e.g. check-k3s-vm’s K3S_CLUSTER_TOKEN autogen, or a pod bed) plus a host charly secrets round-trip.

The CUE schema below is the authoritative grammar for this plugin’s input. It is the same single source that generates the plugin’s Go parameter types and answers the runtime Describe RPC, so this page cannot disagree with either.

// The OUT-OF-TREE plugin-secrets' OWN CUE schema — the typed params for the
// `credential` store-backend VERB (verb:credential). It is the SINGLE SOURCE for
// this plugin's params, used two ways (the same contract the reference
// examplerunverb + core `spec` use):
//
// 1. GENERATE the Go param struct — `cue exp gengotypes` (driven by task cue:gen,
// which wraps this with `package params` + `@go(params)`) emits
// ../params/cue_types_gen.go, so the provider decodes the credential operation
// into a TYPED struct, never a hand-parsed map.
// 2. VALIDATE / non-empty-schema load gate — the host splices this onto the base
// (base ++ plugin) at connect; verb:credential carries no AUTHORED plugin_input
// (its params are an internal RPC the core credential adapter sends, NOT a plan
// step), so it advertises an EMPTY InputDef and this schema exists to satisfy the
// host's non-empty-schema load gate (mirrors candy/plugin-mcp's schema/mcp.cue).
//
// SELF-CONTAINED: every field is a bare primitive referencing NO base def, so it
// compiles standalone (gengotypes + the load-gate compile) AND splices onto the base
// — the splice exists to detect a def-name collision with the base, not to resolve refs.
//
// verb:credential is NOT a check verb — it is the externalized CREDENTIAL STORE
// BACKEND. The core's pluginCredentialStore (charly/credential_plugin.go) forwards
// every CredentialStore method (get/set/delete/list/name), the env-less resolve
// (resolve → {value, source}), the doctor health probe (health), and the keyring
// re-probe (reset) over this verb's Invoke envelope.
#CredentialInput: {
// method — the store operation: get | set | delete | list | name | resolve | health | reset | await-unlock.
method: string & !="" @go(Method)
// service — the credential service namespace (e.g. "charly/secret", "charly/vnc").
service?: string @go(Service)
// key — the entry key within the service.
key?: string @go(Key)
// value — the value to store (set only).
value?: string @go(Value)
}

See also the candy reference for this candy’s install surface.