(in-package :passepartout) (defvar *vault-memory* (make-hash-table :test 'equal) "In-memory cache of sensitive credentials.") (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)))))) (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))) (defun vault-get-secret (provider) "Retrieves a stored secret or token for a gateway provider." (vault-get provider :type :secret)) (defun vault-set-secret (provider secret) "Stores a secret or token for a gateway provider." (vault-set provider secret :type :secret)) (defskill :passepartout-security-vault :priority 600 :trigger (lambda (ctx) (declare (ignore ctx)) nil)) defvar *VAULT-MEMORY* (make-hash-table :test 'equal)) (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))