Security
Credential vault, license management, permissions, and the triage state machine.
Credential Vault
The vault provides per-plugin encrypted storage for API keys, tokens, and other secrets. Data is encrypted at rest with AES-256-GCM and scoped to the calling plugin — one plugin cannot access another plugin's secrets.
Store a Secret
engine.vault_store("my_api_key", "sk-abc123...")
# Encrypted at rest, scoped to this plugin
Retrieve a Secret
key = engine.vault_retrieve("my_api_key")
if key:
# Use the decrypted value
headers = {"Authorization": f"Bearer {key}"}
Delete a Secret
License Management Coming Soon
ANIMA will support tiered licensing with signed offline license keys. Plugins will be able to check the active license to enable or disable features. This system is under development.
Permissions
Plugins declare required permissions in plugin.toml. The core enforces these at runtime.
# In plugin.toml
[plugin.permissions]
network = ["api.example.com"] # allowed external endpoints
filesystem = ["read:corpus/"] # beyond own data dir
subprocess = false # can it spawn subprocesses?
if engine.check_permission("my-plugin", "network", "api.example.com"):
# Allowed to make this network call
pass
Permission Types
| Permission | Description |
|---|---|
network | Allowed external endpoints (beyond ANIMA core) |
filesystem | File access beyond the plugin's own data directory |
subprocess | Whether the plugin can spawn subprocesses |
Triage State Machine Rust
The triage state machine validates every new belief before it enters the knowledge graph. This includes beliefs from document extraction, dream synthesis, and manual injection.
Pipeline
The triage runs as a multi-step state machine. At each step, the Rust core returns what it needs, Python performs the side effect (LLM call, semantic search), and resumes the state machine with the result.
| Step | What Happens | Resume Method |
|---|---|---|
NeedsTranslation | Python translates via LLM | triage_resume_translation(id, translated?) |
NeedsClassification | Python classifies via LLM | triage_resume_classification(id, classification) |
NeedsRewrite | Python rewrites narrative to mechanism | triage_resume_rewrite(id, rewrite?) |
NeedsContradictionCheck | Python searches for conflicts | triage_resume_contradictions(id, matches) |
NeedsConstraintCheck | Python checks hypothesis constraints | triage_resume_constraints(id, matches) |
NeedsDuplicateCheck | Python checks for duplicates | triage_resume_duplicate(id, is_duplicate) |
FinalDecision | Accept, reject, or queue | (terminal state) |
Starting Triage
{id, step, ...payload}.Final Decision
The terminal FinalDecision step returns:
{
"decision": "accept", # accept | reject | queue
"code": "PASS",
"reason": "Passed all quality gates",
}
Quality Validation
{passes, result, reason}. Useful for pre-checking beliefs without running the full triage.Debugging
Rust Core Security Methods Rust
| Method | Returns | Notes |
|---|---|---|
vault_store(plugin_id, key, value) | bool | AES-256-GCM encrypted |
vault_retrieve(plugin_id, key) | str | None | Per-plugin isolated |
vault_delete(plugin_id, key) | bool | |
get_license_info() | dict | Coming soon |
check_feature(feature) | bool | Coming soon |
check_permission(plugin_id, action, target, config?) | bool | Network/filesystem/subprocess |