picoclaw/pkg
sky5454 2f10b47f59
feat(credential): part1 add AES-GCM encryption, SecureStore, and onboard ke… (#1521)
* feat(credential): add AES-GCM encryption, SecureStore, and onboard keygen

- pkg/credential: new package with AES-256-GCM enc:// credential format,
  HKDF-SHA256 key derivation (passphrase + optional SSH key binding),
  ErrPassphraseRequired / ErrDecryptionFailed sentinel errors,
  and PassphraseProvider hook for runtime passphrase injection

- pkg/credential/store: lock-free SecureStore via atomic.Pointer[string];
  passphrase never written to disk or os.Environ

- pkg/credential/keygen: ed25519 SSH key generation helper used by onboard

- pkg/config: replace os.Getenv(PassphraseEnvVar) with
  credential.PassphraseProvider() at all three call sites so that
  LoadConfig and SaveConfig use whatever passphrase source is active

- cmd/picoclaw/onboard: prompt for passphrase with echo-off, generate
  picoclaw-specific SSH key, re-encrypt existing config on re-onboard

- docs/credential_encryption.md: design doc for the enc:// format

* fix(credential): address Copilot review comments on PR #1521

- credential.go: decouple ErrPassphraseRequired from env var name;
  message is now 'enc:// passphrase required' since PassphraseProvider
  may come from any source, not just os.Environ

- credential.go: Resolver resolves symlinks via EvalSymlinks before the
  isWithinDir containment check, preventing symlink-based path traversal
  for file:// credential references

- store.go: tighten comment to describe only what SecureStore guarantees
  (in-memory only); remove claims about how callers transport the value

- store_test.go: replace the meaningless GetReturnsCopy test (Go strings
  are immutable, equality across two calls proves nothing) with
  TestSecureStore_ConcurrentSetGet that exercises atomic.Pointer under
  10-goroutine concurrent Set/Get load

- config_test.go: update error-message assertion to match new sentinel text

- docs/credential_encryption.md: remove reference to non-existent
  'picoclaw encrypt' subcommand; describe the onboard flow instead

* fix(config): encryptPlaintextAPIKeys: struct-based encryption, fail-fast, remove raw []byte

* fix(credential): require SSH private key for encryption/decryption, remove passphrase-only mode

* lint: fix credential keygen lint, fix test keygen

* onboard: make encryption opt-in via --enc flag

Encryption (passphrase prompt + SSH key generation) is now only
triggered when the user passes --enc to 'picoclaw onboard'.
Without the flag, onboard skips the credential-encryption setup and
writes a plain config + workspace templates directly.

- Add --enc BoolFlag in NewOnboardCommand()
- Pass encrypt bool into onboard()
- Guard passphrase prompt, SSH key generation, and related env-var
  setup behind the encrypt branch
- Adjust 'Next steps' output so the passphrase reminder only appears
  when --enc was used
2026-03-16 14:06:32 +08:00
..
agent feat: expose local file paths for non-image media to enable agent file tools (#1516) 2026-03-14 12:09:11 +08:00
auth feat(auth): add Anthropic OAuth setup-token login (#926) 2026-03-06 19:58:23 +08:00
bus Removed the old heavy logic 2026-03-08 18:22:15 +01:00
channels fix: Use secure defaults for Pico channel setup and stop leaking the token in the URL (#1563) 2026-03-16 09:58:37 +08:00
commands feat: add /clear command to clear chat history (#1266) 2026-03-09 16:39:33 +08:00
config feat(credential): part1 add AES-GCM encryption, SecureStore, and onboard ke… (#1521) 2026-03-16 14:06:32 +08:00
constants refactor: replace bool map with set-style map for internal channels (#472) 2026-02-19 11:48:17 +01:00
credential feat(credential): part1 add AES-GCM encryption, SecureStore, and onboard ke… (#1521) 2026-03-16 14:06:32 +08:00
cron feat(cron): add execution lifecycle logging (#1185) 2026-03-06 20:46:52 +08:00
devices refactor: cleanup dead code and turn on dead code detection in CI (#515) 2026-02-24 21:52:25 +08:00
fileutil refactor(pkg): move atomic file write to dedicated fileutil package 2026-02-24 23:57:13 +08:00
health chore: resolve conflicts with upstream/main 2026-02-28 12:21:54 +08:00
heartbeat enable dupl check 2026-03-01 18:17:32 +11:00
identity fix(identity): prevent allowlist ID entries from matching usernames (#1406) 2026-03-13 15:41:18 +08:00
logger Merge pull request #1442 from afjcjsbx/feat/logger-stdout-formatting 2026-03-14 22:04:51 +01:00
mcp Feat/add tool enable or disable configuration (#1071) 2026-03-05 14:53:26 +08:00
media chore: resolve conflicts with upstream/main 2026-02-28 12:21:54 +08:00
memory fix: skip meta json files during session migration (#1340) 2026-03-11 14:29:42 +08:00
migrate docs: remove stale TOOLS.md references (#1388) 2026-03-12 09:47:01 +08:00
providers fix(provider/azure): lint err 2026-03-15 12:45:11 +08:00
routing fix(routing): address review feedback on CJK estimation and observability 2026-03-06 13:10:20 +08:00
session fix(security): harden unauthenticated tool-exec paths (#1360) 2026-03-11 19:22:20 +08:00
skills enhance skill installer (#1252) 2026-03-13 14:04:02 +08:00
state fix(security): harden unauthenticated tool-exec paths (#1360) 2026-03-11 19:22:20 +08:00
tools fix: safety guard incorrectly blocks commands with URLs (#1254) 2026-03-13 17:16:05 +08:00
utils enhance skill installer (#1252) 2026-03-13 14:04:02 +08:00
voice Fix lint 2026-03-04 10:21:59 +00:00