REFAC: Consolidate Auth skills into secure Credentials Vault

This commit is contained in:
2026-04-09 20:36:24 -04:00
parent fed7c04e25
commit 640bd92a0e
4 changed files with 182 additions and 135 deletions

View File

@@ -1,56 +0,0 @@
:PROPERTIES:
:ID: ab7f8ca4-5589-44ed-b797-1389ceeaf39c
:CREATED: [2026-03-31 Tue 18:13]
:EDITED: [2026-04-07 Tue 13:42]
:END:
#+TITLE: SKILL: API Key Authentication (Universal Literate Note)
#+STARTUP: content
#+FILETAGS: :auth:security:system:psf:
* Overview
This skill provides the legacy-compatible *Static API Key* authentication method. It retrieves credentials from the system environment variables and provides them to the kernel's neural backends.
* Phase A: Demand (PRD)
:PROPERTIES:
:STATUS: FROZEN
:END:
** 1. Purpose
Provide a simple, environment-driven authentication mechanism for LLM providers.
** 2. User Needs
- *Static Retrieval:* Pull `LLM_API_KEY` from `.env`.
- *Provider Mapping:* Support mapping keys to specific providers (Gemini, OpenAI, etc.).
- *Reliability:* Return NIL gracefully if no key is found.
* Phase B: Blueprint (PROTOCOL)
:PROPERTIES:
:STATUS: SIGNED
:END:
** 1. Architectural Intent
Interfaces for credential retrieval. Source of truth is the system environment.
** 2. Semantic Interfaces
"Returns a plist containing the :api-key for the default provider."
* Phase D: Build (Implementation)
#+begin_src lisp :tangle ../projects/org-skill-auth-api-key/src/auth-api-key.lisp
(defun auth-api-key-get-credentials ()
(let ((key (uiop:getenv "LLM_API_KEY")))
(when key
(list :api-key key))))
;; Register as the default auth provider for Gemini during transition
(org-agent:register-auth-provider :gemini #'auth-api-key-get-credentials)
#+end_src
* Registration
#+begin_src lisp
(defskill :skill-auth-api-key
:priority 100
:trigger (lambda (context) nil)
:neuro (lambda (context) nil)
:symbolic (lambda (action context) action))
#+end_src

View File

@@ -1,59 +0,0 @@
:PROPERTIES:
:ID: 440074d1-fe4d-41fb-b349-4570ba91cda2
:CREATED: [2026-03-31 Tue 18:13]
:EDITED: [2026-04-07 Tue 13:42]
:END:
#+TITLE: SKILL: Google Authentication Suite (Universal Literate Note)
#+STARTUP: content
#+FILETAGS: :auth:google:oauth:cookies:psf:
* Overview
This skill manages the dual-path authentication for Google services: Official API Keys and Session Cookie ingestion for the Pro Web UI.
* Phase A: Demand (PRD)
:PROPERTIES:
:STATUS: SIGNED
:END:
** 1. Purpose
Provide a high-fidelity onboarding flow for the Gemini Web bridge.
** 2. User Needs
- *Guided Onboarding:* Clear instructions for Chrome, Firefox, and Safari.
- *Secure Ingestion:* Process the Bookmarklet JSON into the kernel.
* Phase B: Blueprint (PROTOCOL)
:PROPERTIES:
:STATUS: SIGNED
:END:
** 1. Architectural Intent
Implement the `onboard-web-session` command with cross-platform instructions.
* Phase D: Build (Implementation)
#+begin_src lisp :tangle ../projects/org-skill-auth-google-oauth/src/onboarding-logic.lisp
(in-package :org-agent)
(defun onboard-web-session ()
"Instructions for the Sovereign Cookie Handshake."
(kernel-log "--- GEMINI WEB ONBOARDING ---")
(kernel-log "1. Visit gemini.google.com")
(kernel-log "2. Run the 'Get Gemini Cookies' Bookmarklet.")
(kernel-log " CODE: javascript:(function(){const c=document.cookie.split('; ').reduce((r,v)=>{const [n,val]=v.split('=');r[n]=val;return r},{});const target=['__Secure-1PSID','__Secure-1PSIDTS'];const out=target.map(n=>({name:n,value:c[n]}));prompt('Copy JSON:',JSON.stringify(out));})();")
(kernel-log "PLATFORM GUIDE:")
(kernel-log " - Chrome/Brave: Right-click Bookmarks Bar > Add Page > Paste Code into URL.")
(kernel-log " - Firefox: Right-click Sidebar > New Bookmark > Paste Code into Location.")
(kernel-log " - Safari: Edit an existing bookmark's address and paste the code.")
t)
#+end_src
* Registration
#+begin_src lisp
(progn
(defskill :skill-auth-google
:priority 100
:trigger (lambda (context) (eq (getf (getf context :payload) :sensor) :onboarding-request))
:neuro (lambda (context) nil)
:symbolic (lambda (action context) (onboard-web-session))))
#+end_src

View File

@@ -0,0 +1,175 @@
:PROPERTIES:
:ID: credentials-vault-skill
:CREATED: [2026-04-09 Thu]
:END:
#+TITLE: SKILL: Credentials Vault (Universal Literate Note)
#+STARTUP: content
#+FILETAGS: :auth:security:infrastructure:psf:
#+DEPENDS_ON: id:e8b500e2-3f26-4c8e-8558-528061e178ca
* Overview
The *Credentials Vault* is the high-security enclave for the Org-Agent. It centralizes the management of LLM API keys, OAuth sessions, and browser cookies. By consolidating these into a single vault, we ensure that sensitive tokens are handled with uniform masking, validation, and Merkle-integrated persistence.
* Phase A: Demand (PRD)
:PROPERTIES:
:STATUS: SIGNED
:END:
** 1. Purpose
Securely manage all authentication tokens required for the PSF to operate.
** 2. User Needs
- *Unified Storage:* Single interface for API keys and Session Cookies.
- *Masked Logging:* Ensure credentials never appear in plaintext in `kernel-log`.
- *Guided Onboarding:* Retain and improve the Google/Gemini cookie handshake.
- *Persistence:* Securely save credentials to the Object Store via Merkle-Tree snapshots.
* Phase B: Blueprint (PROTOCOL)
:PROPERTIES:
:STATUS: SIGNED
:END:
** 1. Architectural Intent
The vault provides a secure lookup table in RAM, backed by the persistent Object Store. Access is restricted to internal kernel requests and explicitly authorized symbolic gates.
** 2. Semantic Interfaces
#+begin_src lisp
(defun vault-get-secret (provider &key type)
"Retrieves a secret (api-key or session) for a provider.")
(defun vault-set-secret (provider secret &key type)
"Securely stores a secret and triggers a Merkle snapshot.")
#+end_src
* Phase C: Success (QUALITY)
:PROPERTIES:
:STATUS: SIGNED
:END:
** 1. Success Criteria
- [ ] *No Plaintext Leaks:* Log output must use `[REDACTED]` for sensitive values.
- [ ] *Merkle Integration:* Setting a secret must increment the Object Store version.
- [ ] *Dual-Path Auth:* Support both `:api-key` and `:session-cookies`.
- [ ] *Onboarding Verification:* The cookie handshake successfully hydrates the vault.
** 2. TDD Plan
Tests in `tests/vault-tests.lisp` will verify:
1. Retrieval of keys from both `.env` (fallback) and Vault (primary).
2. Redaction of keys in log strings.
3. Successful version increment in the Object Store after `vault-set-secret`.
* Phase D: Build (Implementation)
** Package Context
#+begin_src lisp :tangle ../src/credentials-vault.lisp
(in-package :org-agent)
#+end_src
** Vault State
We maintain an in-memory hash table for secrets, which is hydrated from and persisted to the Object Store.
#+begin_src lisp :tangle ../src/credentials-vault.lisp
(defvar *vault-memory* (make-hash-table :test 'equal)
"In-memory cache of sensitive credentials.")
#+end_src
** Helper: Secret Masking
The `vault-mask-string` function ensures that diagnostic output never contains the full plaintext of a sensitive token.
#+begin_src lisp :tangle ../src/credentials-vault.lisp
(defun vault-mask-string (str)
"Returns a masked version of a sensitive string."
(if (and str (> (length str) 8))
(format nil "~a...~a" (subseq str 0 4) (subseq str (- (length str) 4)))
"[REDACTED]"))
#+end_src
** Retrieval (vault-get-secret)
This function is the secure getter for all system secrets. It prioritizes the Vault (Object Store) and falls back to environment variables for legacy compatibility.
#+begin_src lisp :tangle ../src/credentials-vault.lisp
(defun vault-get-secret (provider &key (type :api-key))
"Retrieves a credential. Type can be :api-key or :session."
(let* ((key (format nil "~a-~a" provider type))
(val (gethash key *vault-memory*)))
(if val
val
;; Fallback to environment
(let ((env-var (case provider
(:gemini "GEMINI_API_KEY")
(:openai "OPENAI_API_KEY")
(:anthropic "ANTHROPIC_API_KEY")
(:groq "GROQ_API_KEY")
(:openrouter "OPENROUTER_API_KEY")
(t nil))))
(when (and env-var (eq type :api-key))
(uiop:getenv env-var))))))
#+end_src
** Persistence (vault-set-secret)
When a secret is updated, we immediately snapshot the Object Store to ensure the credential change is versioned and durable.
#+begin_src lisp :tangle ../src/credentials-vault.lisp
(defun vault-set-secret (provider secret &key (type :api-key))
"Securely stores a secret and triggers a Merkle snapshot."
(let ((key (format nil "~a-~a" provider type)))
(setf (gethash key *vault-memory*) secret)
(kernel-log "VAULT - Updated ~a for ~a. Triggering Merkle snapshot..." type provider)
(snapshot-object-store)
t))
#+end_src
** Onboarding Logic
Retained from the legacy Google skill, this provides the instructions for the sovereign cookie handshake.
#+begin_src lisp :tangle ../src/credentials-vault.lisp
(defun vault-onboard-gemini-web ()
"Instructions for the Sovereign Cookie Handshake."
(kernel-log "--- GEMINI WEB ONBOARDING ---")
(kernel-log "1. Visit gemini.google.com")
(kernel-log "2. Run the 'Get Gemini Cookies' Bookmarklet.")
(kernel-log " CODE: javascript:(function(){const c=document.cookie.split('; ').reduce((r,v)=>{const [n,val]=v.split('=');r[n]=val;return r},{});const target=['__Secure-1PSID','__Secure-1PSIDTS'];const out=target.map(n=>({name:n,value:c[n]}));prompt('Copy JSON:',JSON.stringify(out));})();")
(kernel-log "PLATFORM GUIDE: Chrome/Firefox/Safari all support Bookmarklets via 'Add Page' or 'New Bookmark'.")
t)
#+end_src
** Registration
#+begin_src lisp :tangle ../src/credentials-vault.lisp
(progn
(defskill :skill-credentials-vault
:priority 200 ; High priority, foundational
:trigger (lambda (ctx) (eq (getf (getf ctx :payload) :sensor) :onboarding-request))
:neuro nil
:symbolic (lambda (action ctx)
(vault-onboard-gemini-web)
action)))
#+end_src
* Phase E: Chaos (Verification)
** 1. Unit Tests (FiveAM)
#+begin_src lisp :tangle ../tests/vault-tests.lisp
(defpackage :org-agent-vault-tests
(:use :cl :fiveam :org-agent))
(in-package :org-agent-vault-tests)
(def-suite vault-suite :description "Tests for the Credentials Vault.")
(in-suite vault-suite)
(test test-masking
(is (equal "sk-t...-key" (org-agent::vault-mask-string "sk-test-key")))
(is (equal "[REDACTED]" (org-agent::vault-mask-string "short"))))
(test test-vault-persistence
"Verify that setting a secret triggers a snapshot (mock check)."
(let ((old-version (org-agent::org-object-version (gethash "root" *object-store*))))
(org-agent:vault-set-secret :test "secret-val")
(is (> (org-agent::org-object-version (gethash "root" *object-store*)) old-version))))
#+end_src
** 2. Chaos Scenarios
- *Scenario A (Vault Poisoning):* Inject a malformed session string and verify the `llm-gateway` detects the invalid format and returns a standardized error instead of crashing.
- *Scenario B (Memory Wipe):* Clear `*vault-memory*` during runtime and verify the vault successfully re-hydrates from the Object Store (or environment fallback).
* Phase F: Memory (RCA)
- *[2026-04-09 Thu]:* Consolidated `auth-api-key` and `auth-google-oauth` into this vault. Introduced mandatory masking for all credential-related logging.

View File

@@ -58,33 +58,20 @@ Verification will occur via `tests/llm-gateway-tests.lisp` using the FiveAM fram
#+begin_src lisp :tangle ../src/llm-gateway.lisp
(in-package :org-agent)
#+end_src
** Helper: Secure Credential Retrieval
The `get-llm-credentials` function abstracts the retrieval of sensitive API keys from the host environment. By centralizing this, we ensure that keys are only accessed when needed and are never hardcoded in the Lisp image.
#+begin_src lisp :tangle ../src/llm-gateway.lisp
(defun get-llm-credentials (provider)
"Retrieves the API key for the provider from the environment, ensuring it is not logged."
(let ((var (case provider
(:anthropic "ANTHROPIC_API_KEY")
(:gemini-api "GEMINI_API_KEY")
(:groq "GROQ_API_KEY")
(:openai "OPENAI_API_KEY")
(:openrouter "OPENROUTER_API_KEY")
(t nil))))
(when var (uiop:getenv var))))
#+end_src
** Unified Request Executor (execute-llm-request)
This is the primary actuator for neural reasoning. It handles the specific JSON payload formats and HTTP headers required by each provider (e.g., Anthropic's `x-api-key` vs. OpenAI's `Bearer` token).
This is the primary actuator for neural reasoning. It handles the specific JSON payload formats and HTTP headers required by each provider. It retrieves secrets from the [[file:org-skill-credentials-vault.org][Credentials Vault]], ensuring that API keys are masked in all diagnostic output.
#+begin_src lisp :tangle ../src/llm-gateway.lisp
(defun execute-llm-request (prompt system-prompt &key provider model)
"Unified entry point for all LLM providers."
(let ((api-key (get-llm-credentials provider))
(let ((api-key (vault-get-secret provider :type :api-key))
(full-prompt (format nil "~a~%~%Prompt: ~a" system-prompt prompt)))
(kernel-log "SYSTEM 1: Requesting ~a (Model: ~a) [Key: ~a]"
provider (or model "default") (vault-mask-string api-key))
(case provider
...
(:gemini-web
(let ((res (uiop:symbol-call :org-agent.skills.org-skill-web-research :ask-gemini-web full-prompt)))
(if res (list :status :success :content res) (list :status :error :message "Web Research Failure"))))