coding-client 1.21.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coding_client/__init__.py +1 -0
- coding_client/api/__init__.py +19 -0
- coding_client/api/exception_handlers.py +158 -0
- coding_client/api/logging_setup.py +44 -0
- coding_client/api/metrics.py +40 -0
- coding_client/api/openapi_config.py +124 -0
- coding_client/api/request_logging.py +60 -0
- coding_client/api/validation.py +150 -0
- coding_client/auth/__init__.py +78 -0
- coding_client/auth/_default_tenant.py +132 -0
- coding_client/auth/_header_trust.py +98 -0
- coding_client/auth/_onbehalf.py +315 -0
- coding_client/auth/_trusted_networks.py +94 -0
- coding_client/auth/dependencies.py +61 -0
- coding_client/auth/middleware.py +445 -0
- coding_client/auth/models.py +83 -0
- coding_client/auth/outbound.py +137 -0
- coding_client/auth/rbac.py +21 -0
- coding_client/auth/rbac_coding.py +5 -0
- coding_client/auth/tenant.py +650 -0
- coding_client/auth/websocket.py +148 -0
- coding_client/clients/__init__.py +24 -0
- coding_client/clients/base.py +131 -0
- coding_client/clients/coding_ai.py +33 -0
- coding_client/clients/coding_analysis.py +36 -0
- coding_client/clients/coding_containers.py +45 -0
- coding_client/clients/coding_github.py +127 -0
- coding_client/clients/coding_realtime.py +127 -0
- coding_client/clients/coding_security.py +51 -0
- coding_client/clients/coding_testing.py +31 -0
- coding_client/clients/coding_workspaces.py +265 -0
- coding_client/config/__init__.py +12 -0
- coding_client/config/base_settings.py +61 -0
- coding_client/config/yaml_config_loader.py +172 -0
- coding_client/db/__init__.py +42 -0
- coding_client/db/db_types.py +122 -0
- coding_client/db/exceptions.py +59 -0
- coding_client/db/postgres_connection.py +572 -0
- coding_client/db/tenant_query_helper.py +417 -0
- coding_client/db_init.py +49 -0
- coding_client/exceptions/__init__.py +67 -0
- coding_client/exceptions/api_exceptions.py +395 -0
- coding_client/exceptions/pydantic_ai_exceptions.py +533 -0
- coding_client/interfaces/__init__.py +22 -0
- coding_client/interfaces/cache_interface.py +179 -0
- coding_client/interfaces/container_interface.py +49 -0
- coding_client/interfaces/docker_interface.py +283 -0
- coding_client/interfaces/graph_interface.py +28 -0
- coding_client/interfaces/security_interface.py +72 -0
- coding_client/interfaces/webhook_interface.py +67 -0
- coding_client/llm/__init__.py +54 -0
- coding_client/llm/base_agent.py +195 -0
- coding_client/llm/context.py +121 -0
- coding_client/llm/responses.py +102 -0
- coding_client/llm/routing.py +82 -0
- coding_client/llm/settings.py +102 -0
- coding_client/models/__init__.py +62 -0
- coding_client/models/agent.py +38 -0
- coding_client/models/ai_test_failure.py +745 -0
- coding_client/models/analysis.py +330 -0
- coding_client/models/architecture.py +685 -0
- coding_client/models/bug.py +128 -0
- coding_client/models/code_graph.py +317 -0
- coding_client/models/container.py +241 -0
- coding_client/models/core.py +878 -0
- coding_client/models/docker_container.py +104 -0
- coding_client/models/github.py +293 -0
- coding_client/models/logging.py +29 -0
- coding_client/models/package_manager.py +257 -0
- coding_client/models/pr_validation.py +440 -0
- coding_client/models/pydantic_ai.py +395 -0
- coding_client/models/repo_scanner.py +249 -0
- coding_client/models/responses.py +431 -0
- coding_client/models/security.py +185 -0
- coding_client/models/static_analysis.py +508 -0
- coding_client/models/system.py +48 -0
- coding_client/models/test_executor.py +204 -0
- coding_client/models/testing.py +673 -0
- coding_client/models/testing_config.py +200 -0
- coding_client/models/validation.py +127 -0
- coding_client/models_init.py +272 -0
- coding_client/telemetry.py +195 -0
- coding_client/testing.py +180 -0
- coding_client/types/__init__.py +130 -0
- coding_client/types/constraint_types.py +276 -0
- coding_client/types/core_types.py +112 -0
- coding_client/types/state_machine.py +443 -0
- coding_client/utils/__init__.py +86 -0
- coding_client/utils/archive_utils.py +387 -0
- coding_client/utils/ast_debug.py +45 -0
- coding_client/utils/async_timeout.py +364 -0
- coding_client/utils/constants.py +518 -0
- coding_client/utils/content_processing.py +326 -0
- coding_client/utils/database.py +916 -0
- coding_client/utils/encoding_helper.py +222 -0
- coding_client/utils/enum_helpers.py +166 -0
- coding_client/utils/file_operations.py +177 -0
- coding_client/utils/filesystem_ops.py +528 -0
- coding_client/utils/http_client.py +562 -0
- coding_client/utils/path_utils.py +471 -0
- coding_client/utils/profiling.py +421 -0
- coding_client/utils/response_builder.py +240 -0
- coding_client/utils/retry_helper.py +712 -0
- coding_client/utils/security_validation.py +423 -0
- coding_client-1.21.2.dist-info/METADATA +234 -0
- coding_client-1.21.2.dist-info/RECORD +109 -0
- coding_client-1.21.2.dist-info/WHEEL +5 -0
- coding_client-1.21.2.dist-info/licenses/LICENSE +201 -0
- coding_client-1.21.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"""Testing configuration models for background tasks and quality analysis."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestingConfiguration(BaseModel):
|
|
12
|
+
"""Configuration for testing and quality analysis."""
|
|
13
|
+
|
|
14
|
+
# Basic settings
|
|
15
|
+
default_timeout: int = Field(
|
|
16
|
+
default=30, ge=1, le=300, description="Default test timeout in seconds"
|
|
17
|
+
)
|
|
18
|
+
max_memory_mb: int = Field(
|
|
19
|
+
default=512,
|
|
20
|
+
ge=128,
|
|
21
|
+
le=2048,
|
|
22
|
+
description="Maximum memory per container in MB",
|
|
23
|
+
)
|
|
24
|
+
max_cpu_quota: int = Field(
|
|
25
|
+
default=50000,
|
|
26
|
+
ge=10000,
|
|
27
|
+
le=100000,
|
|
28
|
+
description="Maximum CPU quota (100000 = 1 CPU)",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Security settings
|
|
32
|
+
network_isolation: bool = Field(
|
|
33
|
+
default=True, description="Enable network isolation for containers"
|
|
34
|
+
)
|
|
35
|
+
readonly_filesystem: bool = Field(
|
|
36
|
+
default=True, description="Use read-only filesystem for containers"
|
|
37
|
+
)
|
|
38
|
+
enable_security_scanning: bool = Field(
|
|
39
|
+
default=True, description="Enable security scanning of code"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Language-specific settings
|
|
43
|
+
python_version: str = Field(default="3.11", description="Python version to use")
|
|
44
|
+
node_version: str = Field(default="18", description="Node.js version to use")
|
|
45
|
+
|
|
46
|
+
# Quality tool settings
|
|
47
|
+
enabled_python_tools: list[str] = Field(
|
|
48
|
+
default=["ruff", "ruff-format", "ty", "bandit"],
|
|
49
|
+
description="Enabled Python quality tools",
|
|
50
|
+
)
|
|
51
|
+
enabled_js_tools: list[str] = Field(
|
|
52
|
+
default=["eslint", "prettier"],
|
|
53
|
+
description="Enabled JavaScript quality tools",
|
|
54
|
+
)
|
|
55
|
+
enabled_ts_tools: list[str] = Field(
|
|
56
|
+
default=["eslint", "prettier", "tsc"],
|
|
57
|
+
description="Enabled TypeScript quality tools",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Analysis settings
|
|
61
|
+
quality_score_threshold: float = Field(
|
|
62
|
+
default=7.0,
|
|
63
|
+
ge=0.0,
|
|
64
|
+
le=10.0,
|
|
65
|
+
description="Minimum quality score threshold",
|
|
66
|
+
)
|
|
67
|
+
auto_fix_enabled: bool = Field(
|
|
68
|
+
default=False, description="Enable automatic resolving of issues"
|
|
69
|
+
)
|
|
70
|
+
fail_on_security_issues: bool = Field(
|
|
71
|
+
default=True, description="Fail analysis on security issues"
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Caching settings
|
|
75
|
+
cache_test_results: bool = Field(default=True, description="Cache test execution results")
|
|
76
|
+
cache_quality_results: bool = Field(default=True, description="Cache quality analysis results")
|
|
77
|
+
cache_ttl_seconds: int = Field(
|
|
78
|
+
default=3600, ge=300, le=86400, description="Cache TTL in seconds"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Container settings
|
|
82
|
+
cleanup_containers: bool = Field(
|
|
83
|
+
default=True,
|
|
84
|
+
description="Automatically cleanup containers after execution",
|
|
85
|
+
)
|
|
86
|
+
container_registry: str = Field(default="docker.io", description="Container registry to use")
|
|
87
|
+
base_images: dict[str, str] = Field(
|
|
88
|
+
default={
|
|
89
|
+
"python": "code_graph_helper-api:latest",
|
|
90
|
+
"javascript": "node:18-slim",
|
|
91
|
+
"typescript": "node:18-slim",
|
|
92
|
+
},
|
|
93
|
+
description="Base container images for each language",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class DependencyScanConfig(BaseModel):
|
|
98
|
+
"""Configuration for dependency scanning tasks."""
|
|
99
|
+
|
|
100
|
+
enabled: bool = Field(default=True, description="Enable dependency scanning")
|
|
101
|
+
scan_dev_dependencies: bool = Field(
|
|
102
|
+
default=False, description="Include dev dependencies in scan"
|
|
103
|
+
)
|
|
104
|
+
security_advisory_check: bool = Field(default=True, description="Check for security advisories")
|
|
105
|
+
outdated_package_check: bool = Field(default=True, description="Check for outdated packages")
|
|
106
|
+
max_scan_time_seconds: int = Field(
|
|
107
|
+
default=300, ge=30, le=1800, description="Maximum scan time in seconds"
|
|
108
|
+
)
|
|
109
|
+
cache_scan_results: bool = Field(default=True, description="Cache dependency scan results")
|
|
110
|
+
cache_ttl_hours: int = Field(default=24, ge=1, le=168, description="Cache TTL in hours")
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class QualityScanConfig(BaseModel):
|
|
114
|
+
"""Configuration for quality scanning tasks."""
|
|
115
|
+
|
|
116
|
+
enabled: bool = Field(default=True, description="Enable quality scanning")
|
|
117
|
+
parallel_tool_execution: bool = Field(default=True, description="Run quality tools in parallel")
|
|
118
|
+
max_parallel_tools: int = Field(
|
|
119
|
+
default=4, ge=1, le=8, description="Maximum parallel tool executions"
|
|
120
|
+
)
|
|
121
|
+
fail_fast: bool = Field(default=False, description="Stop on first tool failure")
|
|
122
|
+
generate_reports: bool = Field(default=True, description="Generate quality reports")
|
|
123
|
+
include_suggestions: bool = Field(default=True, description="Include improvement suggestions")
|
|
124
|
+
max_scan_time_seconds: int = Field(
|
|
125
|
+
default=600, ge=60, le=3600, description="Maximum scan time in seconds"
|
|
126
|
+
)
|
|
127
|
+
cache_quality_results: bool = Field(default=True, description="Cache quality scan results")
|
|
128
|
+
cache_ttl_hours: int = Field(default=6, ge=1, le=72, description="Cache TTL in hours")
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class BackgroundTaskConfig(BaseModel):
|
|
132
|
+
"""Configuration for background task execution."""
|
|
133
|
+
|
|
134
|
+
max_concurrent_tasks: int = Field(
|
|
135
|
+
default=5, ge=1, le=20, description="Maximum concurrent background tasks"
|
|
136
|
+
)
|
|
137
|
+
task_timeout_seconds: int = Field(
|
|
138
|
+
default=1800, ge=300, le=7200, description="Task timeout in seconds"
|
|
139
|
+
)
|
|
140
|
+
retry_failed_tasks: bool = Field(default=True, description="Retry failed tasks")
|
|
141
|
+
max_retries: int = Field(default=3, ge=0, le=10, description="Maximum task retry attempts")
|
|
142
|
+
retry_delay_seconds: int = Field(
|
|
143
|
+
default=60, ge=10, le=300, description="Delay between retries in seconds"
|
|
144
|
+
)
|
|
145
|
+
cleanup_completed_tasks: bool = Field(default=True, description="Cleanup completed task data")
|
|
146
|
+
cleanup_delay_hours: int = Field(
|
|
147
|
+
default=24, ge=1, le=168, description="Delay before cleanup in hours"
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class TaskExecutionResult(BaseModel):
|
|
152
|
+
"""Result of a background task execution."""
|
|
153
|
+
|
|
154
|
+
task_id: str = Field(description="Unique task identifier")
|
|
155
|
+
task_type: str = Field(description="Type of task executed")
|
|
156
|
+
success: bool = Field(description="Whether task completed successfully")
|
|
157
|
+
start_time: datetime = Field(description="Task start timestamp")
|
|
158
|
+
end_time: datetime | None = Field(None, description="Task completion timestamp")
|
|
159
|
+
execution_time_seconds: float | None = Field(None, description="Task execution duration")
|
|
160
|
+
result_data: dict[str, Any] | None = Field(None, description="Task result data")
|
|
161
|
+
error_message: str | None = Field(None, description="Error message if failed")
|
|
162
|
+
retry_count: int = Field(default=0, description="Number of retry attempts")
|
|
163
|
+
metadata: dict[str, Any] | None = Field(None, description="Additional task metadata")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class TestingTaskQueueConfig(BaseModel):
|
|
167
|
+
"""Configuration for task queue management."""
|
|
168
|
+
|
|
169
|
+
queue_name: str = Field(description="Name of the task queue")
|
|
170
|
+
max_queue_size: int = Field(default=1000, ge=10, le=10000, description="Maximum queue size")
|
|
171
|
+
worker_count: int = Field(default=3, ge=1, le=10, description="Number of worker processes")
|
|
172
|
+
batch_size: int = Field(default=5, ge=1, le=50, description="Tasks processed per batch")
|
|
173
|
+
poll_interval_seconds: int = Field(
|
|
174
|
+
default=10, ge=1, le=60, description="Queue polling interval"
|
|
175
|
+
)
|
|
176
|
+
priority_enabled: bool = Field(default=True, description="Enable task priority handling")
|
|
177
|
+
dead_letter_queue: bool = Field(
|
|
178
|
+
default=True, description="Enable dead letter queue for failed tasks"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
# Factory function for creating default configurations
|
|
183
|
+
def get_default_testing_config() -> TestingConfiguration:
|
|
184
|
+
"""Get default testing configuration."""
|
|
185
|
+
return TestingConfiguration()
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def get_default_dependency_scan_config() -> DependencyScanConfig:
|
|
189
|
+
"""Get default dependency scan configuration."""
|
|
190
|
+
return DependencyScanConfig()
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def get_default_quality_scan_config() -> QualityScanConfig:
|
|
194
|
+
"""Get default quality scan configuration."""
|
|
195
|
+
return QualityScanConfig()
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def get_default_background_task_config() -> BackgroundTaskConfig:
|
|
199
|
+
"""Get default background task configuration."""
|
|
200
|
+
return BackgroundTaskConfig()
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Validation models for multi-language code validation endpoints.
|
|
2
|
+
|
|
3
|
+
This module provides language-specific validation models that ensure consistent
|
|
4
|
+
request/response structures across different programming languages. The models
|
|
5
|
+
are designed with Pydantic v2/v3 compatibility and support specialized validation
|
|
6
|
+
options for each supported language.
|
|
7
|
+
|
|
8
|
+
The validation system handles:
|
|
9
|
+
- Language-specific validation requirements (class names, project types, etc.)
|
|
10
|
+
- Consistent error reporting across all languages
|
|
11
|
+
- Type-safe request/response validation
|
|
12
|
+
- Proper field aliasing for API compatibility
|
|
13
|
+
|
|
14
|
+
Supported Languages:
|
|
15
|
+
- Python: General-purpose validation with filename support
|
|
16
|
+
- JavaScript/TypeScript: ES6+ and TypeScript validation
|
|
17
|
+
- Java: Class-based validation with className parameter
|
|
18
|
+
- Rust: Crate-based validation with crate type specification
|
|
19
|
+
- C#: Project-based validation with framework targeting
|
|
20
|
+
- Go: Package-based validation with Go module support
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
```python
|
|
24
|
+
from validation_models import JavaValidationRequest, ValidationResponse
|
|
25
|
+
|
|
26
|
+
# Create Java validation request
|
|
27
|
+
request = JavaValidationRequest(
|
|
28
|
+
code='public class Hello { public static void main(String[] args) { System.out.println("Hello"); } }',
|
|
29
|
+
className="Hello"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Process validation response
|
|
33
|
+
response = ValidationResponse(
|
|
34
|
+
validationId="val-123",
|
|
35
|
+
valid=True,
|
|
36
|
+
errors=[],
|
|
37
|
+
output="Compilation successful"
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
from __future__ import annotations
|
|
43
|
+
|
|
44
|
+
from typing import Literal
|
|
45
|
+
|
|
46
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class ValidationRequest(BaseModel):
|
|
50
|
+
"""Base validation request model."""
|
|
51
|
+
|
|
52
|
+
model_config = ConfigDict(
|
|
53
|
+
extra="forbid", # Reject extra fields
|
|
54
|
+
str_strip_whitespace=True, # Strip whitespace from strings
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
code: str = Field(..., description="Code to validate")
|
|
58
|
+
|
|
59
|
+
@field_validator("code")
|
|
60
|
+
@classmethod
|
|
61
|
+
def validate_code_not_none(cls, v: str) -> str:
|
|
62
|
+
"""Ensure code is provided and not None."""
|
|
63
|
+
if v is None:
|
|
64
|
+
raise ValueError("Code field is required")
|
|
65
|
+
return v
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class JavaScriptValidationRequest(ValidationRequest):
|
|
69
|
+
"""JavaScript/TypeScript validation request."""
|
|
70
|
+
|
|
71
|
+
filename: str | None = Field(default="test.js", description="Filename for validation")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class PythonValidationRequest(ValidationRequest):
|
|
75
|
+
"""Python validation request."""
|
|
76
|
+
|
|
77
|
+
filename: str | None = Field(default="test.py", description="Filename for validation")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class JavaValidationRequest(ValidationRequest):
|
|
81
|
+
"""Java validation request."""
|
|
82
|
+
|
|
83
|
+
className: str | None = Field(default="Test", description="Java class name")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class RustValidationRequest(ValidationRequest):
|
|
87
|
+
"""Rust validation request."""
|
|
88
|
+
|
|
89
|
+
crateType: Literal["bin", "lib"] | None = Field(default="bin", description="Crate type")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class CSharpValidationRequest(ValidationRequest):
|
|
93
|
+
"""C# validation request."""
|
|
94
|
+
|
|
95
|
+
projectType: Literal["console", "library"] | None = Field(
|
|
96
|
+
default="console", description="Project type"
|
|
97
|
+
)
|
|
98
|
+
targetFramework: str | None = Field(default="net8.0", description="Target framework")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class GoValidationRequest(ValidationRequest):
|
|
102
|
+
"""Go validation request."""
|
|
103
|
+
|
|
104
|
+
filename: str | None = Field(default="main.go", description="Filename for validation")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ValidationResponse(BaseModel):
|
|
108
|
+
"""Validation response model."""
|
|
109
|
+
|
|
110
|
+
model_config = ConfigDict(extra="forbid")
|
|
111
|
+
|
|
112
|
+
validationId: str = Field(..., description="Unique validation ID")
|
|
113
|
+
valid: bool = Field(..., description="Whether the code is valid")
|
|
114
|
+
errors: list[str] = Field(default_factory=list, description="List of validation errors")
|
|
115
|
+
output: str = Field(default="", description="Validation output")
|
|
116
|
+
warnings: list[str] | None = Field(default=None, description="List of warnings")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class CodeValidationErrorResponse(BaseModel):
|
|
120
|
+
"""Validation error response model."""
|
|
121
|
+
|
|
122
|
+
model_config = ConfigDict(extra="forbid")
|
|
123
|
+
|
|
124
|
+
validationId: str | None = Field(default=None, description="Validation ID if available")
|
|
125
|
+
valid: bool = Field(default=False, description="Always false for errors")
|
|
126
|
+
error: str = Field(..., description="Error message")
|
|
127
|
+
details: str | None = Field(default=None, description="Additional error details")
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SQLAlchemy ORM models for code graph database.
|
|
3
|
+
|
|
4
|
+
Models include:
|
|
5
|
+
- Node: Code entities (functions, classes, modules) with multi-language support
|
|
6
|
+
- Edge: Relationships between entities (calls, imports, inheritance)
|
|
7
|
+
- Codebase: Repository/project tracking
|
|
8
|
+
- SchemaVersion: Migration tracking
|
|
9
|
+
- NodeAudit: Change audit logging
|
|
10
|
+
- Architecture analysis tables (components, metrics, patterns, packages)
|
|
11
|
+
- Quality analysis tables (results, sessions)
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from sqlalchemy import (
|
|
15
|
+
Column,
|
|
16
|
+
DateTime,
|
|
17
|
+
Float,
|
|
18
|
+
ForeignKey,
|
|
19
|
+
Index,
|
|
20
|
+
Integer,
|
|
21
|
+
String,
|
|
22
|
+
Text,
|
|
23
|
+
UniqueConstraint,
|
|
24
|
+
func,
|
|
25
|
+
)
|
|
26
|
+
from sqlalchemy.dialects.postgresql import JSONB, TSVECTOR
|
|
27
|
+
|
|
28
|
+
from .db_init import Base
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Node(Base):
|
|
32
|
+
"""Code entity node in the graph."""
|
|
33
|
+
|
|
34
|
+
__tablename__ = "nodes"
|
|
35
|
+
|
|
36
|
+
id = Column(String(500), primary_key=True)
|
|
37
|
+
type = Column(String(50), nullable=False, index=True)
|
|
38
|
+
properties = Column(JSONB, nullable=True, default=dict)
|
|
39
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
40
|
+
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
41
|
+
content_hash = Column(String(64), nullable=True, index=True)
|
|
42
|
+
file_size = Column(Integer, nullable=True)
|
|
43
|
+
tenant_id = Column(String(100), nullable=True, index=True)
|
|
44
|
+
tsv = Column(TSVECTOR, nullable=True)
|
|
45
|
+
|
|
46
|
+
__table_args__ = (
|
|
47
|
+
Index("ix_nodes_type_created", "type", "created_at"),
|
|
48
|
+
Index("ix_nodes_tenant_type", "tenant_id", "type"),
|
|
49
|
+
Index("ix_nodes_tsv", "tsv", postgresql_using="gin"),
|
|
50
|
+
Index("ix_nodes_properties", "properties", postgresql_using="gin"),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Edge(Base):
|
|
55
|
+
"""Relationship edge between code entities."""
|
|
56
|
+
|
|
57
|
+
__tablename__ = "edges"
|
|
58
|
+
|
|
59
|
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
60
|
+
source = Column(String(500), ForeignKey("nodes.id", ondelete="CASCADE"), nullable=False)
|
|
61
|
+
target = Column(String(500), ForeignKey("nodes.id", ondelete="CASCADE"), nullable=False)
|
|
62
|
+
relationship = Column(String(50), nullable=False)
|
|
63
|
+
properties = Column(JSONB, nullable=True, default=dict)
|
|
64
|
+
weight = Column(Float, nullable=False, default=1.0)
|
|
65
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
66
|
+
tenant_id = Column(String(100), nullable=True)
|
|
67
|
+
|
|
68
|
+
__table_args__ = (
|
|
69
|
+
UniqueConstraint("source", "target", "relationship", name="uq_edges_source_target_rel"),
|
|
70
|
+
Index("ix_edges_source", "source"),
|
|
71
|
+
Index("ix_edges_target", "target"),
|
|
72
|
+
Index("ix_edges_relationship", "relationship"),
|
|
73
|
+
Index("ix_edges_source_rel", "source", "relationship"),
|
|
74
|
+
Index("ix_edges_target_rel", "target", "relationship"),
|
|
75
|
+
Index("ix_edges_weight", "relationship", "weight"),
|
|
76
|
+
Index("ix_edges_tenant", "tenant_id"),
|
|
77
|
+
Index("ix_edges_tenant_source", "tenant_id", "source"),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class Codebase(Base):
|
|
82
|
+
"""Repository/project being analyzed."""
|
|
83
|
+
|
|
84
|
+
__tablename__ = "codebases"
|
|
85
|
+
|
|
86
|
+
id = Column(String(100), primary_key=True)
|
|
87
|
+
name = Column(String(200), nullable=False)
|
|
88
|
+
description = Column(Text, nullable=True)
|
|
89
|
+
tenant_id = Column(String(100), nullable=True, index=True)
|
|
90
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
91
|
+
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class SchemaVersion(Base):
|
|
95
|
+
"""Tracks schema migration versions."""
|
|
96
|
+
|
|
97
|
+
__tablename__ = "schema_version"
|
|
98
|
+
|
|
99
|
+
version = Column(Integer, primary_key=True)
|
|
100
|
+
description = Column(Text, nullable=True)
|
|
101
|
+
applied_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class NodeAudit(Base):
|
|
105
|
+
"""Audit log for node operations."""
|
|
106
|
+
|
|
107
|
+
__tablename__ = "nodes_audit"
|
|
108
|
+
|
|
109
|
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
110
|
+
node_id = Column(String(500), nullable=True)
|
|
111
|
+
operation = Column(String(20), nullable=False)
|
|
112
|
+
timestamp = Column(DateTime(timezone=True), server_default=func.now())
|
|
113
|
+
tenant_id = Column(String(100), nullable=True)
|
|
114
|
+
|
|
115
|
+
__table_args__ = (
|
|
116
|
+
Index("ix_nodes_audit_node_id", "node_id"),
|
|
117
|
+
Index("ix_nodes_audit_tenant", "tenant_id"),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# Architecture Analysis Tables
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class ArchitectureComponent(Base):
|
|
125
|
+
"""Architecture component for dependency analysis."""
|
|
126
|
+
|
|
127
|
+
__tablename__ = "architecture_components"
|
|
128
|
+
|
|
129
|
+
id = Column(String(100), primary_key=True)
|
|
130
|
+
codebase_id = Column(
|
|
131
|
+
String(100), ForeignKey("codebases.id", ondelete="CASCADE"), nullable=False
|
|
132
|
+
)
|
|
133
|
+
name = Column(String(200), nullable=False)
|
|
134
|
+
files = Column(JSONB, nullable=False, default=list)
|
|
135
|
+
dependencies = Column(JSONB, nullable=False, default=list)
|
|
136
|
+
layer = Column(String(50), nullable=True)
|
|
137
|
+
tenant_id = Column(String(100), nullable=True)
|
|
138
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
139
|
+
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
140
|
+
|
|
141
|
+
__table_args__ = (
|
|
142
|
+
Index("ix_arch_components_codebase", "codebase_id"),
|
|
143
|
+
Index("ix_arch_components_layer", "layer"),
|
|
144
|
+
Index("ix_arch_components_tenant", "tenant_id"),
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class ArchitectureMetric(Base):
|
|
149
|
+
"""Architecture quality metrics (instability, abstractness, distance)."""
|
|
150
|
+
|
|
151
|
+
__tablename__ = "architecture_metrics"
|
|
152
|
+
|
|
153
|
+
codebase_id = Column(
|
|
154
|
+
String(100), ForeignKey("codebases.id", ondelete="CASCADE"), primary_key=True
|
|
155
|
+
)
|
|
156
|
+
instability = Column(Float, nullable=False)
|
|
157
|
+
abstractness = Column(Float, nullable=False)
|
|
158
|
+
distance = Column(Float, nullable=False)
|
|
159
|
+
tenant_id = Column(String(100), nullable=True, index=True)
|
|
160
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
161
|
+
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class DetectedPattern(Base):
|
|
165
|
+
"""Detected design patterns in codebase."""
|
|
166
|
+
|
|
167
|
+
__tablename__ = "detected_patterns"
|
|
168
|
+
|
|
169
|
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
170
|
+
codebase_id = Column(
|
|
171
|
+
String(100), ForeignKey("codebases.id", ondelete="CASCADE"), nullable=False
|
|
172
|
+
)
|
|
173
|
+
name = Column(String(100), nullable=False)
|
|
174
|
+
location = Column(String(500), nullable=False)
|
|
175
|
+
confidence = Column(Float, nullable=False)
|
|
176
|
+
tenant_id = Column(String(100), nullable=True)
|
|
177
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
178
|
+
|
|
179
|
+
__table_args__ = (
|
|
180
|
+
Index("ix_detected_patterns_codebase", "codebase_id"),
|
|
181
|
+
Index("ix_detected_patterns_name", "name"),
|
|
182
|
+
Index("ix_detected_patterns_tenant", "tenant_id"),
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class ExternalPackage(Base):
|
|
187
|
+
"""External package dependencies with vulnerability tracking."""
|
|
188
|
+
|
|
189
|
+
__tablename__ = "external_packages"
|
|
190
|
+
|
|
191
|
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
192
|
+
codebase_id = Column(
|
|
193
|
+
String(100), ForeignKey("codebases.id", ondelete="CASCADE"), nullable=False
|
|
194
|
+
)
|
|
195
|
+
name = Column(String(200), nullable=False)
|
|
196
|
+
current_version = Column(String(50), nullable=False)
|
|
197
|
+
latest_version = Column(String(50), nullable=True)
|
|
198
|
+
license = Column(String(100), nullable=True)
|
|
199
|
+
severity = Column(String(20), nullable=True)
|
|
200
|
+
tenant_id = Column(String(100), nullable=True)
|
|
201
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
202
|
+
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
203
|
+
|
|
204
|
+
__table_args__ = (
|
|
205
|
+
UniqueConstraint("codebase_id", "name", name="uq_external_packages_codebase_name"),
|
|
206
|
+
Index("ix_external_packages_codebase", "codebase_id"),
|
|
207
|
+
Index("ix_external_packages_severity", "severity"),
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
class LayerAssignment(Base):
|
|
212
|
+
"""Layer assignments for architecture analysis."""
|
|
213
|
+
|
|
214
|
+
__tablename__ = "layer_assignments"
|
|
215
|
+
|
|
216
|
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
217
|
+
codebase_id = Column(
|
|
218
|
+
String(100), ForeignKey("codebases.id", ondelete="CASCADE"), nullable=False
|
|
219
|
+
)
|
|
220
|
+
layer_name = Column(String(50), nullable=False)
|
|
221
|
+
component_ids = Column(JSONB, nullable=False, default=list)
|
|
222
|
+
tenant_id = Column(String(100), nullable=True)
|
|
223
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
224
|
+
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
|
225
|
+
|
|
226
|
+
__table_args__ = (
|
|
227
|
+
UniqueConstraint("codebase_id", "layer_name", name="uq_layer_assignments_codebase_layer"),
|
|
228
|
+
Index("ix_layer_assignments_codebase", "codebase_id"),
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class QualityResult(Base):
|
|
233
|
+
"""Quality analysis results."""
|
|
234
|
+
|
|
235
|
+
__tablename__ = "quality_results"
|
|
236
|
+
|
|
237
|
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
238
|
+
codebase_id = Column(
|
|
239
|
+
String(100), ForeignKey("codebases.id", ondelete="CASCADE"), nullable=False
|
|
240
|
+
)
|
|
241
|
+
overall_score = Column(Float, nullable=False)
|
|
242
|
+
issues_count = Column(Integer, nullable=False)
|
|
243
|
+
issues_data = Column(JSONB, nullable=True)
|
|
244
|
+
summary_data = Column(JSONB, nullable=True)
|
|
245
|
+
tenant_id = Column(String(100), nullable=True)
|
|
246
|
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
247
|
+
|
|
248
|
+
__table_args__ = (Index("ix_quality_results_codebase", "codebase_id"),)
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class AnalysisSession(Base):
|
|
252
|
+
"""Analysis session tracking."""
|
|
253
|
+
|
|
254
|
+
__tablename__ = "analysis_sessions"
|
|
255
|
+
|
|
256
|
+
id = Column(String(100), primary_key=True)
|
|
257
|
+
codebase_id = Column(
|
|
258
|
+
String(100), ForeignKey("codebases.id", ondelete="CASCADE"), nullable=False
|
|
259
|
+
)
|
|
260
|
+
analysis_type = Column(String(50), nullable=False)
|
|
261
|
+
status = Column(String(20), nullable=False, default="running")
|
|
262
|
+
started_at = Column(DateTime(timezone=True), server_default=func.now())
|
|
263
|
+
completed_at = Column(DateTime(timezone=True), nullable=True)
|
|
264
|
+
error_message = Column(Text, nullable=True)
|
|
265
|
+
result_data = Column(JSONB, nullable=True)
|
|
266
|
+
tenant_id = Column(String(100), nullable=True)
|
|
267
|
+
|
|
268
|
+
__table_args__ = (
|
|
269
|
+
Index("ix_analysis_sessions_codebase", "codebase_id"),
|
|
270
|
+
Index("ix_analysis_sessions_type", "analysis_type"),
|
|
271
|
+
Index("ix_analysis_sessions_status", "status"),
|
|
272
|
+
)
|