{
  "component_id": "src_mcp_server.rs",
  "name": "Signet MCP Management Server",
  "description": "MCP (Model Context Protocol) server for conversational policy management through Claude. Provides tools for managing policy rules, credentials, spending limits, preflights, and vault operations. Handles policy CRUD, validation, testing, signing, and enforcement configuration.",
  "version": 1,
  "types": [
    {
      "name": "SignetMcpServer",
      "kind": "struct",
      "fields": [],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "MCP server implementation for Signet policy management. Zero-sized struct implementing ServerHandler trait.",
      "owner_component": ""
    },
    {
      "name": "PolicyConfig",
      "kind": "struct",
      "fields": [
        {
          "name": "version",
          "type_ref": "i32",
          "required": true,
          "default": "1",
          "description": "Policy schema version",
          "validators": []
        },
        {
          "name": "rules",
          "type_ref": "Vec<PolicyRule>",
          "required": true,
          "default": "vec![]",
          "description": "Ordered list of policy rules",
          "validators": []
        },
        {
          "name": "default_action",
          "type_ref": "Decision",
          "required": true,
          "default": "Decision::Allow",
          "description": "Default decision when no rules match",
          "validators": []
        }
      ],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "Policy configuration structure containing version, rules, and default action. Default implementation defined in this module.",
      "owner_component": "crate::policy"
    },
    {
      "name": "Tool",
      "kind": "struct",
      "fields": [
        {
          "name": "name",
          "type_ref": "Cow<'static, str>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "description",
          "type_ref": "Option<Cow<'static, str>>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "input_schema",
          "type_ref": "Arc<serde_json::Map<String, Value>>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "MCP tool definition with name, description, and JSON schema.",
      "owner_component": "rmcp::model"
    },
    {
      "name": "ServerInfo",
      "kind": "struct",
      "fields": [],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "MCP server metadata including instructions and capabilities.",
      "owner_component": "rmcp::model"
    },
    {
      "name": "ListToolsResult",
      "kind": "struct",
      "fields": [
        {
          "name": "tools",
          "type_ref": "Vec<Tool>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "next_cursor",
          "type_ref": "Option<String>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "meta",
          "type_ref": "Option<serde_json::Value>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "Response for list_tools MCP request.",
      "owner_component": "rmcp::model"
    },
    {
      "name": "CallToolResult",
      "kind": "struct",
      "fields": [],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "Response for call_tool MCP request.",
      "owner_component": "rmcp::model"
    },
    {
      "name": "Content",
      "kind": "struct",
      "fields": [],
      "item_type": "",
      "variants": [],
      "inner_types": [],
      "description": "MCP content item (text or other types).",
      "owner_component": "rmcp::model"
    }
  ],
  "functions": [
    {
      "name": "policy_path",
      "description": "Returns the filesystem path to the policy YAML file in the signet directory.",
      "inputs": [],
      "output_type": "PathBuf",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns path to policy.yaml in signet directory"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "vault::signet_dir()",
          "description": "Calls vault::signet_dir() to get base path"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "load_policy_raw",
      "description": "Loads the policy configuration from the YAML file. Returns default PolicyConfig on file read or parse errors.",
      "inputs": [],
      "output_type": "PolicyConfig",
      "error_cases": [
        {
          "name": "file_read_error",
          "condition": "Policy file cannot be read",
          "error_type": "Silent - returns PolicyConfig::default()",
          "error_data": {}
        },
        {
          "name": "yaml_parse_error",
          "condition": "YAML parsing fails",
          "error_type": "Silent - returns PolicyConfig::default()",
          "error_data": {}
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Returns valid PolicyConfig (default if file missing or invalid)"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": "Reads and parses policy YAML file"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "save_policy",
      "description": "Serializes and saves the policy configuration to the YAML file. Creates parent directories if needed. Silently ignores errors.",
      "inputs": [
        {
          "name": "config",
          "type_ref": "&PolicyConfig",
          "required": true,
          "default": "",
          "description": "Policy configuration to save",
          "validators": []
        }
      ],
      "output_type": "()",
      "error_cases": [
        {
          "name": "serialization_error",
          "condition": "serde_yaml::to_string fails",
          "error_type": "Silent - no write occurs",
          "error_data": {}
        },
        {
          "name": "write_error",
          "condition": "std::fs::write fails",
          "error_type": "Silent - errors ignored",
          "error_data": {}
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Policy written to disk if serialization and write succeed"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes_file"
      ],
      "structured_side_effects": [
        {
          "kind": "writes_file",
          "target": "policy.yaml",
          "description": "Writes YAML to policy file"
        },
        {
          "kind": "writes_file",
          "target": "parent directory",
          "description": "Creates parent directories if missing"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "auto_sign_policy",
      "description": "Automatically signs the policy file with HMAC if vault is available. Silently skips if vault is unavailable or signing fails.",
      "inputs": [],
      "output_type": "()",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "vault::try_load_vault() returns None",
          "error_type": "Silent - no signing occurs",
          "error_data": {}
        },
        {
          "name": "signing_error",
          "condition": "vault::sign_policy fails",
          "error_type": "Silent - error ignored",
          "error_data": {}
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Policy signed if vault available and signing succeeds"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes_file",
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault::try_load_vault()"
        },
        {
          "kind": "writes_file",
          "target": "policy HMAC",
          "description": "Calls vault::sign_policy()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "make_tool",
      "description": "Constructs an MCP Tool object with name, description, and JSON schema for tool inputs.",
      "inputs": [
        {
          "name": "name",
          "type_ref": "&'static str",
          "required": true,
          "default": "",
          "description": "Tool name",
          "validators": []
        },
        {
          "name": "desc",
          "type_ref": "&'static str",
          "required": true,
          "default": "",
          "description": "Tool description",
          "validators": []
        },
        {
          "name": "schema",
          "type_ref": "serde_json::Value",
          "required": true,
          "default": "",
          "description": "JSON schema for tool inputs",
          "validators": []
        }
      ],
      "output_type": "Tool",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns populated Tool instance"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "get_info",
      "description": "Returns MCP server metadata: instructions and capabilities. Part of ServerHandler trait implementation.",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&SignetMcpServer",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "ServerInfo",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns ServerInfo with instructions and tool capabilities enabled"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "list_tools",
      "description": "Returns the list of all available MCP tools for policy management. Async handler for MCP list_tools request.",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&SignetMcpServer",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "params",
          "type_ref": "Option<PaginatedRequestParams>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "ctx",
          "type_ref": "RequestContext<RoleServer>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Result<ListToolsResult, McpError>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns list of 23 tool definitions"
      ],
      "idempotent": false,
      "is_async": true,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "call_tool",
      "description": "Dispatches MCP tool calls to appropriate handlers based on tool name. Async handler for MCP call_tool request.",
      "inputs": [
        {
          "name": "self",
          "type_ref": "&SignetMcpServer",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "request",
          "type_ref": "CallToolRequestParams",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        },
        {
          "name": "ctx",
          "type_ref": "RequestContext<RoleServer>",
          "required": true,
          "default": "",
          "description": "",
          "validators": []
        }
      ],
      "output_type": "Result<CallToolResult, McpError>",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns CallToolResult with text content"
      ],
      "idempotent": false,
      "is_async": true,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "various",
          "description": "Delegates to handler functions which may read/write policy, vault, etc."
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_list_rules",
      "description": "Lists all policy rules with their properties: action, reason, conditions, gate/ensure config, lock status.",
      "inputs": [],
      "output_type": "String",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns formatted string listing all rules or default action message"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": "Calls load_policy_raw()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_add_rule",
      "description": "Adds a new policy rule. Validates action type, gate/ensure config, and rule uniqueness. Auto-signs policy after success.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing name, action, reason, tool_pattern, conditions, gate, ensure",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "invalid_action",
          "condition": "Action is not ALLOW, DENY, ASK, GATE, or ENSURE",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "duplicate_rule",
          "condition": "Rule with same name already exists",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "missing_gate_config",
          "condition": "GATE action without gate config or empty requires_prior",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "invalid_gate_within",
          "condition": "gate.within not in range 1-500",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "missing_ensure_config",
          "condition": "ENSURE action without ensure config",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "invalid_ensure_check",
          "condition": "ensure.check validation fails",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "invalid_ensure_timeout",
          "condition": "ensure.timeout not in range 1-30",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Rule name must not already exist",
        "Action must be ALLOW/DENY/ASK/GATE/ENSURE",
        "GATE requires gate.requires_prior",
        "ENSURE requires valid ensure.check"
      ],
      "postconditions": [
        "Rule added to policy",
        "Policy saved to disk",
        "Policy auto-signed"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file",
        "writes_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": "Loads existing policy"
        },
        {
          "kind": "writes_file",
          "target": "policy.yaml",
          "description": "Saves updated policy"
        },
        {
          "kind": "writes_file",
          "target": "policy HMAC",
          "description": "Calls auto_sign_policy()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_remove_rule",
      "description": "Removes a policy rule by name. Prevents removal of locked rules. Auto-signs policy after success.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing name",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "locked_rule",
          "condition": "Rule is locked (self-protection)",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "rule_not_found",
          "condition": "Rule with specified name does not exist",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Rule must exist",
        "Rule must not be locked"
      ],
      "postconditions": [
        "Rule removed from policy if found and not locked",
        "Policy saved and auto-signed"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file",
        "writes_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": ""
        },
        {
          "kind": "writes_file",
          "target": "policy.yaml",
          "description": ""
        },
        {
          "kind": "writes_file",
          "target": "policy HMAC",
          "description": ""
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_set_limit",
      "description": "Creates or updates a spending limit rule for a category. Replaces existing limit rule with same category/amount.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing category, max_amount, per, tool_pattern",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Spending limit rule created/updated",
        "Policy saved and auto-signed"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file",
        "writes_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": ""
        },
        {
          "kind": "writes_file",
          "target": "policy.yaml",
          "description": ""
        },
        {
          "kind": "writes_file",
          "target": "policy HMAC",
          "description": ""
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_status",
      "description": "Shows vault status, policy rule count, credential count, session spending, and recent actions.",
      "inputs": [],
      "output_type": "String",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns formatted status string"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": ""
        },
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault::try_load_vault()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_recent_actions",
      "description": "Returns recent action log entries from vault with limit parameter.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing limit (default 20)",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked"
      ],
      "postconditions": [
        "Returns formatted action log or error message"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault::try_load_vault() and recent_actions()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_store_credential",
      "description": "Stores a Tier 3 credential in the vault with compartment encryption.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing name and value",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked"
      ],
      "postconditions": [
        "Credential stored in vault as Tier 3"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault.store_credential()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_list_credentials",
      "description": "Lists credential names and tiers from vault (does not reveal values).",
      "inputs": [],
      "output_type": "String",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked"
      ],
      "postconditions": [
        "Returns formatted list of credential names and tiers"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault.list_credentials()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_delete_credential",
      "description": "Deletes a credential from the vault by name.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing name",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "credential_not_found",
          "condition": "Credential with specified name does not exist",
          "error_type": "String message (not error)",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked"
      ],
      "postconditions": [
        "Credential deleted if found"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault.delete_credential()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_validate",
      "description": "Validates the policy file for errors: bad regex patterns, unknown functions, malformed conditions.",
      "inputs": [],
      "output_type": "String",
      "error_cases": [
        {
          "name": "policy_load_error",
          "condition": "Policy file cannot be loaded",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Returns validation report with errors or success message"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": "Calls crate::policy::load_policy_config()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_test",
      "description": "Dry-run test of a tool call against the policy without executing it. Returns decision, matched rule, reason, and eval time.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing tool_name and tool_input",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns evaluation result with decision, matched rule, reason, and timing"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file",
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": "Calls crate::policy::load_policy()"
        },
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault::try_load_vault() for context"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_reorder_rule",
      "description": "Moves a rule to a new position in the policy. Prevents locked rules from being moved and prevents unlocked rules from being placed before locked rules.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing name and position (1-based)",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "invalid_position",
          "condition": "Position is 0",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "rule_not_found",
          "condition": "Rule with specified name does not exist",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "locked_rule",
          "condition": "Rule is locked",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Position must be >= 1",
        "Rule must exist",
        "Rule must not be locked"
      ],
      "postconditions": [
        "Rule moved to specified position (or first safe position)",
        "Policy saved and auto-signed"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file",
        "writes_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": ""
        },
        {
          "kind": "writes_file",
          "target": "policy.yaml",
          "description": ""
        },
        {
          "kind": "writes_file",
          "target": "policy HMAC",
          "description": ""
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_edit_rule",
      "description": "Edits properties of an existing rule. Prevents editing locked rules. Validates new action, gate, and ensure configs.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing name and optional fields: action, reason, tool_pattern, conditions, gate, ensure",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "rule_not_found",
          "condition": "Rule with specified name does not exist",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "locked_rule",
          "condition": "Rule is locked",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "invalid_action",
          "condition": "Action is not ALLOW, DENY, ASK, GATE, or ENSURE",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "invalid_gate_config",
          "condition": "gate.requires_prior is empty",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "invalid_ensure_check",
          "condition": "ensure.check validation fails",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Rule must exist",
        "Rule must not be locked"
      ],
      "postconditions": [
        "Rule properties updated",
        "Policy saved and auto-signed"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "reads_file",
        "writes_file"
      ],
      "structured_side_effects": [
        {
          "kind": "reads_file",
          "target": "policy.yaml",
          "description": ""
        },
        {
          "kind": "writes_file",
          "target": "policy.yaml",
          "description": ""
        },
        {
          "kind": "writes_file",
          "target": "policy HMAC",
          "description": ""
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_sign_policy",
      "description": "Signs the policy file with HMAC for tamper detection using vault session key.",
      "inputs": [],
      "output_type": "String",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "signing_error",
          "condition": "vault::sign_policy fails",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked"
      ],
      "postconditions": [
        "Policy HMAC written to disk"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "writes_file"
      ],
      "structured_side_effects": [
        {
          "kind": "writes_file",
          "target": "policy HMAC",
          "description": "Calls vault::sign_policy()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_reset_session",
      "description": "Rejects session reset requests from MCP to prevent spending limit bypass. Returns explanation message.",
      "inputs": [],
      "output_type": "String",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns rejection message"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "handle_use_credential",
      "description": "Requests a credential through policy-gated capability system. Enforces domain, purpose, amount, and one-time constraints. Returns masked credential value.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing name, domain, amount, purpose",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "credential_denied",
          "condition": "vault.request_capability() returns Err",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked"
      ],
      "postconditions": [
        "Credential released if policy allows",
        "Usage logged to vault"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault.request_capability()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_condition_help",
      "description": "Returns comprehensive documentation of all available condition functions with examples.",
      "inputs": [],
      "output_type": "String",
      "error_cases": [],
      "preconditions": [],
      "postconditions": [
        "Returns formatted help text"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "parse_soft_constraints",
      "description": "Parses and validates soft constraint array from preflight submission arguments.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Arguments containing constraints array",
          "validators": []
        }
      ],
      "output_type": "Result<Vec<vault::SoftConstraint>, String>",
      "error_cases": [
        {
          "name": "missing_constraints",
          "condition": "constraints key missing or not array",
          "error_type": "Err(String)",
          "error_data": {}
        },
        {
          "name": "invalid_constraint_object",
          "condition": "Constraint is not a JSON object",
          "error_type": "Err(String)",
          "error_data": {}
        },
        {
          "name": "empty_name",
          "condition": "Constraint name is empty",
          "error_type": "Err(String)",
          "error_data": {}
        },
        {
          "name": "invalid_action",
          "condition": "Action is not DENY or ASK",
          "error_type": "Err(String)",
          "error_data": {}
        },
        {
          "name": "empty_alternative",
          "condition": "Alternative (plan B) is empty",
          "error_type": "Err(String)",
          "error_data": {}
        },
        {
          "name": "invalid_regex",
          "condition": "tool_pattern is not valid regex",
          "error_type": "Err(String)",
          "error_data": {}
        }
      ],
      "preconditions": [
        "constraints array must exist",
        "Each constraint must have name, tool_pattern, conditions, action, reason, alternative"
      ],
      "postconditions": [
        "Returns validated SoftConstraint vector on success"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "handle_preflight_submit",
      "description": "Files a preflight: declares task intent, risks, and self-imposed constraints before starting work. Constraints are HMAC-signed and locked for specified duration.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing task, risks, constraints, lockout_minutes",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "empty_task",
          "condition": "Task description is empty",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "invalid_lockout_min",
          "condition": "Lockout < 5 minutes",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "invalid_lockout_max",
          "condition": "Lockout > 480 minutes",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "constraint_validation_error",
          "condition": "parse_soft_constraints returns Err",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "active_locked_preflight",
          "condition": "Another preflight is locked and active",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "store_error",
          "condition": "vault.store_preflight() returns Err",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked",
        "No active locked preflight",
        "Lockout must be 5-480 minutes",
        "Max 20 constraints (implied by parse validation)"
      ],
      "postconditions": [
        "Preflight stored in vault with HMAC signature",
        "Constraints active for lockout duration"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault.store_preflight()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_preflight_active",
      "description": "Shows the active preflight: task, risks, constraints, violation count, lockout status.",
      "inputs": [],
      "output_type": "String",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked"
      ],
      "postconditions": [
        "Returns formatted preflight details or 'no active' message"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault.active_preflight()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_preflight_history",
      "description": "Shows past preflights with their status, violations, and escalation state.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing limit (default 10)",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked"
      ],
      "postconditions": [
        "Returns formatted preflight history or 'no history' message"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault.preflight_history()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_preflight_violations",
      "description": "Shows constraint violations for the active or a specified preflight.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing optional preflight_id",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "vault_unavailable",
          "condition": "Vault not set up or locked",
          "error_type": "String error message",
          "error_data": {}
        },
        {
          "name": "no_active_no_id",
          "condition": "No preflight_id specified and no active preflight",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [
        "Vault must be set up and unlocked"
      ],
      "postconditions": [
        "Returns formatted violation list or 'no violations' message"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [
        "mutates_state"
      ],
      "structured_side_effects": [
        {
          "kind": "mutates_state",
          "target": "vault",
          "description": "Calls vault.preflight_violations()"
        }
      ],
      "performance_budget": null
    },
    {
      "name": "handle_preflight_test",
      "description": "Dry-run validation of preflight constraints without submitting. Tests constraint structure and logic.",
      "inputs": [
        {
          "name": "args",
          "type_ref": "&serde_json::Map<String, Value>",
          "required": true,
          "default": "",
          "description": "Tool arguments containing constraints array",
          "validators": []
        }
      ],
      "output_type": "String",
      "error_cases": [
        {
          "name": "validation_error",
          "condition": "parse_soft_constraints returns Err",
          "error_type": "String error message",
          "error_data": {}
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Returns validation result"
      ],
      "idempotent": false,
      "is_async": false,
      "side_effects": [],
      "structured_side_effects": [],
      "performance_budget": null
    },
    {
      "name": "run_server",
      "description": "Runs the MCP server on stdio transport. Async main entry point.",
      "inputs": [],
      "output_type": "Result<(), Box<dyn std::error::Error>>",
      "error_cases": [
        {
          "name": "server_error",
          "condition": "rmcp::serve_server or service.waiting() fails",
          "error_type": "Box<dyn std::error::Error>",
          "error_data": {}
        }
      ],
      "preconditions": [],
      "postconditions": [
        "Server running and serving requests on stdio"
      ],
      "idempotent": false,
      "is_async": true,
      "side_effects": [
        "network_call"
      ],
      "structured_side_effects": [
        {
          "kind": "network_call",
          "target": "stdio",
          "description": "Serves MCP protocol over stdio transport"
        }
      ],
      "performance_budget": null
    }
  ],
  "dependencies": [
    "rmcp::model",
    "rmcp",
    "rmcp::service",
    "rmcp::transport",
    "serde_json",
    "std::borrow",
    "std::path",
    "std::sync",
    "std::fs",
    "std::time",
    "crate::policy",
    "crate::vault",
    "regex",
    "serde_yaml"
  ],
  "dependency_contracts": {},
  "invariants": [
    "Policy path is always {signet_dir}/policy.yaml",
    "Locked rules cannot be removed, edited, or reordered",
    "Unlocked rules cannot be placed before locked rules in reorder",
    "GATE action requires gate.requires_prior to be non-empty",
    "GATE gate.within must be 1-500",
    "ENSURE action requires valid ensure.check name",
    "ENSURE ensure.timeout must be 1-30",
    "Soft constraints can only have DENY or ASK actions",
    "Soft constraints require non-empty alternative (plan B)",
    "Preflight lockout must be 5-480 minutes",
    "Session reset only allowed via CLI to prevent spending limit bypass",
    "Credentials masked in response (show last 4 chars only)",
    "Policy auto-signed after all mutation operations",
    "All file operations silently ignore errors in save_policy and auto_sign_policy",
    "Default PolicyConfig: version=1, rules=[], default_action=Allow"
  ],
  "requires": [],
  "processing_register": "",
  "data_access": {
    "reads": [
      "policy.yaml",
      "vault state"
    ],
    "writes": [
      "policy.yaml",
      "policy HMAC",
      "vault state"
    ],
    "rationale": "Reads and writes policy configuration. Reads/writes vault for credentials, spending, actions, preflights.",
    "side_effects": [
      {
        "type": "file_read",
        "classification": "sensitive",
        "fields": [
          "policy.yaml"
        ],
        "rationale": "Policy rules contain security-critical constraints"
      },
      {
        "type": "file_write",
        "classification": "sensitive",
        "fields": [
          "policy.yaml",
          "policy HMAC"
        ],
        "rationale": "Policy modifications affect security enforcement"
      },
      {
        "type": "state_mutation",
        "classification": "sensitive",
        "fields": [
          "vault credentials",
          "vault spending counters",
          "vault action log",
          "vault preflights"
        ],
        "rationale": "Vault operations involve encrypted credentials and financial tracking"
      }
    ]
  },
  "authority": {
    "domains": [
      "policy_management",
      "mcp_server",
      "vault_operations"
    ],
    "rationale": "Owns MCP server implementation for policy CRUD, credential management, and preflight operations. Authority over conversational policy interface."
  }
}