Files
passepartout/skills/org-skill-credentials-vault.org

7.3 KiB

SKILL: Credentials Vault (Universal Literate Note)

Overview

The Credentials Vault is the high-security enclave for the OpenCortex. 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)

1. Purpose

Securely manage all authentication tokens required for the opencortex to operate.

2. User Needs

  • Unified Storage: Single interface for API keys and Session Cookies.
  • Masked Logging: Ensure credentials never appear in plaintext in `harness-log`.
  • Guided Onboarding: Retain and improve the Google/Gemini cookie handshake.
  • Persistence: Securely save credentials to the Memory via Merkle-Tree snapshots.

Phase B: Blueprint (PROTOCOL)

1. Architectural Intent

The vault provides a secure lookup table in RAM, backed by the persistent Memory. Access is restricted to internal kernel requests and explicitly authorized deterministic gates.

2. Semantic Interfaces

(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.")

Phase C: Success (QUALITY)

1. Success Criteria

  • No Plaintext Leaks: Log output must use `[REDACTED]` for sensitive values.
  • Merkle Integration: Setting a secret must increment the Memory 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 Memory after `vault-set-secret`.

Phase D: Build (Implementation)

Package Context

Vault State

We maintain an in-memory hash table for secrets, which is hydrated from and persisted to the Memory.

(defvar opencortex::*vault-memory* (make-hash-table :test 'equal)
  "In-memory cache of sensitive credentials.")

Helper: Secret Masking

The `vault-mask-string` function ensures that diagnostic output never contains the full plaintext of a sensitive token.

(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]"))

Retrieval (vault-get-secret)

This function is the secure getter for all system secrets. It prioritizes the Vault (Memory) and falls back to environment variables for legacy compatibility.

(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 opencortex::*vault-memory*)))
    (if val
        val
        ;; Fallback to environment
        (let ((env-var (case provider
                         ((:gemini :gemini-api) "GEMINI_API_KEY")
                         (:openai "OPENAI_API_KEY")
                         (:anthropic "ANTHROPIC_API_KEY")
                         (:groq "GROQ_API_KEY")
                         (:openrouter "OPENROUTER_API_KEY")
                         (:telegram "TELEGRAM_BOT_TOKEN")
                         (:signal "SIGNAL_ACCOUNT_NUMBER")
                         (:matrix-homeserver "MATRIX_HOMESERVER")
                         (:matrix-token "MATRIX_ACCESS_TOKEN")
                         (t nil))))
          (when (and env-var (eq type :api-key))
            (getenv env-var))))))

Persistence (vault-set-secret)

When a secret is updated, we immediately snapshot the Memory to ensure the credential change is versioned and durable.

(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 opencortex::*vault-memory*) secret)
    (harness-log "VAULT - Updated ~a for ~a. Triggering Merkle snapshot..." type provider)
    (snapshot-memory)
    t))

Onboarding Logic

Retained from the legacy Google skill, this provides the instructions for the autonomous cookie handshake.

(defun vault-onboard-gemini-web ()
  "Instructions for the Autonomous Cookie Handshake."
  (harness-log "--- GEMINI WEB ONBOARDING ---")
  (harness-log "1. Visit gemini.google.com")
  (harness-log "2. Run the 'Get Gemini Cookies' Bookmarklet.")
  (harness-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));})();")
  (harness-log "PLATFORM GUIDE: Chrome/Firefox/Safari all support Bookmarklets via 'Add Page' or 'New Bookmark'.")
  t)

Registration

(progn
  (defskill :skill-credentials-vault
    :priority 200 ; High priority, foundational
    :trigger (lambda (ctx) (eq (getf (getf ctx :payload) :sensor) :onboarding-request))
    :probabilistic nil
    :deterministic (lambda (action ctx) 
                (vault-onboard-gemini-web)
                action)))

Phase E: Chaos (Verification)

Note: Tests disabled in jail load.

1. Unit Tests (FiveAM)

#|
(defpackage :opencortex-vault-tests
  (:use :cl :fiveam :opencortex))
(in-package :opencortex-vault-tests)

(def-suite vault-suite :description "Tests for the Credentials Vault.")
(in-suite vault-suite)

(test test-masking
  (is (equal "sk-t...-key" (opencortex::vault-mask-string "sk-test-key")))
  (is (equal "[REDACTED]" (opencortex::vault-mask-string "short"))))

(test test-vault-persistence
  "Verify that setting a secret triggers a snapshot (mock check)."
  (let ((old-version (opencortex::org-object-version (gethash "root" *memory*))))
    (opencortex:vault-set-secret :test "secret-val")
    (is (> (opencortex::org-object-version (gethash "root" *memory*)) old-version))))
|#

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 `opencortex::*vault-memory*` during runtime and verify the vault successfully re-hydrates from the Memory (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.