Fixed 3 real compilation errors: - security-vault.lisp: bare defvar missing opening paren - embedding-native.lisp: CFFI struct refs updated (llama-mparams→(:struct ...), 19 places) - symbolic-events.lisp: heartbeat vars + save-memory-to-disk → passepartout:: prefix Suppressed ~100 harmless cross-skill STYLE-WARNINGs: - Added grep filter for STYLE-WARNING / WARNING: redefining in the pre-compile step of the passepartout bash script ROADMAP updated: all v0.5.1 items marked DONE. Test suite: 116/116 (100%)
166 lines
5.5 KiB
Org Mode
166 lines
5.5 KiB
Org Mode
#+TITLE: SKILL: Credentials Vault (org-skill-credentials-vault.org)
|
|
#+AUTHOR: Agent
|
|
#+FILETAGS: :system:security:vault:
|
|
#+PROPERTY: header-args:lisp :tangle ../lisp/security-vault.lisp
|
|
|
|
* 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
|
|
|
|
1. (vault-set provider secret &key type): stores secret under
|
|
~(format nil "~a-~a" provider type)~ in ~*vault-memory*~.
|
|
2. (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.
|
|
3. (vault-get-secret provider): wrapper — calls ~vault-get~ with
|
|
~:type :secret~.
|
|
4. (vault-set-secret provider secret): wrapper — calls ~vault-set~
|
|
with ~:type :secret~.
|
|
5. Vault isolation: storing a secret for provider A does not affect
|
|
provider B's entry. Different ~:type~ values 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
|
|
#+begin_src lisp
|
|
(in-package :passepartout)
|
|
#+end_src
|
|
|
|
** Vault Storage
|
|
;; REPL-VERIFIED: 2026-05-03T13:00:00
|
|
#+begin_src lisp
|
|
(defvar *vault-memory* (make-hash-table :test 'equal)
|
|
"In-memory cache of sensitive credentials.")
|
|
#+end_src
|
|
|
|
** Secret Management
|
|
;; REPL-VERIFIED: 2026-05-03T13:00:00
|
|
#+begin_src lisp
|
|
(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))))))
|
|
|
|
#+end_src
|
|
** vault-set
|
|
;; REPL-VERIFIED: 2026-05-03T13:00:00
|
|
#+begin_src lisp
|
|
(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)))
|
|
#+end_src
|
|
|
|
** 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
|
|
#+begin_src lisp
|
|
(defun vault-get-secret (provider)
|
|
"Retrieves a stored secret or token for a gateway provider."
|
|
(vault-get provider :type :secret))
|
|
|
|
#+end_src
|
|
** vault-set-secret
|
|
;; REPL-VERIFIED: 2026-05-03T13:00:00
|
|
#+begin_src lisp
|
|
(defun vault-set-secret (provider secret)
|
|
"Stores a secret or token for a gateway provider."
|
|
(vault-set provider secret :type :secret))
|
|
#+end_src
|
|
|
|
** Skill Registration
|
|
#+begin_src lisp
|
|
(defskill :passepartout-security-vault
|
|
:priority 600
|
|
:trigger (lambda (ctx) (declare (ignore ctx)) nil))
|
|
#+end_src
|
|
|
|
|
|
** Vault Memory (relocated from core-skills)
|
|
|
|
#+begin_src lisp
|
|
(defvar *VAULT-MEMORY* (make-hash-table :test 'equal))
|
|
#+end_src
|
|
|
|
* Test Suite
|
|
|
|
#+begin_src lisp
|
|
(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))
|
|
#+end_src |