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).
Providers
Section titled “Providers”The reserved words this plugin serves:
secrets— command classcredential— verb class
What it does
Section titled “What it does”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 + thegpgsubgroup), 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 forsecrets gpg edit, and livegpgshell-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.
Parameter schema
Section titled “Parameter schema”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.
schema/credential.cue
Section titled “schema/credential.cue”// 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.