{
  "component_id": "src_vault.rs",
  "name": "Signet Vault - Encrypted Local State with Tiered Access",
  "description": "Encrypted local state vault with tiered access control for AI agent tool call enforcement. Implements three security tiers: Tier 1 (unencrypted ledger/action log), Tier 2 (session-key encrypted session state), Tier 3 (compartment-key encrypted credentials requiring passphrase). Security model includes Argon2id-derived master key, device-encrypted session key file, brute-force protection via lockout after failed attempts, and policy file integrity via HMAC. Provides credential storage with metadata constraints, spending ledger, preflight task management, and violation tracking.",
  "version": 1,
  "types": [
    {
      "name": "VaultMeta",
      "kind": "struct",
      "fields": [
        {
          "name": "salt",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Base64-encoded salt for key derivation",
          "validators": []
        },
        {
          "name": "key_check",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Base64-encoded HMAC check value for passphrase verification",
          "validators": []
        },
        {
          "name": "created_at",
          "type_ref": "f64",
          "required": true,
          "default": "",
          "description": "Unix epoch timestamp of vault creation",
          "validators": []
        },
        {
          "name": "failed_attempts",
          "type_ref": "u32",
          "required": true,
          "default": "0",
          "description": "Count of failed unlock attempts",
          "validators": []
        },
        {
          "name": "locked_until",
          "type_ref": "f64",
          "required": true,
          "default": "0.0",
          "description": "Unix epoch timestamp until which vault is locked",
          "validators": []
        }
      ],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "Metadata for vault initialization and lockout tracking",
      "owner_component": ""
    },
    {
      "name": "CredentialMeta",
      "kind": "struct",
      "fields": [
        {
          "name": "domain",
          "type_ref": "Option<String>",
          "required": false,
          "default": "",
          "description": "Domain scope restriction (e.g. 'amazon.com')",
          "validators": []
        },
        {
          "name": "purpose",
          "type_ref": "Option<String>",
          "required": false,
          "default": "",
          "description": "Purpose restriction (e.g. 'purchase', 'api_access')",
          "validators": []
        },
        {
          "name": "max_amount",
          "type_ref": "Option<f64>",
          "required": false,
          "default": "",
          "description": "Per-use amount cap",
          "validators": []
        },
        {
          "name": "one_time",
          "type_ref": "bool",
          "required": true,
          "default": "false",
          "description": "Invalidate after first use",
          "validators": []
        },
        {
          "name": "label",
          "type_ref": "Option<String>",
          "required": false,
          "default": "",
          "description": "Human-readable label",
          "validators": []
        }
      ],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "Metadata constraints for stored credentials",
      "owner_component": ""
    },
    {
      "name": "Preflight",
      "kind": "struct",
      "fields": [
        {
          "name": "id",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Unique preflight identifier",
          "validators": []
        },
        {
          "name": "task",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Task description",
          "validators": []
        },
        {
          "name": "risks",
          "type_ref": "Vec<String>",
          "required": true,
          "default": "",
          "description": "List of identified risks",
          "validators": []
        },
        {
          "name": "constraints",
          "type_ref": "Vec<SoftConstraint>",
          "required": true,
          "default": "",
          "description": "Soft constraints to enforce",
          "validators": []
        },
        {
          "name": "submitted_at",
          "type_ref": "u64",
          "required": true,
          "default": "",
          "description": "Unix timestamp of submission",
          "validators": []
        },
        {
          "name": "lockout_until",
          "type_ref": "u64",
          "required": true,
          "default": "",
          "description": "Unix timestamp until which preflight is active",
          "validators": []
        },
        {
          "name": "violation_count",
          "type_ref": "u32",
          "required": true,
          "default": "",
          "description": "Count of constraint violations",
          "validators": []
        },
        {
          "name": "escalated",
          "type_ref": "bool",
          "required": true,
          "default": "",
          "description": "Whether violation threshold exceeded",
          "validators": []
        }
      ],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "Preflight task with constraints and violation tracking",
      "owner_component": ""
    },
    {
      "name": "SoftConstraint",
      "kind": "struct",
      "fields": [
        {
          "name": "name",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Constraint name",
          "validators": []
        },
        {
          "name": "tool_pattern",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Tool name pattern to match",
          "validators": []
        },
        {
          "name": "conditions",
          "type_ref": "Vec<String>",
          "required": true,
          "default": "",
          "description": "Conditions for constraint activation",
          "validators": []
        },
        {
          "name": "action",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Action to take: 'DENY' or 'ASK'",
          "validators": []
        },
        {
          "name": "reason",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Human-readable reason",
          "validators": []
        },
        {
          "name": "alternative",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Suggested alternative (plan B)",
          "validators": []
        }
      ],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "Single constraint rule for preflight enforcement",
      "owner_component": ""
    },
    {
      "name": "PreflightViolation",
      "kind": "struct",
      "fields": [
        {
          "name": "preflight_id",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "ID of violated preflight",
          "validators": []
        },
        {
          "name": "constraint_name",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Name of violated constraint",
          "validators": []
        },
        {
          "name": "tool_name",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Tool that triggered violation",
          "validators": []
        },
        {
          "name": "parameters_summary",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Summary of tool parameters",
          "validators": []
        },
        {
          "name": "alternative",
          "type_ref": "String",
          "required": true,
          "default": "",
          "description": "Suggested alternative",
          "validators": []
        },
        {
          "name": "timestamp",
          "type_ref": "u64",
          "required": true,
          "default": "",
          "description": "Unix timestamp of violation",
          "validators": []
        }
      ],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "Record of a constraint violation",
      "owner_component": ""
    },
    {
      "name": "Vault",
      "kind": "struct",
      "fields": [
        {
          "name": "master_key",
          "type_ref": "[u8; 32]",
          "required": true,
          "default": "",
          "description": "Argon2id-derived master key",
          "validators": []
        },
        {
          "name": "session_key",
          "type_ref": "[u8; 32]",
          "required": true,
          "default": "",
          "description": "HKDF-derived session key for Tier 2",
          "validators": []
        },
        {
          "name": "compartment_key",
          "type_ref": "[u8; 32]",
          "required": true,
          "default": "",
          "description": "HKDF-derived compartment key for Tier 3",
          "validators": []
        },
        {
          "name": "db_path",
          "type_ref": "PathBuf",
          "required": true,
          "default": "",
          "description": "Path to SQLite database",
          "validators": []
        },
        {
          "name": "session_start",
          "type_ref": "f64",
          "required": true,
          "default": "",
          "description": "Unix epoch timestamp of session start",
          "validators": []
        }
      ],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "Main vault instance with derived keys and database connection",
      "owner_component": ""
    }
  ],
  "functions": [
    {
      "name": "now_epoch",
      "description": "Get current Unix epoch time as f64 seconds",
      "inputs": [],
      "output_type": "f64",
      "error_cases": [
        {
          "name": "system_time_error",
          "condition": "SystemTime before UNIX_EPOCH",
          "error_type": "panic",
          "error_data": {
            "message": "unwrap on duration_since failed"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Returns monotonically increasing timestamp"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads system clock"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "random_hex_id",
      "description": "Generate a 32-character hex string from 16 random bytes",
      "inputs": [],
      "output_type": "String",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns 32-character lowercase hex string",
        "Each call produces unique value with high probability"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads from system RNG"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "derive_master_key",
      "description": "Derive 32-byte master key from passphrase and salt using Argon2id",
      "inputs": [
        {
          "name": "passphrase",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "User passphrase",
          "validators": []
        },
        {
          "name": "salt",
          "type_ref": "&[u8]",
          "required": true,
          "default": "",
          "description": "Salt bytes (typically 32 bytes)",
          "validators": []
        }
      ],
      "output_type": "[u8; 32]",
      "error_cases": [
        {
          "name": "argon2_failure",
          "condition": "Argon2 derivation fails",
          "error_type": "panic",
          "error_data": {
            "message": "Argon2 derivation failed"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Returns deterministic key for same passphrase+salt",
        "Key is cryptographically derived via Argon2id"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "CPU-intensive computation (memory-hard)"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "derive_subkey",
      "description": "Derive purpose-specific subkey from master key using HKDF-SHA256",
      "inputs": [
        {
          "name": "master",
          "type_ref": "&[u8; 32]",
          "required": true,
          "default": "",
          "description": "Master key",
          "validators": []
        },
        {
          "name": "purpose",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Purpose label (e.g. 'session', 'compartment')",
          "validators": []
        }
      ],
      "output_type": "[u8; 32]",
      "error_cases": [
        {
          "name": "hkdf_expand_failure",
          "condition": "HKDF expand fails",
          "error_type": "panic",
          "error_data": {
            "message": "HKDF expand failed"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Returns deterministic subkey for same master+purpose",
        "Subkey cryptographically independent from other purposes"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "make_key_check",
      "description": "Generate HMAC-SHA256 check value for master key verification",
      "inputs": [
        {
          "name": "master",
          "type_ref": "&[u8; 32]",
          "required": true,
          "default": "",
          "description": "Master key",
          "validators": []
        }
      ],
      "output_type": "Vec<u8>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns deterministic check value for same master key",
        "Check value can verify passphrase without exposing key"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "encrypt",
      "description": "Encrypt plaintext using AES-256-GCM with random nonce",
      "inputs": [
        {
          "name": "key",
          "type_ref": "&[u8; 32]",
          "required": true,
          "default": "",
          "description": "AES-256 key",
          "validators": []
        },
        {
          "name": "plaintext",
          "type_ref": "&[u8]",
          "required": true,
          "default": "",
          "description": "Data to encrypt",
          "validators": []
        }
      ],
      "output_type": "Vec<u8>",
      "error_cases": [
        {
          "name": "encryption_failure",
          "condition": "AES-GCM encryption fails",
          "error_type": "panic",
          "error_data": {
            "message": "encryption failed"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Returns nonce (12 bytes) concatenated with ciphertext",
        "Ciphertext is authenticated"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads from system RNG for nonce generation"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "decrypt",
      "description": "Decrypt AES-256-GCM ciphertext (nonce prepended)",
      "inputs": [
        {
          "name": "key",
          "type_ref": "&[u8; 32]",
          "required": true,
          "default": "",
          "description": "AES-256 key",
          "validators": []
        },
        {
          "name": "data",
          "type_ref": "&[u8]",
          "required": true,
          "default": "",
          "description": "Nonce (12 bytes) + ciphertext",
          "validators": []
        }
      ],
      "output_type": "Result<Vec<u8>, String>",
      "error_cases": [
        {
          "name": "data_too_short",
          "condition": "data.len() < 12",
          "error_type": "Result::Err",
          "error_data": {
            "message": "data too short"
          }
        },
        {
          "name": "decryption_failure",
          "condition": "AES-GCM decryption or authentication fails",
          "error_type": "Result::Err",
          "error_data": {
            "message": "decryption failed"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "On success, returns plaintext",
        "On failure, returns error string"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "policy_hmac",
      "description": "Compute HMAC-SHA256 of policy file content using session key",
      "inputs": [
        {
          "name": "session_key",
          "type_ref": "&[u8; 32]",
          "required": true,
          "default": "",
          "description": "Session key",
          "validators": []
        },
        {
          "name": "policy_content",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Policy file content",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns base64-encoded HMAC",
        "Deterministic for same key+content"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "verify_policy_integrity",
      "description": "Verify policy file HMAC signature. Fail-closed: missing HMAC with existing vault returns false.",
      "inputs": [
        {
          "name": "session_key",
          "type_ref": "&[u8; 32]",
          "required": true,
          "default": "",
          "description": "Session key",
          "validators": []
        },
        {
          "name": "policy_path",
          "type_ref": "&std::path::Path",
          "required": true,
          "default": "",
          "description": "Path to policy file",
          "validators": []
        }
      ],
      "output_type": "bool",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns true if policy valid or absent",
        "Returns false if HMAC missing (vault exists) or mismatched"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads policy file",
        "reads .hmac file"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "sign_policy",
      "description": "Sign policy file by writing HMAC to adjacent .hmac file",
      "inputs": [
        {
          "name": "session_key",
          "type_ref": "&[u8; 32]",
          "required": true,
          "default": "",
          "description": "Session key",
          "validators": []
        },
        {
          "name": "policy_path",
          "type_ref": "&std::path::Path",
          "required": true,
          "default": "",
          "description": "Path to policy file",
          "validators": []
        }
      ],
      "output_type": "Result<(), String>",
      "error_cases": [
        {
          "name": "read_policy_error",
          "condition": "Cannot read policy file",
          "error_type": "Result::Err",
          "error_data": {
            "message": "read policy: {error}"
          }
        },
        {
          "name": "write_hmac_error",
          "condition": "Cannot write HMAC file",
          "error_type": "Result::Err",
          "error_data": {
            "message": "write hmac: {error}"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "On success, .hmac file created/updated alongside policy"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads policy file",
        "writes .hmac file"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "new",
      "description": "Create new Vault instance from master key and database path. Initializes database schema and session.",
      "inputs": [
        {
          "name": "master_key",
          "type_ref": "[u8; 32]",
          "required": true,
          "default": "",
          "description": "Argon2id-derived master key",
          "validators": []
        },
        {
          "name": "db_path",
          "type_ref": "PathBuf",
          "required": true,
          "default": "",
          "description": "Path to SQLite database",
          "validators": []
        }
      ],
      "output_type": "Vault",
      "error_cases": [
        {
          "name": "db_open_failure",
          "condition": "Cannot open database",
          "error_type": "panic",
          "error_data": {
            "message": "open db"
          }
        },
        {
          "name": "db_init_failure",
          "condition": "Cannot create schema",
          "error_type": "panic",
          "error_data": {
            "message": "init db"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Database schema initialized",
        "Session keys derived",
        "Session start timestamp loaded or created"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "creates/opens SQLite database",
        "creates tables if not exist",
        "reads/writes session_state table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "session_key",
      "description": "Get reference to session key",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "&[u8; 32]",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns immutable reference to session key"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "init_db",
      "description": "Initialize SQLite database schema with tables for ledger, credentials, session_state, preflights, preflight_violations",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "()",
      "error_cases": [
        {
          "name": "db_open_failure",
          "condition": "Cannot open database",
          "error_type": "panic",
          "error_data": {
            "message": "open db"
          }
        },
        {
          "name": "schema_creation_failure",
          "condition": "Cannot execute schema SQL",
          "error_type": "panic",
          "error_data": {
            "message": "init db"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "All tables and indexes created if not exist"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "creates/opens database",
        "creates tables and indexes"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "load_or_create_session_start",
      "description": "Load session start timestamp from database or create new if expired/missing",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "f64",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns valid session start timestamp",
        "Timestamp is within SESSION_TTL_SECS or newly created"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads session_state table",
        "writes new session_start if expired/missing"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "reset_session",
      "description": "Reset session start to current time, invalidating previous session spending totals",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&mut Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "()",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "session_start set to current epoch",
        "Database updated with new session_start"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes session_state table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "log_action",
      "description": "Log tool action to ledger table (Tier 1: unencrypted)",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "tool",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Tool name",
          "validators": []
        },
        {
          "name": "decision",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Decision: 'ALLOW' or 'DENY'",
          "validators": []
        },
        {
          "name": "category",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Spending category",
          "validators": []
        },
        {
          "name": "amount",
          "type_ref": "f64",
          "required": true,
          "default": "",
          "description": "Amount spent",
          "validators": []
        },
        {
          "name": "detail",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Additional detail",
          "validators": []
        }
      ],
      "output_type": "()",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Action logged to ledger table with current timestamp"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes ledger table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "session_spend",
      "description": "Get total allowed spending in category since session start",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "category",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Spending category (empty string for all)",
          "validators": []
        }
      ],
      "output_type": "f64",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns sum of amounts where decision='ALLOW' and timestamp >= session_start"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads ledger table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "total_spend",
      "description": "Get total allowed spending in category since given timestamp",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "category",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Spending category (empty for all)",
          "validators": []
        },
        {
          "name": "since",
          "type_ref": "f64",
          "required": true,
          "default": "",
          "description": "Unix epoch timestamp",
          "validators": []
        }
      ],
      "output_type": "f64",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns sum of allowed amounts since timestamp",
        "Returns 0.0 if database unopenable"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads ledger table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "recent_actions",
      "description": "Get last N actions from ledger in reverse chronological order",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "limit",
          "type_ref": "u32",
          "required": true,
          "default": "",
          "description": "Max number of actions to return",
          "validators": []
        }
      ],
      "output_type": "Vec<serde_json::Value>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns up to limit actions as JSON objects",
        "Ordered by id DESC (most recent first)"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads ledger table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "has_recent_allowed_action",
      "description": "Check if any of the last N allowed actions match search term(s) in tool name or detail. Supports pipe-delimited OR.",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "search",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Search term or pipe-delimited terms (e.g. 'EnterPlanMode|TaskCreate')",
          "validators": []
        },
        {
          "name": "within",
          "type_ref": "u32",
          "required": true,
          "default": "",
          "description": "Number of recent allowed actions to search (clamped 1-500)",
          "validators": []
        }
      ],
      "output_type": "bool",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns true if any term found in tool or detail columns",
        "Returns false if no match or empty search"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads ledger table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "store_credential",
      "description": "Store credential with tier-based encryption (no expiry or metadata)",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "name",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Credential name (unique key)",
          "validators": []
        },
        {
          "name": "value",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Credential value",
          "validators": []
        },
        {
          "name": "tier",
          "type_ref": "u8",
          "required": true,
          "default": "",
          "description": "Security tier: 2 (session-key) or 3 (compartment-key)",
          "validators": []
        }
      ],
      "output_type": "()",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Credential encrypted and stored",
        "Replaces existing credential with same name"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes credentials table",
        "generates random nonce"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "store_credential_with_expiry",
      "description": "Store credential with tier-based encryption and optional expiry",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "name",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "value",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "tier",
          "type_ref": "u8",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "expires_at",
          "type_ref": "Option<f64>",
          "required": true,
          "default": "",
          "description": "Unix epoch expiry timestamp",
          "validators": []
        }
      ],
      "output_type": "()",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Credential stored with expiry timestamp"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes credentials table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "store_credential_full",
      "description": "Store credential with full metadata and optional expiry",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "name",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "value",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "tier",
          "type_ref": "u8",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "expires_at",
          "type_ref": "Option<f64>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "metadata",
          "type_ref": "Option<&CredentialMeta>",
          "required": true,
          "default": "",
          "description": "Constraint metadata",
          "validators": []
        }
      ],
      "output_type": "()",
      "error_cases": [
        {
          "name": "db_write_failure",
          "condition": "Database write fails",
          "error_type": "panic",
          "error_data": {
            "message": "unwrap on execute failed"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Credential stored with metadata serialized as JSON"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes credentials table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "get_credential",
      "description": "Retrieve and decrypt credential by name. Returns None if expired or not found.",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "name",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Option<String>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns Some(value) if found, valid, and decrypts successfully",
        "Returns None if not found, expired, or decryption fails"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads credentials table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "get_credential_meta",
      "description": "Get credential metadata without retrieving value",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "name",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Option<CredentialMeta>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns deserialized metadata if found and valid JSON"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads credentials table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "request_capability",
      "description": "Request scoped capability token for credential. Enforces domain, purpose, and amount constraints. Invalidates one-time credentials after use.",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "name",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Credential name",
          "validators": []
        },
        {
          "name": "domain",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Requested domain",
          "validators": []
        },
        {
          "name": "amount",
          "type_ref": "f64",
          "required": true,
          "default": "",
          "description": "Requested amount",
          "validators": []
        },
        {
          "name": "purpose",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "Requested purpose",
          "validators": []
        }
      ],
      "output_type": "Result<String, String>",
      "error_cases": [
        {
          "name": "domain_mismatch",
          "condition": "domain constraint violated",
          "error_type": "Result::Err",
          "error_data": {
            "message": "Credential scoped to different domain"
          }
        },
        {
          "name": "purpose_mismatch",
          "condition": "purpose constraint violated",
          "error_type": "Result::Err",
          "error_data": {
            "message": "Credential scoped to different purpose"
          }
        },
        {
          "name": "amount_exceeded",
          "condition": "amount > max_amount",
          "error_type": "Result::Err",
          "error_data": {
            "message": "Amount exceeds cap"
          }
        },
        {
          "name": "not_found_or_expired",
          "condition": "Credential not found or expired",
          "error_type": "Result::Err",
          "error_data": {
            "message": "Credential not found or expired"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "On success: returns credential value, logs action, deletes if one_time",
        "On failure: returns error message"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads credentials table",
        "writes ledger table",
        "deletes credential if one_time"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "delete_credential",
      "description": "Delete credential by name",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "name",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "bool",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns true if credential existed and was deleted",
        "Returns false if not found or error"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes credentials table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "credential_exists",
      "description": "Check if credential exists by name",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "name",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "bool",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns true if credential found in database"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads credentials table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "list_credentials",
      "description": "List all credentials with metadata (values not included)",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Vec<serde_json::Value>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns array of credential info objects"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads credentials table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "store_preflight",
      "description": "Store new preflight task with HMAC signature. Deactivates previous active preflight. Validates constraints.",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "preflight",
          "type_ref": "&Preflight",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Result<(), String>",
      "error_cases": [
        {
          "name": "too_many_constraints",
          "condition": "constraints.len() > MAX_PREFLIGHT_CONSTRAINTS",
          "error_type": "Result::Err",
          "error_data": {
            "message": "Too many constraints"
          }
        },
        {
          "name": "empty_alternative",
          "condition": "Any constraint has empty alternative",
          "error_type": "Result::Err",
          "error_data": {
            "message": "Constraint has empty alternative"
          }
        },
        {
          "name": "invalid_action",
          "condition": "action not DENY or ASK",
          "error_type": "Result::Err",
          "error_data": {
            "message": "action must be DENY or ASK"
          }
        },
        {
          "name": "serialize_error",
          "condition": "Cannot serialize preflight",
          "error_type": "Result::Err",
          "error_data": {
            "message": "serialize: {error}"
          }
        },
        {
          "name": "db_error",
          "condition": "Database operation fails",
          "error_type": "Result::Err",
          "error_data": {
            "message": "db operation: {error}"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "On success: preflight stored as active, previous deactivated",
        "HMAC signature computed and stored"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes preflights table",
        "updates active flag"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "active_preflight",
      "description": "Get currently active preflight with HMAC verification. Returns None if expired, tampered, or not found.",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Option<Preflight>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns Some(preflight) if active, valid HMAC, not expired",
        "Returns None and deactivates if lockout expired",
        "Logs warning if HMAC mismatch"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads preflights table",
        "writes preflights table if lockout expired"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "is_preflight_locked",
      "description": "Check if active preflight is locked (cannot be replaced)",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "bool",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns true if lockout_until > now"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads preflights table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "log_preflight_violation",
      "description": "Record preflight violation. Increments violation_count. Sets escalated flag if threshold exceeded.",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "violation",
          "type_ref": "&PreflightViolation",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Result<(), String>",
      "error_cases": [
        {
          "name": "db_error",
          "condition": "Database operation fails",
          "error_type": "Result::Err",
          "error_data": {
            "message": "db operation: {error}"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Violation logged",
        "violation_count incremented",
        "escalated set to true if count >= DEFAULT_VIOLATION_THRESHOLD"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes preflight_violations table",
        "updates preflights table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "preflight_violations",
      "description": "Get violations for a preflight in reverse chronological order",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "preflight_id",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Vec<PreflightViolation>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns violations ordered by timestamp DESC"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads preflight_violations table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "preflight_history",
      "description": "Get preflight history (all preflights) in reverse chronological order",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "limit",
          "type_ref": "u32",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Vec<serde_json::Value>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns up to limit preflights as JSON objects"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads preflights table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "override_preflight",
      "description": "Deactivate active preflight (human override)",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Result<(), String>",
      "error_cases": [
        {
          "name": "no_active_preflight",
          "condition": "No active preflight found",
          "error_type": "Result::Err",
          "error_data": {
            "message": "No active preflight to override."
          }
        },
        {
          "name": "db_error",
          "condition": "Database operation fails",
          "error_type": "Result::Err",
          "error_data": {
            "message": "deactivate: {error}"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Active preflight deactivated"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes preflights table"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "preflight_hmac",
      "description": "Compute HMAC-SHA256 for preflight payload using session key",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&Vault",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "payload",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns base64-encoded HMAC with 'signet-preflight:' prefix"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "signet_dir",
      "description": "Get signet directory path. Uses SIGNET_DIR env var if set, else ~/.signet",
      "inputs": [],
      "output_type": "PathBuf",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns path to signet directory"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "dirs",
      "description": "Get user home directory path. Falls back to '.' if HOME not set.",
      "inputs": [],
      "output_type": "PathBuf",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns home directory or current directory"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "meta_path",
      "description": "Get path to vault.meta file",
      "inputs": [],
      "output_type": "PathBuf",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns {signet_dir}/vault.meta"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "db_path",
      "description": "Get path to SQLite database file",
      "inputs": [],
      "output_type": "PathBuf",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns {signet_dir}/state.db"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "session_key_path",
      "description": "Get path to encrypted session key cache file",
      "inputs": [],
      "output_type": "PathBuf",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns {signet_dir}/.session_key"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "vault_exists",
      "description": "Check if vault has been initialized",
      "inputs": [],
      "output_type": "bool",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns true if vault.meta file exists"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "pause_path",
      "description": "Get path to pause_until file",
      "inputs": [],
      "output_type": "PathBuf",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns {signet_dir}/pause_until"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "set_pause_file",
      "description": "Set pause-until timestamp in file (no vault required)",
      "inputs": [
        {
          "name": "pause_until",
          "type_ref": "u64",
          "required": true,
          "default": "",
          "description": "Unix timestamp",
          "validators": []
        }
      ],
      "output_type": "()",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "pause_until file created/updated with timestamp"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "creates signet directory if needed",
        "writes pause_until file"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "is_paused_file",
      "description": "Check if paused via file. Auto-expires and cleans up expired pause.",
      "inputs": [],
      "output_type": "bool",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns true if current time < pause_until",
        "Deletes pause file if expired"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads pause_until file",
        "may delete pause_until file"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "clear_pause_file",
      "description": "Remove pause file (resume)",
      "inputs": [],
      "output_type": "()",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "pause_until file deleted if exists"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "deletes pause_until file"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "pause_until_file",
      "description": "Get pause expiry timestamp from file (0 if not paused)",
      "inputs": [],
      "output_type": "u64",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns pause_until timestamp or 0"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads pause_until file"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "disabled_path",
      "description": "Get path to disabled flag file",
      "inputs": [],
      "output_type": "PathBuf",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns {signet_dir}/disabled"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "set_disabled_file",
      "description": "Set disabled flag (bypass all rules including self-protection)",
      "inputs": [],
      "output_type": "()",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "disabled file created"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "creates signet directory if needed",
        "writes disabled file"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "is_disabled_file",
      "description": "Check if fully disabled",
      "inputs": [],
      "output_type": "bool",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns true if disabled file exists"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "clear_disabled_file",
      "description": "Remove disabled flag (re-enable)",
      "inputs": [],
      "output_type": "()",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "disabled file deleted if exists"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "deletes disabled file"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "device_key",
      "description": "Derive device-specific key from machine ID and username using HKDF. Not a passphrase—prevents trivial session key file copying.",
      "inputs": [],
      "output_type": "[u8; 32]",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns deterministic key for this device+user",
        "Falls back to default if machine ID unavailable"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads /etc/machine-id or /var/lib/dbus/machine-id",
        "on macOS: runs ioreg command",
        "reads USER env var"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "encrypt_session_key",
      "description": "Encrypt master key with device key for disk storage",
      "inputs": [
        {
          "name": "master_key",
          "type_ref": "&[u8; 32]",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Vec<u8>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns AES-256-GCM encrypted master key"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads device key",
        "generates random nonce"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "decrypt_session_key",
      "description": "Decrypt session key file with device key",
      "inputs": [
        {
          "name": "encrypted",
          "type_ref": "&[u8]",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Option<[u8; 32]>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns Some(key) if decryption succeeds and length correct",
        "Returns None on failure"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads device key"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "setup_vault",
      "description": "Initialize new vault with passphrase. Creates directory, generates salt, derives keys, writes metadata and encrypted session key cache.",
      "inputs": [
        {
          "name": "passphrase",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Result<Vault, String>",
      "error_cases": [
        {
          "name": "mkdir_error",
          "condition": "Cannot create directory",
          "error_type": "Result::Err",
          "error_data": {
            "message": "mkdir: {error}"
          }
        },
        {
          "name": "write_meta_error",
          "condition": "Cannot write vault.meta",
          "error_type": "Result::Err",
          "error_data": {
            "message": "write meta: {error}"
          }
        },
        {
          "name": "write_key_error",
          "condition": "Cannot write session key cache",
          "error_type": "Result::Err",
          "error_data": {
            "message": "write key: {error}"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "On success: vault initialized, metadata written, session key cached, database initialized",
        "Session key file has 0600 permissions on Unix"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "creates signet directory",
        "writes vault.meta",
        "writes .session_key",
        "creates database"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "unlock_vault",
      "description": "Unlock existing vault with passphrase. Enforces brute-force lockout. Updates session key cache on success.",
      "inputs": [
        {
          "name": "passphrase",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Result<Vault, String>",
      "error_cases": [
        {
          "name": "no_vault",
          "condition": "vault.meta not found",
          "error_type": "Result::Err",
          "error_data": {
            "message": "No vault found. Run 'signet-eval setup' first."
          }
        },
        {
          "name": "locked_out",
          "condition": "failed_attempts >= MAX_FAILED_ATTEMPTS and lockout active",
          "error_type": "Result::Err",
          "error_data": {
            "message": "Vault locked for N more seconds"
          }
        },
        {
          "name": "wrong_passphrase",
          "condition": "key_check mismatch",
          "error_type": "Result::Err",
          "error_data": {
            "message": "Wrong passphrase (N/5 attempts)"
          }
        }
      ],
      "preconditions": [],
      "postconditions": [
        "On success: returns vault, resets failed_attempts, updates session key cache",
        "On failure: increments failed_attempts, sets lockout if threshold reached"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads vault.meta",
        "writes vault.meta on failed attempts",
        "writes .session_key on success"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "try_load_vault",
      "description": "Attempt to load vault from cached session key (hook mode—no passphrase prompt). Verifies key against metadata.",
      "inputs": [],
      "output_type": "Option<Vault>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns Some(vault) if session key valid and verified",
        "Returns None if cache missing, invalid, or verification fails"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads .session_key",
        "reads vault.meta"
      ],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "make_test_vault",
      "description": "Test helper: create vault in temp directory",
      "inputs": [
        {
          "name": "dir",
          "type_ref": "&std::path::Path",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "passphrase",
          "type_ref": "&str",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Vault",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns initialized vault for testing"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    }
  ],
  "dependencies": [
    "aes_gcm",
    "argon2",
    "base64",
    "hkdf",
    "hmac",
    "rand",
    "rusqlite",
    "serde",
    "sha2",
    "std::path",
    "std::time"
  ],
  "dependency_contracts": {},
  "invariants": [
    "SALT_LEN = 32 bytes",
    "KEY_LEN = 32 bytes (AES-256)",
    "NONCE_LEN = 12 bytes (AES-GCM)",
    "SESSION_TTL_SECS = 1800.0 (30 minutes)",
    "MAX_FAILED_ATTEMPTS = 5",
    "LOCKOUT_SECS = 300.0 (5 minutes)",
    "MAX_PREFLIGHT_CONSTRAINTS = 20",
    "DEFAULT_VIOLATION_THRESHOLD = 5",
    "Master key derived via Argon2id (memory-hard KDF)",
    "Session key and compartment key derived from master via HKDF-SHA256",
    "Tier 2 credentials encrypted with session_key",
    "Tier 3 credentials encrypted with compartment_key",
    "All encryption uses AES-256-GCM with random nonce prepended",
    "Policy HMAC uses session_key with 'signet-vault-check' domain separation",
    "Preflight HMAC uses session_key with 'signet-preflight:' prefix",
    "Session key cache encrypted with device-specific key (HKDF from machine-id + username)",
    "Ledger (Tier 1) stored unencrypted in SQLite",
    "Session spend tracking filtered to decision='ALLOW'",
    "Preflight constraints must have non-empty alternatives",
    "Constraint action must be 'DENY' or 'ASK'",
    "One-time credentials deleted after successful request_capability",
    "Expired credentials return None from get_credential",
    "Failed unlock attempts increment counter and trigger lockout at threshold",
    "Lockout auto-expires after LOCKOUT_SECS",
    "HMAC mismatch on preflight triggers warning and returns None",
    "Preflight lockout_until check auto-deactivates expired preflights"
  ],
  "requires": [],
  "processing_register": "",
  "data_access": {
    "reads": [
      "filesystem",
      "environment_variables",
      "system_clock",
      "system_rng"
    ],
    "writes": [
      "filesystem",
      "sqlite_database"
    ],
    "rationale": "Reads vault metadata, policy files, machine ID, env vars (SIGNET_DIR, HOME, USER). Writes vault.meta, .session_key, state.db, policy HMAC files. Uses system RNG for salt/nonce generation.",
    "side_effects": [
      {
        "type": "filesystem_read",
        "classification": "vault_metadata",
        "fields": [
          "vault.meta",
          "policy.yaml",
          "policy.hmac",
          ".session_key",
          "/etc/machine-id",
          "/var/lib/dbus/machine-id"
        ],
        "rationale": "Reads vault configuration and policy signatures"
      },
      {
        "type": "filesystem_write",
        "classification": "vault_state",
        "fields": [
          "vault.meta",
          ".session_key",
          "policy.hmac",
          "pause_until",
          "disabled"
        ],
        "rationale": "Writes vault metadata, session key cache, policy signatures, pause/disable flags"
      },
      {
        "type": "database_write",
        "classification": "ledger_credentials_preflights",
        "fields": [
          "ledger",
          "credentials",
          "session_state",
          "preflights",
          "preflight_violations"
        ],
        "rationale": "SQLite writes for action logging, credential storage, session tracking, preflight enforcement"
      },
      {
        "type": "database_read",
        "classification": "ledger_credentials_preflights",
        "fields": [
          "ledger",
          "credentials",
          "session_state",
          "preflights",
          "preflight_violations"
        ],
        "rationale": "SQLite reads for spending queries, credential retrieval, preflight validation"
      },
      {
        "type": "system_rng",
        "classification": "entropy",
        "fields": [],
        "rationale": "Generates salts, nonces, random IDs"
      },
      {
        "type": "system_clock",
        "classification": "timing",
        "fields": [],
        "rationale": "Session TTL, lockout timing, credential expiry"
      },
      {
        "type": "environment_variables",
        "classification": "configuration",
        "fields": [
          "SIGNET_DIR",
          "HOME",
          "USER"
        ],
        "rationale": "Directory location and device key derivation"
      },
      {
        "type": "subprocess",
        "classification": "device_identification",
        "fields": [
          "ioreg"
        ],
        "rationale": "macOS hardware UUID extraction for device key"
      }
    ]
  },
  "authority": {
    "domains": [
      "vault_encryption",
      "credential_storage",
      "spending_ledger",
      "preflight_management",
      "policy_integrity"
    ],
    "rationale": "Vault owns encrypted state storage, key derivation, credential lifecycle, spending tracking, and preflight constraint enforcement for signet-eval"
  }
}