Skip to content

Remove Pydantic dependency - #37

Merged
corv89 merged 2 commits into
mainfrom
core
Nov 7, 2025
Merged

Remove Pydantic dependency#37
corv89 merged 2 commits into
mainfrom
core

Conversation

@corv89

@corv89 corv89 commented Nov 7, 2025

Copy link
Copy Markdown
Owner

Replace Pydantic models with dataclasses and custom validation throughout the codebase. This eliminates all external dependencies from the core package while maintaining full type safety, validation, and security.

Changes:

  • Add shannot/validation.py with custom ValidationError and validation helpers
  • Convert all Pydantic BaseModel classes to dataclasses in config.py and tools.py
  • Add from_dict() class methods for validation (replaces .model_validate())
  • Add post_init() to SSHExecutorConfig for path expansion
  • Update MCP server to use ValidationError from shannot.validation
  • Update all tests to use custom validation instead of Pydantic
  • Remove pydantic from all dependencies in pyproject.toml
  • Remove pydantic-ai optional dependency entirely
  • Update documentation to reflect dataclass-based models

Benefits:

  • Zero external dependencies for core package
  • Maintained all validation logic and security features
  • Preserved type safety with full type hints
  • Better performance without Pydantic overhead
  • All 90 tests passing

Validation maintained:

  • Command injection prevention via list validation
  • Path expansion for SSH keys and known_hosts
  • Type checking for all configuration fields
  • Port range validation (1-65535)
  • Boolean validation for security flags
  • Required field validation

Replace Pydantic models with dataclasses and custom validation throughout
the codebase. This eliminates all external dependencies from the core
package while maintaining full type safety, validation, and security.

Changes:
- Add shannot/validation.py with custom ValidationError and validation helpers
- Convert all Pydantic BaseModel classes to dataclasses in config.py and tools.py
- Add from_dict() class methods for validation (replaces .model_validate())
- Add __post_init__() to SSHExecutorConfig for path expansion
- Update MCP server to use ValidationError from shannot.validation
- Update all tests to use custom validation instead of Pydantic
- Remove pydantic from all dependencies in pyproject.toml
- Remove pydantic-ai optional dependency entirely
- Update documentation to reflect dataclass-based models

Benefits:
- Zero external dependencies for core package
- Maintained all validation logic and security features
- Preserved type safety with full type hints
- Better performance without Pydantic overhead
- All 90 tests passing

Validation maintained:
- Command injection prevention via list validation
- Path expansion for SSH keys and known_hosts
- Type checking for all configuration fields
- Port range validation (1-65535)
- Boolean validation for security flags
- Required field validation
@corv89 corv89 self-assigned this Nov 7, 2025
@corv89 corv89 added the enhancement New feature or request label Nov 7, 2025
@github-actions

github-actions Bot commented Nov 7, 2025

Copy link
Copy Markdown

CHANGELOG.md is out of date

Please update the changelog by running:

make changelog

Or manually:

git-cliff --config cliff.toml -o CHANGELOG.md

Then commit the updated CHANGELOG.md file.

@github-actions

github-actions Bot commented Nov 7, 2025

Copy link
Copy Markdown

MCP Server Test Results

MCP Server Test Summary

Generated: /__w/shannot/shannot

Test Execution

Test results from mcp-probe:

{
  "metadata": {
    "generated_at": "2025-11-07T06:43:21.695764397+00:00",
    "mcp_probe_version": "0.3.0",
    "total_duration_ms": 1200,
    "transport_type": "stdio"
  },
  "protocol_info": {
    "available_protocols": [
      {
        "endpoints": [
          "/mcp"
        ],
        "session_management": "Mcp-Session-Id header",
        "spec_date": "2025-03-26",
        "supported_methods": [
          "initialize",
          "initialized",
          "tools/list",
          "tools/call",
          "resources/list",
          "resources/read",
          "prompts/list",
          "prompts/get",
          "logging/setLevel",
          "notifications/*"
        ],
        "version": "Modern Streamable HTTP"
      },
      {
        "endpoints": [
          "/sse",
          "/events"
        ],
        "session_management": "sessionId query parameter",
        "spec_date": "2024-11-05",
        "supported_methods": [
          "initialize",
          "initialized",
          "tools/list",
          "tools/call",
          "resources/list",
          "resources/read",
          "prompts/list",
          "prompts/get",
          "logging/setLevel"
        ],
        "version": "Legacy HTTP+SSE"
      },
      {
        "endpoints": [
          "stdio"
        ],
        "session_management": "N/A (stdio)",
        "spec_date": "2025-03-26",
        "supported_methods": [
          "initialize",
          "initialized",
          "tools/list",
          "tools/call",
          "resources/list",
          "resources/read",
          "prompts/list",
          "prompts/get",
          "logging/setLevel",
          "notifications/*"
        ],
        "version": "Standard Transport"
      }
    ],
    "detected_protocol": {
      "endpoints": [
        "stdio"
      ],
      "session_management": "N/A (stdio)",
      "spec_date": "2025-03-26",
      "supported_methods": [
        "initialize",
        "initialized",
        "tools/list",
        "tools/call",
        "resources/list",
        "resources/read",
        "prompts/list",
        "prompts/get",
        "logging/setLevel",
        "notifications/*"
      ],
      "version": "Standard Transport"
    }
  },
  "results": [
    {
      "details": null,
      "duration_ms": 0,
      "message": "Successfully created MCP client",
      "name": "Connection",
      "status": "PASS"
    },
    {
      "details": {
        "name": "shannot-sandbox",
        "protocol_version": "2025-03-26",
        "version": "0.2.1"
      },
      "duration_ms": 395,
      "message": "Connected to shannot-sandbox v0.2.1",
      "name": "Initialization",
      "status": "PASS"
    },
    {
      "details": null,
      "duration_ms": 1,
      "message": "Server capabilities discovered successfully",
      "name": "Capability Discovery",
      "status": "PASS"
    },
    {
      "details": [
        {
          "description": "Execute read-only commands in 'minimal' sandbox on local sandbox. Allowed commands include: ls, /usr/bin/ls, /bin/ls, cat, /usr/bin/cat, ... (11 total). network isolated. Provide arguments as {\"command\": [\"ls\", \"/\"]}.",
          "input_schema": {
            "properties": {
              "command": {
                "description": "Command and arguments to execute",
                "items": {
                  "type": "string"
                },
                "type": "array"
              }
            },
            "required": [
              "command"
            ],
            "type": "object"
          },
          "name": "sandbox_minimal"
        },
        {
          "description": "Execute read-only commands in 'diagnostics' sandbox on local sandbox. Allowed commands include: ls, /usr/bin/ls, /bin/ls, cat, /usr/bin/cat, ... (31 total). network isolated. Provide arguments as {\"command\": [\"ls\", \"/\"]}.",
          "input_schema": {
            "properties": {
              "command": {
                "description": "Command and arguments to execute",
                "items": {
                  "type": "string"
                },
                "type": "array"
              }
            },
            "required": [
              "command"
            ],
            "type": "object"
          },
          "name": "sandbox_diagnostics"
        },
        {
          "description": "Execute read-only commands in 'readonly' sandbox on local sandbox. Allowed commands include: ls, /usr/bin/ls, cat, /usr/bin/cat, head, ... (13 total). network isolated. Provide arguments as {\"command\": [\"ls\", \"/\"]}.",
          "input_schema": {
            "properties": {
              "command": {
                "description": "Command and arguments to execute",
                "items": {
                  "type": "string"
                },
                "type": "array"
              }
            },
            "required": [
              "command"
            ],
            "type": "object"
          },
          "name": "sandbox_readonly"
        }
      ],
      "duration_ms": 1,
      "message": "Successfully listed 3 tools",
      "name": "Tools Listing",
      "status": "PASS"
    },
    {
      "details": [
        {
          "description": "Configuration for minimal sandbox profile",
          "name": "Sandbox Profile: minimal",
          "uri": "sandbox://profiles/minimal"
        },
        {
          "description": "Configuration for diagnostics sandbox profile",
          "name": "Sandbox Profile: diagnostics",
          "uri": "sandbox://profiles/diagnostics"
        },
        {
          "description": "Configuration for readonly sandbox profile",
          "name": "Sandbox Profile: readonly",
          "uri": "sandbox://profiles/readonly"
        }
      ],
      "duration_ms": 1,
      "message": "Successfully listed 3 resources",
      "name": "Resources Listing",
      "status": "PASS"
    },
    {
      "details": [
        {
          "arguments": [
            {
              "description": "Target environment for context (e.g., 'production', 'staging')",
              "name": "target",
              "required": false
            }
          ],
          "description": "Perform a comprehensive system health assessment checking disk space, memory, CPU, processes, and uptime",
          "name": "system-health-check"
        },
        {
          "arguments": [
            {
              "description": "Observed symptom (e.g., 'slow response', 'high load', 'memory exhaustion')",
              "name": "symptom",
              "required": false
            }
          ],
          "description": "Diagnose performance issues by checking resource consumption and identifying bottlenecks",
          "name": "investigate-performance"
        },
        {
          "arguments": [
            {
              "description": "Specific log file path to analyze (e.g., '/var/log/syslog')",
              "name": "log_path",
              "required": false
            },
            {
              "description": "Time period to analyze (e.g., 'last hour', 'today')",
              "name": "timeframe",
              "required": false
            }
          ],
          "description": "Search and analyze system logs to identify errors, warnings, and anomalies",
          "name": "analyze-logs"
        },
        {
          "arguments": [
            {
              "description": "Alert if disk usage exceeds this percentage (e.g., '80')",
              "name": "threshold",
              "required": false
            }
          ],
          "description": "Audit disk space usage to identify what's consuming storage and potential cleanup targets",
          "name": "disk-usage-audit"
        },
        {
          "arguments": [
            {
              "description": "Sort criteria: 'cpu', 'memory', or 'time'",
              "name": "sort_by",
              "required": false
            }
          ],
          "description": "Monitor and analyze running processes to identify resource-intensive or unusual activity",
          "name": "monitor-processes"
        },
        {
          "arguments": [
            {
              "description": "Name of the service to check (e.g., 'nginx', 'postgresql')",
              "name": "service_name",
              "required": true
            }
          ],
          "description": "Check the status and health of a specific system service",
          "name": "check-service-status"
        }
      ],
      "duration_ms": 0,
      "message": "Successfully listed 6 prompts",
      "name": "Prompts Listing",
      "status": "PASS"
    },
    {
      "details": {
        "code": -32602,
        "data": "",
        "message": "Invalid request parameters"
      },
      "duration_ms": 0,
      "message": "Unexpected error code: -32602",
      "name": "Error Handling",
      "status": "WARN"
    }
  ],
  "summary": {
    "failed": 0,
    "passed": 6,
    "skipped": 0,
    "total_tests": 7,
    "warnings": 1
  }
}

Artifacts

  • 20251107-test-report-064321.json (8,991 bytes)

@corv89
corv89 marked this pull request as ready for review November 7, 2025 06:45
@corv89
corv89 merged commit 39aafab into main Nov 7, 2025
16 checks passed
@corv89
corv89 deleted the core branch November 7, 2025 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant