Coverage for src/alprina_cli/api/schemas/scan.py: 100%
41 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-14 11:27 +0100
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-14 11:27 +0100
1"""
2Scan-related request/response schemas.
3"""
5from pydantic import BaseModel, Field
6from typing import List, Optional, Dict, Any
9class CodeScanRequest(BaseModel):
10 """Request schema for code scanning."""
12 code: str = Field(..., description="Source code to scan", min_length=1)
13 language: str = Field(default="python", description="Programming language")
14 profile: str = Field(
15 default="code-audit",
16 description="Scan profile to use",
17 pattern="^(code-audit|secret-detection|config-audit|web-recon)$"
18 )
19 safe_only: bool = Field(default=True, description="Only run safe, non-intrusive checks")
20 metadata: Optional[Dict[str, Any]] = Field(default=None, description="Additional metadata")
22 class Config:
23 schema_extra = {
24 "example": {
25 "code": "def login(user, pwd):\\n query = f\\\"SELECT * FROM users WHERE user='{user}'\\\"",
26 "language": "python",
27 "profile": "code-audit",
28 "safe_only": True
29 }
30 }
33class Finding(BaseModel):
34 """Individual security finding."""
36 id: Optional[str] = Field(None, description="Finding ID")
37 severity: str = Field(..., description="Severity level")
38 type: str = Field(..., description="Vulnerability type")
39 title: str = Field(..., description="Finding title")
40 description: str = Field(..., description="Detailed description")
41 location: Optional[str] = Field(None, description="Location in code")
42 line: Optional[int] = Field(None, description="Line number")
43 confidence: Optional[float] = Field(None, description="Confidence score (0-1)")
46class ScanSummary(BaseModel):
47 """Summary of scan results."""
49 total_findings: int
50 critical: int = 0
51 high: int = 0
52 medium: int = 0
53 low: int = 0
54 info: int = 0
57class TargetScanRequest(BaseModel):
58 """Generic request schema for target-based scanning (file paths, URLs, systems)."""
60 target: str = Field(..., description="Target to scan (file path, URL, IP, etc.)", min_length=1)
61 safe_only: bool = Field(default=True, description="Only run safe, non-intrusive checks")
62 metadata: Optional[Dict[str, Any]] = Field(default=None, description="Additional metadata")
64 class Config:
65 schema_extra = {
66 "example": {
67 "target": "/path/to/app",
68 "safe_only": True,
69 "metadata": {"depth": "comprehensive"}
70 }
71 }
74class ScanResponse(BaseModel):
75 """Response schema for scan results."""
77 scan_id: str = Field(..., description="Unique scan identifier")
78 status: str = Field(..., description="Scan status")
79 scanned_by: str = Field(default="Alprina Security Engine")
80 alprina_engine: str = Field(..., description="Engine status (active/fallback)")
81 findings: List[Finding] = Field(default=[], description="List of findings")
82 summary: ScanSummary = Field(..., description="Scan summary")
83 duration_ms: Optional[int] = Field(None, description="Scan duration in milliseconds")
85 class Config:
86 schema_extra = {
87 "example": {
88 "scan_id": "scan_abc123",
89 "status": "completed",
90 "scanned_by": "Alprina Security Engine",
91 "alprina_engine": "active",
92 "findings": [
93 {
94 "id": "finding_1",
95 "severity": "HIGH",
96 "type": "SQL Injection",
97 "title": "SQL injection vulnerability detected",
98 "description": "User input directly interpolated into SQL query",
99 "location": "login.py:5",
100 "line": 5,
101 "confidence": 0.95
102 }
103 ],
104 "summary": {
105 "total_findings": 1,
106 "high": 1,
107 "medium": 0,
108 "low": 0
109 }
110 }
111 }