Some checks failed
Deploy (Gitea) / deploy (push) Failing after 2s
- Restore (in-package :passepartout) to core-reason - Move *VAULT-MEMORY* back to core-skills - Fix ASDF and defstruct/defpackage ordering - Increase daemon timeout to 120s - Handshake: 0.5.0 Verified: daemon processes messages, TUI clean, gate trace works
5.5 KiB
5.5 KiB
SKILL: Credentials Vault (org-skill-credentials-vault.org)
Overview
The Credentials Vault provides secure in-memory storage for sensitive API keys and session tokens.
Architectural Intent
The Credentials Vault isolates secrets from the rest of the system in a dedicated hash-table. It provides simple get/set primitives with environment-variable fallback for known providers. This is the single place where credentials enter the system — every provider skill routes through here.
Contract
- (vault-set provider secret &key type): stores secret under
(format nil "~a-~a" provider type)in*vault-memory*. - (vault-get provider &key type): returns the stored secret, or falls
back to the appropriate environment variable for known providers
(
:openai,:anthropic,:openrouter,:gemini). Returns NIL if neither exists. - (vault-get-secret provider): wrapper — calls
vault-getwith:type :secret. - (vault-set-secret provider secret): wrapper — calls
vault-setwith:type :secret. - Vault isolation: storing a secret for provider A does not affect
provider B's entry. Different
:typevalues produce different keys.
Boundaries
- Does NOT encrypt at rest — that is the session layer's responsibility.
- Does NOT validate key format — the provider skill does that.
- Does NOT rotate or expire keys — this is a simple store.
Implementation
Package Context
(in-package :passepartout)
Vault Storage
;; REPL-VERIFIED: 2026-05-03T13:00:00
(defvar *vault-memory* (make-hash-table :test 'equal)
"In-memory cache of sensitive credentials.")
Secret Management
;; REPL-VERIFIED: 2026-05-03T13:00:00
(defun vault-get (provider &key (type :api-key))
"Retrieves a credential from the vault or environment."
(let* ((key (format nil "~a-~a" provider type))
(val (gethash key *vault-memory*)))
(if val
val
(let ((env-var (case provider
(:gemini "GEMINI_API_KEY")
(:openai "OPENAI_API_KEY")
(:anthropic "ANTHROPIC_API_KEY")
(:openrouter "OPENROUTER_API_KEY")
(otherwise nil))))
(when env-var (uiop:getenv env-var))))))
vault-set
;; REPL-VERIFIED: 2026-05-03T13:00:00
(defun vault-set (provider secret &key (type :api-key))
"Stores a secret in the vault."
(let ((key (format nil "~a-~a" provider type)))
(setf (gethash key *vault-memory*) secret)))
Secret Wrappers (gateway-messaging)
Thin wrappers that match the export names used by gateway-messaging.
Delegates to the existing vault-get=/=vault-set with :type :secret.
;; REPL-VERIFIED: 2026-05-03T13:00:00
(defun vault-get-secret (provider)
"Retrieves a stored secret or token for a gateway provider."
(vault-get provider :type :secret))
vault-set-secret
;; REPL-VERIFIED: 2026-05-03T13:00:00
(defun vault-set-secret (provider secret)
"Stores a secret or token for a gateway provider."
(vault-set provider secret :type :secret))
Skill Registration
(defskill :passepartout-security-vault
:priority 600
:trigger (lambda (ctx) (declare (ignore ctx)) nil))
Vault Memory (relocated from core-skills)
defvar *VAULT-MEMORY* (make-hash-table :test 'equal))
#+end_src
Test Suite
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload :fiveam :silent t))
(defpackage :passepartout-security-vault-tests
(:use :cl :fiveam :passepartout)
(:export #:vault-suite))
(in-package :passepartout-security-vault-tests)
(def-suite vault-suite :description "Verification of the Credentials Vault")
(in-suite vault-suite)
(test test-vault-round-trip
"Contract 1: vault-set stores a value; vault-get retrieves it."
(let ((test-key :vault-test-round-trip)
(test-secret "secret-abc123"))
(vault-set test-key test-secret)
(is (string= test-secret (vault-get test-key)))
;; Clean up
(vault-set test-key nil)))
(test test-vault-missing-key
"Contract 2: vault-get returns NIL for an unset, unknown provider."
(is (null (vault-get :nonexistent-provider-xyz))))
(test test-vault-isolation
"Contract 5: storing for provider A does not affect provider B."
(vault-set :vault-prov-a "secret-a")
(vault-set :vault-prov-b "secret-b")
(is (string= "secret-a" (vault-get :vault-prov-a)))
(is (string= "secret-b" (vault-get :vault-prov-b)))
(vault-set :vault-prov-a nil)
(vault-set :vault-prov-b nil))
(test test-vault-secret-wrappers
"Contracts 3,4: vault-get-secret and vault-set-secret use :type :secret."
(let ((test-provider :vault-secret-test))
(vault-set-secret test-provider "my-token")
(is (string= "my-token" (vault-get-secret test-provider)))
;; Clean up
(vault-set-secret test-provider nil)))
(test test-vault-type-isolation
"Contract 5: different :type values produce different keys."
(vault-set :vault-type-test "key-value" :type :api-key)
(vault-set :vault-type-test "secret-value" :type :secret)
(is (string= "key-value" (vault-get :vault-type-test :type :api-key)))
(is (string= "secret-value" (vault-get :vault-type-test :type :secret)))
(vault-set :vault-type-test nil :type :api-key)
(vault-set :vault-type-test nil :type :secret))