nat-engine 1__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.
- mannf/__init__.py +33 -0
- mannf/__main__.py +10 -0
- mannf/_version.py +8 -0
- mannf/agents/__init__.py +7 -0
- mannf/agents/analyzer_agent.py +9 -0
- mannf/agents/base.py +9 -0
- mannf/agents/bdi_agent.py +9 -0
- mannf/agents/belief_state.py +9 -0
- mannf/agents/coordinator_agent.py +9 -0
- mannf/agents/executor_agent.py +9 -0
- mannf/agents/monitor_agent.py +9 -0
- mannf/agents/oracle_agent.py +9 -0
- mannf/agents/planner_agent.py +9 -0
- mannf/agents/test_agent.py +9 -0
- mannf/anomaly/__init__.py +7 -0
- mannf/anomaly/enhanced_detector.py +9 -0
- mannf/cli.py +9 -0
- mannf/core/__init__.py +26 -0
- mannf/core/agents/__init__.py +52 -0
- mannf/core/agents/accessibility_scanner_agent.py +245 -0
- mannf/core/agents/analyzer_agent.py +224 -0
- mannf/core/agents/autonomous_loop_agent.py +1086 -0
- mannf/core/agents/autonomous_loop_models.py +62 -0
- mannf/core/agents/autonomous_run_differ.py +427 -0
- mannf/core/agents/base.py +128 -0
- mannf/core/agents/bdi_agent.py +330 -0
- mannf/core/agents/belief_state.py +202 -0
- mannf/core/agents/browser_coordinator_agent.py +224 -0
- mannf/core/agents/browser_executor_agent.py +410 -0
- mannf/core/agents/coordinator_agent.py +262 -0
- mannf/core/agents/executor_agent.py +222 -0
- mannf/core/agents/monitor_agent.py +188 -0
- mannf/core/agents/oracle_agent.py +150 -0
- mannf/core/agents/performance_testing_agent.py +279 -0
- mannf/core/agents/planner_agent.py +128 -0
- mannf/core/agents/test_agent.py +249 -0
- mannf/core/agents/visual_regression_agent.py +311 -0
- mannf/core/agents/web_crawler_agent.py +510 -0
- mannf/core/agents/worker_pool.py +366 -0
- mannf/core/anomaly/__init__.py +14 -0
- mannf/core/anomaly/enhanced_detector.py +541 -0
- mannf/core/browser/__init__.py +63 -0
- mannf/core/browser/accessibility_scanner.py +424 -0
- mannf/core/browser/discovery_model.py +178 -0
- mannf/core/browser/dom_snapshot.py +349 -0
- mannf/core/browser/ingestor_bridge.py +371 -0
- mannf/core/browser/performance_metrics.py +217 -0
- mannf/core/browser/reflection_analyzer.py +442 -0
- mannf/core/browser/scenario_generator.py +1100 -0
- mannf/core/browser/security_scenario_generator.py +695 -0
- mannf/core/browser/visual_comparer.py +159 -0
- mannf/core/diagnostics/__init__.py +28 -0
- mannf/core/diagnostics/failure_clusterer.py +211 -0
- mannf/core/diagnostics/flake_detector.py +233 -0
- mannf/core/diagnostics/root_cause_analyzer.py +273 -0
- mannf/core/distributed/__init__.py +16 -0
- mannf/core/distributed/endpoint.py +139 -0
- mannf/core/distributed/system_under_test.py +207 -0
- mannf/core/functional_orchestrator.py +428 -0
- mannf/core/messaging/__init__.py +11 -0
- mannf/core/messaging/bus.py +113 -0
- mannf/core/messaging/messages.py +89 -0
- mannf/core/nat_orchestrator.py +342 -0
- mannf/core/neural/__init__.py +183 -0
- mannf/core/orchestrator.py +272 -0
- mannf/core/prioritization/__init__.py +17 -0
- mannf/core/prioritization/adaptive_controller.py +509 -0
- mannf/core/prioritization/belief_prioritizer.py +231 -0
- mannf/core/prioritization/risk_scorer.py +430 -0
- mannf/core/reporting/__init__.py +12 -0
- mannf/core/reporting/unified_report.py +664 -0
- mannf/core/testing/__init__.py +17 -0
- mannf/core/testing/adaptive_controller.py +149 -0
- mannf/core/testing/models.py +179 -0
- mannf/core/validation/__init__.py +10 -0
- mannf/core/validation/self_validation_runner.py +180 -0
- mannf/dashboard/__init__.py +7 -0
- mannf/dashboard/app.py +9 -0
- mannf/dashboard/models.py +9 -0
- mannf/dashboard/static/index.html +2538 -0
- mannf/dashboard/telemetry.py +9 -0
- mannf/distributed/__init__.py +7 -0
- mannf/distributed/endpoint.py +9 -0
- mannf/distributed/system_under_test.py +9 -0
- mannf/healing/__init__.py +7 -0
- mannf/healing/graphql_schema_diff.py +9 -0
- mannf/healing/healer.py +9 -0
- mannf/healing/models.py +9 -0
- mannf/healing/schema_diff.py +9 -0
- mannf/integrations/__init__.py +7 -0
- mannf/integrations/auth.py +9 -0
- mannf/integrations/graphql_parser.py +9 -0
- mannf/integrations/graphql_sut.py +9 -0
- mannf/integrations/http_sut.py +9 -0
- mannf/integrations/openapi_parser.py +9 -0
- mannf/integrations/postman_parser.py +9 -0
- mannf/llm/__init__.py +7 -0
- mannf/llm/anthropic_provider.py +9 -0
- mannf/llm/base.py +9 -0
- mannf/llm/config.py +9 -0
- mannf/llm/factory.py +9 -0
- mannf/llm/openai_provider.py +9 -0
- mannf/llm/prompts.py +9 -0
- mannf/messaging/__init__.py +7 -0
- mannf/messaging/bus.py +9 -0
- mannf/messaging/messages.py +9 -0
- mannf/nat_orchestrator.py +9 -0
- mannf/neural/__init__.py +7 -0
- mannf/orchestrator.py +9 -0
- mannf/prioritization/__init__.py +7 -0
- mannf/prioritization/adaptive_controller.py +9 -0
- mannf/prioritization/belief_prioritizer.py +9 -0
- mannf/prioritization/risk_scorer.py +9 -0
- mannf/product/__init__.py +29 -0
- mannf/product/admin/__init__.py +3 -0
- mannf/product/admin/routes.py +514 -0
- mannf/product/auth/__init__.py +5 -0
- mannf/product/auth/saml.py +212 -0
- mannf/product/billing/__init__.py +5 -0
- mannf/product/billing/audit.py +160 -0
- mannf/product/billing/feature_gates.py +180 -0
- mannf/product/billing/metering.py +179 -0
- mannf/product/billing/notifications.py +181 -0
- mannf/product/billing/plans.py +133 -0
- mannf/product/billing/rate_limits.py +35 -0
- mannf/product/billing/stripe_billing.py +906 -0
- mannf/product/billing/tenant_auth.py +233 -0
- mannf/product/billing/tenant_manager.py +873 -0
- mannf/product/cli.py +3900 -0
- mannf/product/cli_admin.py +408 -0
- mannf/product/dashboard/__init__.py +61 -0
- mannf/product/dashboard/app.py +3567 -0
- mannf/product/dashboard/models.py +460 -0
- mannf/product/dashboard/static/index.html +6347 -0
- mannf/product/dashboard/static/manifest.json +25 -0
- mannf/product/dashboard/static/pwa-icon-192.png +0 -0
- mannf/product/dashboard/static/pwa-icon-512.png +0 -0
- mannf/product/dashboard/static/sw.js +64 -0
- mannf/product/dashboard/telemetry.py +547 -0
- mannf/product/database.py +145 -0
- mannf/product/demo.py +844 -0
- mannf/product/doctor.py +509 -0
- mannf/product/exporters/__init__.py +65 -0
- mannf/product/exporters/azuredevops_exporter.py +257 -0
- mannf/product/exporters/base.py +307 -0
- mannf/product/exporters/bugzilla_exporter.py +200 -0
- mannf/product/exporters/dedup.py +275 -0
- mannf/product/exporters/finding_adapter.py +216 -0
- mannf/product/exporters/github_exporter.py +197 -0
- mannf/product/exporters/gitlab_exporter.py +215 -0
- mannf/product/exporters/jira_exporter.py +180 -0
- mannf/product/exporters/linear_exporter.py +195 -0
- mannf/product/exporters/loader.py +233 -0
- mannf/product/exporters/pagerduty_exporter.py +363 -0
- mannf/product/exporters/sentry_exporter.py +322 -0
- mannf/product/exporters/servicenow_exporter.py +240 -0
- mannf/product/exporters/shortcut_exporter.py +231 -0
- mannf/product/exporters/webhook_exporter.py +383 -0
- mannf/product/formatters/__init__.py +18 -0
- mannf/product/formatters/allure_formatter.py +161 -0
- mannf/product/formatters/ctrf_formatter.py +149 -0
- mannf/product/healing/__init__.py +30 -0
- mannf/product/healing/graphql_schema_diff.py +152 -0
- mannf/product/healing/healer.py +141 -0
- mannf/product/healing/models.py +175 -0
- mannf/product/healing/schema_diff.py +251 -0
- mannf/product/ingestors/__init__.py +77 -0
- mannf/product/ingestors/base.py +256 -0
- mannf/product/ingestors/bgstm_ingestor.py +764 -0
- mannf/product/ingestors/curl_ingestor.py +1019 -0
- mannf/product/ingestors/cypress_ingestor.py +487 -0
- mannf/product/ingestors/gherkin_ingestor.py +967 -0
- mannf/product/ingestors/graphql_ingestor.py +845 -0
- mannf/product/ingestors/grpc_ingestor.py +591 -0
- mannf/product/ingestors/har_ingestor.py +976 -0
- mannf/product/ingestors/loader.py +284 -0
- mannf/product/ingestors/models.py +146 -0
- mannf/product/ingestors/openapi_ingestor.py +606 -0
- mannf/product/ingestors/playwright_ingestor.py +449 -0
- mannf/product/ingestors/postman_ingestor.py +631 -0
- mannf/product/ingestors/traffic_ingestor.py +679 -0
- mannf/product/ingestors/websocket_ingestor.py +526 -0
- mannf/product/integrations/__init__.py +21 -0
- mannf/product/integrations/auth.py +190 -0
- mannf/product/integrations/graphql_parser.py +436 -0
- mannf/product/integrations/graphql_sut.py +247 -0
- mannf/product/integrations/grpc_sut.py +469 -0
- mannf/product/integrations/http_sut.py +237 -0
- mannf/product/integrations/kafka_adapter.py +342 -0
- mannf/product/integrations/openapi_parser.py +513 -0
- mannf/product/integrations/postman_parser.py +467 -0
- mannf/product/integrations/webhook_receiver.py +344 -0
- mannf/product/integrations/websocket_sut.py +434 -0
- mannf/product/llm/__init__.py +25 -0
- mannf/product/llm/anthropic_provider.py +94 -0
- mannf/product/llm/base.py +267 -0
- mannf/product/llm/config.py +48 -0
- mannf/product/llm/factory.py +42 -0
- mannf/product/llm/openai_provider.py +93 -0
- mannf/product/llm/prompts.py +403 -0
- mannf/product/llm/root_cause_service.py +311 -0
- mannf/product/llm/test_plan_models.py +78 -0
- mannf/product/metrics.py +149 -0
- mannf/product/middleware/__init__.py +3 -0
- mannf/product/middleware/audit_middleware.py +112 -0
- mannf/product/middleware/tenant_isolation.py +114 -0
- mannf/product/models.py +347 -0
- mannf/product/notifications/__init__.py +24 -0
- mannf/product/notifications/dispatcher.py +411 -0
- mannf/product/onboarding.py +190 -0
- mannf/product/orchestration/__init__.py +39 -0
- mannf/product/orchestration/ingest_scan_orchestrator.py +339 -0
- mannf/product/orchestration/pipeline.py +401 -0
- mannf/product/orchestrator.py +987 -0
- mannf/product/orchestrator_models.py +269 -0
- mannf/product/regression/__init__.py +36 -0
- mannf/product/regression/differ.py +172 -0
- mannf/product/regression/masking.py +100 -0
- mannf/product/regression/models.py +232 -0
- mannf/product/regression/recorder.py +124 -0
- mannf/product/regression/replayer.py +168 -0
- mannf/product/reports/__init__.py +10 -0
- mannf/product/reports/pdf.py +132 -0
- mannf/product/scheduling/__init__.py +57 -0
- mannf/product/scheduling/cron_utils.py +251 -0
- mannf/product/scheduling/engine.py +473 -0
- mannf/product/scheduling/models.py +86 -0
- mannf/product/scheduling/queue.py +894 -0
- mannf/product/scheduling/store.py +235 -0
- mannf/product/security/__init__.py +21 -0
- mannf/product/security/belief_guided.py +143 -0
- mannf/product/security/checks/__init__.py +55 -0
- mannf/product/security/checks/base.py +69 -0
- mannf/product/security/checks/bfla.py +77 -0
- mannf/product/security/checks/bola.py +77 -0
- mannf/product/security/checks/bopla.py +80 -0
- mannf/product/security/checks/broken_auth.py +86 -0
- mannf/product/security/checks/graphql_security.py +299 -0
- mannf/product/security/checks/inventory.py +70 -0
- mannf/product/security/checks/misconfig.py +158 -0
- mannf/product/security/checks/resource_consumption.py +70 -0
- mannf/product/security/checks/sensitive_flows.py +80 -0
- mannf/product/security/checks/ssrf.py +101 -0
- mannf/product/security/checks/unsafe_consumption.py +120 -0
- mannf/product/security/models.py +92 -0
- mannf/product/security/plugin_loader.py +182 -0
- mannf/product/security/reporter.py +92 -0
- mannf/product/security/scanner.py +183 -0
- mannf/product/server.py +6220 -0
- mannf/product/setup_wizard.py +873 -0
- mannf/product/status.py +404 -0
- mannf/product/storage/__init__.py +10 -0
- mannf/product/storage/artifact_store.py +343 -0
- mannf/product/telemetry.py +300 -0
- mannf/product/uninstall.py +169 -0
- mannf/product/upgrade.py +139 -0
- mannf/product/weights/__init__.py +13 -0
- mannf/product/weights/blob_store.py +299 -0
- mannf/product/weights/factory.py +42 -0
- mannf/product/weights/registry.py +159 -0
- mannf/product/weights/store.py +210 -0
- mannf/regression/__init__.py +7 -0
- mannf/regression/differ.py +9 -0
- mannf/regression/masking.py +9 -0
- mannf/regression/models.py +9 -0
- mannf/regression/recorder.py +9 -0
- mannf/regression/replayer.py +9 -0
- mannf/security/__init__.py +7 -0
- mannf/security/belief_guided.py +9 -0
- mannf/security/checks/__init__.py +7 -0
- mannf/security/checks/base.py +9 -0
- mannf/security/checks/bfla.py +9 -0
- mannf/security/checks/bola.py +9 -0
- mannf/security/checks/bopla.py +9 -0
- mannf/security/checks/broken_auth.py +9 -0
- mannf/security/checks/graphql_security.py +9 -0
- mannf/security/checks/inventory.py +9 -0
- mannf/security/checks/misconfig.py +9 -0
- mannf/security/checks/resource_consumption.py +9 -0
- mannf/security/checks/sensitive_flows.py +9 -0
- mannf/security/checks/ssrf.py +9 -0
- mannf/security/checks/unsafe_consumption.py +9 -0
- mannf/security/models.py +9 -0
- mannf/security/reporter.py +9 -0
- mannf/security/scanner.py +9 -0
- mannf/server.py +9 -0
- mannf/testing/__init__.py +7 -0
- mannf/testing/adaptive_controller.py +9 -0
- mannf/testing/models.py +9 -0
- mannf/weights/__init__.py +7 -0
- mannf/weights/registry.py +9 -0
- mannf/weights/store.py +9 -0
- nat_engine-1.dist-info/METADATA +555 -0
- nat_engine-1.dist-info/RECORD +299 -0
- nat_engine-1.dist-info/WHEEL +5 -0
- nat_engine-1.dist-info/entry_points.txt +4 -0
- nat_engine-1.dist-info/licenses/LICENSE +651 -0
- nat_engine-1.dist-info/licenses/NOTICE +178 -0
- nat_engine-1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# Copyright (C) 2026 Brad Guider
|
|
2
|
+
# This file is part of NAT (Neural Agent Testing Framework).
|
|
3
|
+
# Licensed under the AGPL-3.0. See LICENSE for details.
|
|
4
|
+
# Commercial licensing available — see COMMERCIAL_LICENSE.md.
|
|
5
|
+
|
|
6
|
+
"""Pydantic models for the NAT web dashboard data layer."""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from typing import Any, Dict, List, Optional
|
|
11
|
+
|
|
12
|
+
from pydantic import BaseModel, Field
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DashboardSummary(BaseModel):
|
|
16
|
+
"""Overall system statistics shown in the overview bar."""
|
|
17
|
+
|
|
18
|
+
total_scans: int = 0
|
|
19
|
+
endpoints_discovered: int = 0
|
|
20
|
+
anomalies_found: int = 0
|
|
21
|
+
avg_risk_score: float = 0.0
|
|
22
|
+
total_tests_run: int = 0
|
|
23
|
+
pass_rate: float = 0.0
|
|
24
|
+
active_anomalies: int = 0
|
|
25
|
+
last_scan_at: Optional[str] = None
|
|
26
|
+
health_score: float = 1.0
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class EndpointRiskCard(BaseModel):
|
|
30
|
+
"""Per-endpoint card data for the risk heatmap."""
|
|
31
|
+
|
|
32
|
+
endpoint: str
|
|
33
|
+
risk_score: float
|
|
34
|
+
fault_rate: float
|
|
35
|
+
belief_signal: float
|
|
36
|
+
latency_signal: float
|
|
37
|
+
diversity_signal: float
|
|
38
|
+
trend: str
|
|
39
|
+
run_count: int
|
|
40
|
+
fault_count: int
|
|
41
|
+
anomaly_count: int = 0
|
|
42
|
+
last_test_result: Optional[str] = None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class BeliefStateSnapshot(BaseModel):
|
|
46
|
+
"""Agent belief state data formatted for visualization."""
|
|
47
|
+
|
|
48
|
+
agent_id: str
|
|
49
|
+
agent_role: str
|
|
50
|
+
beliefs: Dict[str, Any] = Field(default_factory=dict)
|
|
51
|
+
active: bool = True
|
|
52
|
+
current_task: Optional[str] = None
|
|
53
|
+
endpoints_assigned: List[str] = Field(default_factory=list)
|
|
54
|
+
confidence: float = 0.5
|
|
55
|
+
# Telemetry-enriched fields (populated by the real-time broadcast path)
|
|
56
|
+
confidence_per_service: Dict[str, float] = Field(default_factory=dict)
|
|
57
|
+
intentions: List[Dict[str, Any]] = Field(default_factory=list)
|
|
58
|
+
desires: Dict[str, float] = Field(default_factory=dict)
|
|
59
|
+
entropy: float = 0.0
|
|
60
|
+
timestamp: Optional[str] = None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class AnomalyTimelineEntry(BaseModel):
|
|
64
|
+
"""An anomaly event for the timeline display."""
|
|
65
|
+
|
|
66
|
+
endpoint: str
|
|
67
|
+
anomaly_type: str
|
|
68
|
+
severity: str
|
|
69
|
+
score: float
|
|
70
|
+
description: str
|
|
71
|
+
detected_at: str
|
|
72
|
+
scan_id: Optional[str] = None
|
|
73
|
+
details: Dict[str, Any] = Field(default_factory=dict)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# ---------------------------------------------------------------------------
|
|
77
|
+
# Functional Testing Results models
|
|
78
|
+
# ---------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class VisualDiffEntry(BaseModel):
|
|
82
|
+
"""A single visual regression comparison result."""
|
|
83
|
+
|
|
84
|
+
task_id: str
|
|
85
|
+
baseline_url: Optional[str] = None
|
|
86
|
+
current_url: Optional[str] = None
|
|
87
|
+
diff_url: Optional[str] = None
|
|
88
|
+
diff_percent: float = 0.0
|
|
89
|
+
passed: bool = True
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class A11yViolationSummary(BaseModel):
|
|
93
|
+
"""Aggregated accessibility violation counts by severity."""
|
|
94
|
+
|
|
95
|
+
critical: int = 0
|
|
96
|
+
serious: int = 0
|
|
97
|
+
moderate: int = 0
|
|
98
|
+
minor: int = 0
|
|
99
|
+
total: int = 0
|
|
100
|
+
sample_violations: List[Dict[str, Any]] = Field(default_factory=list)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class PerfMetrics(BaseModel):
|
|
104
|
+
"""Performance scorecard (Core Web Vitals + TTFB)."""
|
|
105
|
+
|
|
106
|
+
lcp_ms: Optional[float] = None # Largest Contentful Paint
|
|
107
|
+
fid_ms: Optional[float] = None # First Input Delay
|
|
108
|
+
cls: Optional[float] = None # Cumulative Layout Shift
|
|
109
|
+
ttfb_ms: Optional[float] = None # Time to First Byte
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class FunctionalTestItem(BaseModel):
|
|
113
|
+
"""Per-task outcome row in the functional testing results."""
|
|
114
|
+
|
|
115
|
+
task_id: str
|
|
116
|
+
task_name: str
|
|
117
|
+
passed: bool
|
|
118
|
+
duration_ms: Optional[float] = None
|
|
119
|
+
error: Optional[str] = None
|
|
120
|
+
artifact_url: Optional[str] = None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class FunctionalTestResult(BaseModel):
|
|
124
|
+
"""Aggregated functional testing results for the dashboard."""
|
|
125
|
+
|
|
126
|
+
run_id: Optional[str] = None
|
|
127
|
+
started_at: Optional[str] = None
|
|
128
|
+
completed_at: Optional[str] = None
|
|
129
|
+
total: int = 0
|
|
130
|
+
passed: int = 0
|
|
131
|
+
failed: int = 0
|
|
132
|
+
pass_rate: float = 0.0
|
|
133
|
+
items: List[FunctionalTestItem] = Field(default_factory=list)
|
|
134
|
+
visual_diffs: List[VisualDiffEntry] = Field(default_factory=list)
|
|
135
|
+
a11y: Optional[A11yViolationSummary] = None
|
|
136
|
+
perf: Optional[PerfMetrics] = None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# ---------------------------------------------------------------------------
|
|
140
|
+
# Usage & Billing models
|
|
141
|
+
# ---------------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class InvoiceEntry(BaseModel):
|
|
145
|
+
"""A single invoice row for the billing tab."""
|
|
146
|
+
|
|
147
|
+
invoice_id: str
|
|
148
|
+
date: str
|
|
149
|
+
amount_cents: int
|
|
150
|
+
currency: str = "usd"
|
|
151
|
+
status: str # "paid", "open", "void", etc.
|
|
152
|
+
pdf_url: Optional[str] = None
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class UsageSummary(BaseModel):
|
|
156
|
+
"""Usage gauge data for the billing tab."""
|
|
157
|
+
|
|
158
|
+
plan_name: str = "Free"
|
|
159
|
+
plan_tier: str = "free"
|
|
160
|
+
functional_used: int = 0
|
|
161
|
+
functional_quota: int = 0
|
|
162
|
+
security_used: int = 0
|
|
163
|
+
security_quota: int = 0
|
|
164
|
+
functional_percent: float = 0.0
|
|
165
|
+
security_percent: float = 0.0
|
|
166
|
+
approaching_limit: bool = False
|
|
167
|
+
quota_reset_date: Optional[str] = None
|
|
168
|
+
stripe_portal_url: Optional[str] = None
|
|
169
|
+
invoices: List[InvoiceEntry] = Field(default_factory=list)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
# ---------------------------------------------------------------------------
|
|
173
|
+
# Onboarding / Getting Started models
|
|
174
|
+
# ---------------------------------------------------------------------------
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class OnboardingStep(BaseModel):
|
|
178
|
+
"""A single step in the onboarding checklist."""
|
|
179
|
+
|
|
180
|
+
step: int
|
|
181
|
+
title: str
|
|
182
|
+
description: str
|
|
183
|
+
completed: bool = False
|
|
184
|
+
action_label: Optional[str] = None
|
|
185
|
+
action_url: Optional[str] = None
|
|
186
|
+
code_snippet: Optional[str] = None
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class OnboardingStatus(BaseModel):
|
|
190
|
+
"""Onboarding checklist completion state."""
|
|
191
|
+
|
|
192
|
+
steps: List[OnboardingStep] = Field(default_factory=list)
|
|
193
|
+
completed_count: int = 0
|
|
194
|
+
total_count: int = 0
|
|
195
|
+
api_key_masked: Optional[str] = None
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
# ---------------------------------------------------------------------------
|
|
199
|
+
# Scenario Suggestion / Discovery models (Phase 3)
|
|
200
|
+
# ---------------------------------------------------------------------------
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class DiscoveryRequest(BaseModel):
|
|
204
|
+
"""Request body for POST /api/v1/discover."""
|
|
205
|
+
|
|
206
|
+
url: str
|
|
207
|
+
max_pages: int = 50
|
|
208
|
+
max_depth: int = 5
|
|
209
|
+
include_negative: bool = True
|
|
210
|
+
include_boundary: bool = True
|
|
211
|
+
# Optional LLM configuration for AI-enhanced scenario generation
|
|
212
|
+
llm_provider: Optional[str] = None # e.g. "openai" or "anthropic"
|
|
213
|
+
llm_api_key: Optional[str] = None
|
|
214
|
+
llm_model: Optional[str] = None
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
class AutonomousRequest(BaseModel):
|
|
218
|
+
"""Request body for POST /api/v1/autonomous/start."""
|
|
219
|
+
|
|
220
|
+
url: str
|
|
221
|
+
strategy: str = "all" # "all", "high_risk", "new_changed", "belief_targeted"
|
|
222
|
+
max_iterations: int = 5
|
|
223
|
+
max_duration_s: float = 600.0
|
|
224
|
+
max_pages: int = 50
|
|
225
|
+
max_depth: int = 5
|
|
226
|
+
headless: bool = True
|
|
227
|
+
risk_threshold: float = 0.6
|
|
228
|
+
llm_provider: Optional[str] = None
|
|
229
|
+
llm_api_key: Optional[str] = None
|
|
230
|
+
llm_model: Optional[str] = None
|
|
231
|
+
# Deploy / commit attribution (Phase 6.3)
|
|
232
|
+
build_id: Optional[str] = None
|
|
233
|
+
commit_sha: Optional[str] = None
|
|
234
|
+
deploy_tag: Optional[str] = None
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
class DiscoveryScenario(BaseModel):
|
|
238
|
+
"""A single suggested functional test scenario."""
|
|
239
|
+
|
|
240
|
+
scenario_id: str
|
|
241
|
+
url: str
|
|
242
|
+
steps: List[Dict[str, Any]] = Field(default_factory=list)
|
|
243
|
+
metadata: Dict[str, Any] = Field(default_factory=dict)
|
|
244
|
+
selected: bool = True
|
|
245
|
+
confidence: float = 0.5
|
|
246
|
+
risk_score: float = 0.5
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class DiscoveryResult(BaseModel):
|
|
250
|
+
"""In-memory record for a single discovery crawl + scenario generation run."""
|
|
251
|
+
|
|
252
|
+
discovery_id: str
|
|
253
|
+
status: str # "running", "complete", "failed"
|
|
254
|
+
base_url: str
|
|
255
|
+
scenarios: List[DiscoveryScenario] = Field(default_factory=list)
|
|
256
|
+
stats: Dict[str, int] = Field(default_factory=dict)
|
|
257
|
+
created_at: str
|
|
258
|
+
error: Optional[str] = None
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
# ---------------------------------------------------------------------------
|
|
262
|
+
# Bug Filing / Triage models (Phase 6.4)
|
|
263
|
+
# ---------------------------------------------------------------------------
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class BugFilingConfig(BaseModel):
|
|
267
|
+
"""Configuration for the auto-bug-filing pipeline.
|
|
268
|
+
|
|
269
|
+
Controls *which* failures get filed, *where* they go, and whether they
|
|
270
|
+
need manual approval before a ticket is created.
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
enabled: bool = False
|
|
274
|
+
"""Master switch — no tickets are created when ``False``."""
|
|
275
|
+
|
|
276
|
+
target_system: str = "github"
|
|
277
|
+
"""Ticket destination: ``"github"``, ``"jira"``, or ``"webhook"``."""
|
|
278
|
+
|
|
279
|
+
exporter_config: Dict[str, Any] = Field(default_factory=dict)
|
|
280
|
+
"""System-specific config passed directly to the chosen exporter plugin."""
|
|
281
|
+
|
|
282
|
+
severity_threshold: str = "high"
|
|
283
|
+
"""Minimum failure severity to file (``"critical"``, ``"high"``, ``"medium"``, ``"low"``)."""
|
|
284
|
+
|
|
285
|
+
auto_file: bool = True
|
|
286
|
+
"""When ``True``, tickets are created automatically.
|
|
287
|
+
When ``False``, failures land in the pending-approval queue."""
|
|
288
|
+
|
|
289
|
+
deduplicate: bool = True
|
|
290
|
+
"""When ``True``, the pipeline checks for an existing open ticket with the
|
|
291
|
+
same fingerprint before creating a new one."""
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class FiledBugEntry(BaseModel):
|
|
295
|
+
"""A successfully auto-filed bug ticket."""
|
|
296
|
+
|
|
297
|
+
bug_id: str
|
|
298
|
+
"""Internal UUID for this filing record."""
|
|
299
|
+
|
|
300
|
+
run_id: str
|
|
301
|
+
"""Autonomous run that produced the failure."""
|
|
302
|
+
|
|
303
|
+
fingerprint: str
|
|
304
|
+
"""Deterministic sha256 fingerprint of the failure."""
|
|
305
|
+
|
|
306
|
+
failure: Dict[str, Any] = Field(default_factory=dict)
|
|
307
|
+
"""The original failure dict from ``AutonomousRunReport.unique_failures``."""
|
|
308
|
+
|
|
309
|
+
target_system: str
|
|
310
|
+
"""Exporter used: ``"github"``, ``"jira"``, etc."""
|
|
311
|
+
|
|
312
|
+
external_id: Optional[str] = None
|
|
313
|
+
"""Ticket ID in the external system (e.g. ``"NAT-42"`` or ``"99"``)."""
|
|
314
|
+
|
|
315
|
+
external_url: Optional[str] = None
|
|
316
|
+
"""Direct link to the ticket in the external system."""
|
|
317
|
+
|
|
318
|
+
severity: str = "low"
|
|
319
|
+
filed_at: str = ""
|
|
320
|
+
was_duplicate: bool = False
|
|
321
|
+
"""``True`` when this was a known duplicate — a comment was added instead of a new ticket."""
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
class PendingBugEntry(BaseModel):
|
|
325
|
+
"""A failure awaiting manual approval before a ticket is created."""
|
|
326
|
+
|
|
327
|
+
bug_id: str
|
|
328
|
+
"""Internal UUID for this pending record."""
|
|
329
|
+
|
|
330
|
+
run_id: str
|
|
331
|
+
"""Autonomous run that produced the failure."""
|
|
332
|
+
|
|
333
|
+
fingerprint: str
|
|
334
|
+
"""Deterministic sha256 fingerprint of the failure."""
|
|
335
|
+
|
|
336
|
+
failure: Dict[str, Any] = Field(default_factory=dict)
|
|
337
|
+
"""The original failure dict."""
|
|
338
|
+
|
|
339
|
+
severity: str = "low"
|
|
340
|
+
queued_at: str = ""
|
|
341
|
+
status: str = "pending"
|
|
342
|
+
"""Lifecycle state: ``"pending"``, ``"approved"``, ``"dismissed"``."""
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
# ---------------------------------------------------------------------------
|
|
346
|
+
# ML/LLM Diagnostics models (Phase 6.5)
|
|
347
|
+
# ---------------------------------------------------------------------------
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
class BeliefTrend(BaseModel):
|
|
351
|
+
"""Time-series entry for a single page's fault_likelihood over time."""
|
|
352
|
+
|
|
353
|
+
run_id: str
|
|
354
|
+
iteration: int
|
|
355
|
+
page_key: str
|
|
356
|
+
fault_likelihood: float
|
|
357
|
+
timestamp: str
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
class FlakinessSummary(BaseModel):
|
|
361
|
+
"""Flakiness statistics for a single page+scenario pair."""
|
|
362
|
+
|
|
363
|
+
page_key: str
|
|
364
|
+
scenario_id: str
|
|
365
|
+
is_flaky: bool
|
|
366
|
+
flake_rate: float
|
|
367
|
+
total_runs: int
|
|
368
|
+
pass_count: int
|
|
369
|
+
fail_count: int
|
|
370
|
+
alternations: int
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
class FailureCluster(BaseModel):
|
|
374
|
+
"""A cluster of failures sharing a similar error signature."""
|
|
375
|
+
|
|
376
|
+
cluster_id: str
|
|
377
|
+
label: str
|
|
378
|
+
representative_error: str
|
|
379
|
+
pages: List[str] = Field(default_factory=list)
|
|
380
|
+
size: int
|
|
381
|
+
failures: List[Dict[str, Any]] = Field(default_factory=list)
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
class RootCauseSuggestion(BaseModel):
|
|
385
|
+
"""LLM-generated root cause suggestion for a failure."""
|
|
386
|
+
|
|
387
|
+
task_id: str = ""
|
|
388
|
+
url: str = ""
|
|
389
|
+
page: str = ""
|
|
390
|
+
likely_cause: str
|
|
391
|
+
suggested_fix: str
|
|
392
|
+
confidence: float
|
|
393
|
+
files_to_check: List[str] = Field(default_factory=list)
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
class PredictiveRiskScore(BaseModel):
|
|
397
|
+
"""Predicted failure probability for a page in the next run."""
|
|
398
|
+
|
|
399
|
+
page_key: str
|
|
400
|
+
predicted_failure_probability: float
|
|
401
|
+
belief_momentum: float
|
|
402
|
+
recent_failure_density: float
|
|
403
|
+
confidence: float
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
# ---------------------------------------------------------------------------
|
|
407
|
+
# Phase 7.4 — Confidence Calibration & Self-Validation models
|
|
408
|
+
# ---------------------------------------------------------------------------
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
class DismissedFinding(BaseModel):
|
|
412
|
+
"""A finding dismissed by the user as a false positive."""
|
|
413
|
+
|
|
414
|
+
finding_id: str
|
|
415
|
+
"""Unique identifier of the dismissed finding (from ``unique_failures`` or ``browser_security_findings``)."""
|
|
416
|
+
|
|
417
|
+
endpoint: str = ""
|
|
418
|
+
"""Endpoint path/key the finding was associated with."""
|
|
419
|
+
|
|
420
|
+
dismissed_by: str = "user"
|
|
421
|
+
"""Who dismissed the finding (user identifier or ``"user"`` if anonymous)."""
|
|
422
|
+
|
|
423
|
+
dismissed_at: str = ""
|
|
424
|
+
"""ISO-8601 timestamp of the dismissal."""
|
|
425
|
+
|
|
426
|
+
run_id: str = ""
|
|
427
|
+
"""Autonomous run that produced the finding."""
|
|
428
|
+
|
|
429
|
+
reason: str = ""
|
|
430
|
+
"""Optional free-text reason supplied by the user."""
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
class CalibrationBucket(BaseModel):
|
|
434
|
+
"""A single bucket in the predicted-vs-actual reliability curve.
|
|
435
|
+
|
|
436
|
+
The bucket covers predictions in ``[bucket_low, bucket_high)``.
|
|
437
|
+
"""
|
|
438
|
+
|
|
439
|
+
bucket_low: float
|
|
440
|
+
bucket_high: float
|
|
441
|
+
predicted_count: int
|
|
442
|
+
"""Number of predictions falling in this bucket."""
|
|
443
|
+
actual_failure_rate: Optional[float] = None
|
|
444
|
+
"""Observed fraction of failures among the predictions in this bucket.
|
|
445
|
+
``None`` when no actual outcomes are available (sparse data)."""
|
|
446
|
+
mean_predicted: Optional[float] = None
|
|
447
|
+
"""Mean predicted failure probability within this bucket."""
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
class CalibrationReport(BaseModel):
|
|
451
|
+
"""Predicted-vs-actual reliability curve for the calibration dashboard view."""
|
|
452
|
+
|
|
453
|
+
buckets: List[CalibrationBucket] = Field(default_factory=list)
|
|
454
|
+
total_predictions: int = 0
|
|
455
|
+
total_with_outcomes: int = 0
|
|
456
|
+
brier_score: Optional[float] = None
|
|
457
|
+
"""Mean squared error between predicted probabilities and actual outcomes.
|
|
458
|
+
Lower is better (0 = perfect). ``None`` when no actual outcomes are available."""
|
|
459
|
+
generated_at: str = ""
|
|
460
|
+
|