secrets

package
v0.22.146 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 2, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package secrets stores per-source credentials separately from config.toml.

Per ADR-008, secrets live at ~/.config/clawtool/secrets.toml (mode 0600). Keeping them out of config.toml means the latter can be safely committed to a repo / synced via dotfiles, while credentials stay machine-local.

The store is structured as: scope (= source instance name) → key/value map. Scope "global" holds env that applies to every source.

Resolve() interpolates ${VAR} references in a config-supplied env map against secrets first, then the process env, returning the env that should be set on a spawned source process.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultPath

func DefaultPath() string

DefaultPath returns ~/.config/clawtool/secrets.toml (or the XDG variant). Mirrors config.DefaultPath but with the secrets.toml filename.

func ScrubEnv added in v0.22.36

func ScrubEnv(parent []string) []string

ScrubEnv returns a fresh slice safe to assign to cmd.Env. Pass os.Environ() (or any []string of "K=V" entries). The input slice is NOT mutated.

When CLAWTOOL_KEEP_SECRETS=1 is set on the parent process, the function passes the env through unchanged — explicit opt-out for the rare cases where the operator wants the pre-octopus behaviour. The opt-out is logged once on stderr when the package is first imported... actually, it's a per-call decision, so no logging here; the caller can warn if they want that visible.

Types

type Store

type Store struct {
	Scopes map[string]map[string]string `toml:"scopes,omitempty"`
}

Store is the in-memory representation of secrets.toml.

func LoadOrEmpty

func LoadOrEmpty(path string) (*Store, error)

LoadOrEmpty reads the secrets file. A missing file is not an error; we return an empty store so callers can Set+Save without first running an init step.

func (*Store) Delete

func (s *Store) Delete(scope, key string)

Delete removes a key from a scope. Empty scopes are pruned to keep the on-disk file tidy.

func (*Store) Expand added in v0.9.0

func (s *Store) Expand(scope, v string) (string, []string)

Expand resolves every ${VAR} reference in v against the secrets scope first, then the "global" scope, then the process env, returning the expanded string plus the list of variable names that could not be resolved (in encounter order, deduplicated).

A literal without any ${...} substring is returned verbatim with no missing entries — this is the hot-path callers depend on so they don't pay the regex cost on plain values.

func (*Store) Get

func (s *Store) Get(scope, key string) (string, bool)

Get returns the value for (scope, key). It checks the requested scope first, then the "global" scope, then returns ok=false. This lets the user define shared values once in [scopes.global] and override per instance only when needed.

func (*Store) Rename added in v0.22.2

func (s *Store) Rename(oldScope, newScope string) bool

Rename moves every secret stored under `oldScope` to `newScope`. Returns true when at least one key was moved, false when oldScope was empty or absent. If newScope already has keys, oldScope's values overwrite collisions — the caller is expected to refuse the rename earlier (config-side instance collision check) so reaching the secrets layer with an existing target is a logic error in the caller, not user-survivable input. Empty oldScope / newScope are normalised to "global" the same way Set / Get do.

func (*Store) Resolve

func (s *Store) Resolve(scope string, template map[string]string) (resolved map[string]string, missing []string)

Resolve takes the env map a catalog entry asks for (e.g. {GITHUB_TOKEN: "${GITHUB_TOKEN}"}) and returns the env that should be set on the spawned source. Each ${VAR} reference is filled in by:

  1. The store at scope+key, then store global+key
  2. The process env
  3. Empty string (with `missing` populated so callers can warn)

Plain (non-${...}) values are passed through unchanged.

func (*Store) Save

func (s *Store) Save(path string) error

Save writes the store to path with mode 0600 (creating the parent dir with mode 0700 if necessary). Atomic via temp+rename so a crash never leaves a half-written secrets file.

func (*Store) Set

func (s *Store) Set(scope, key, value string)

Set assigns a value to (scope, key). Scope "" maps to "global".

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL