truthound-dashboard 1.4.4__py3-none-any.whl → 1.5.0__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.
- truthound_dashboard/api/alerts.py +75 -86
- truthound_dashboard/api/anomaly.py +7 -13
- truthound_dashboard/api/cross_alerts.py +38 -52
- truthound_dashboard/api/drift.py +49 -59
- truthound_dashboard/api/drift_monitor.py +234 -79
- truthound_dashboard/api/enterprise_sampling.py +498 -0
- truthound_dashboard/api/history.py +57 -5
- truthound_dashboard/api/lineage.py +3 -48
- truthound_dashboard/api/maintenance.py +104 -49
- truthound_dashboard/api/mask.py +1 -2
- truthound_dashboard/api/middleware.py +2 -1
- truthound_dashboard/api/model_monitoring.py +435 -311
- truthound_dashboard/api/notifications.py +227 -191
- truthound_dashboard/api/notifications_advanced.py +21 -20
- truthound_dashboard/api/observability.py +586 -0
- truthound_dashboard/api/plugins.py +2 -433
- truthound_dashboard/api/profile.py +199 -37
- truthound_dashboard/api/quality_reporter.py +701 -0
- truthound_dashboard/api/reports.py +7 -16
- truthound_dashboard/api/router.py +66 -0
- truthound_dashboard/api/rule_suggestions.py +5 -5
- truthound_dashboard/api/scan.py +17 -19
- truthound_dashboard/api/schedules.py +85 -50
- truthound_dashboard/api/schema_evolution.py +6 -6
- truthound_dashboard/api/schema_watcher.py +667 -0
- truthound_dashboard/api/sources.py +98 -27
- truthound_dashboard/api/tiering.py +1323 -0
- truthound_dashboard/api/triggers.py +14 -11
- truthound_dashboard/api/validations.py +12 -11
- truthound_dashboard/api/versioning.py +1 -6
- truthound_dashboard/core/__init__.py +129 -3
- truthound_dashboard/core/actions/__init__.py +62 -0
- truthound_dashboard/core/actions/custom.py +426 -0
- truthound_dashboard/core/actions/notifications.py +910 -0
- truthound_dashboard/core/actions/storage.py +472 -0
- truthound_dashboard/core/actions/webhook.py +281 -0
- truthound_dashboard/core/anomaly.py +262 -67
- truthound_dashboard/core/anomaly_explainer.py +4 -3
- truthound_dashboard/core/backends/__init__.py +67 -0
- truthound_dashboard/core/backends/base.py +299 -0
- truthound_dashboard/core/backends/errors.py +191 -0
- truthound_dashboard/core/backends/factory.py +423 -0
- truthound_dashboard/core/backends/mock_backend.py +451 -0
- truthound_dashboard/core/backends/truthound_backend.py +718 -0
- truthound_dashboard/core/checkpoint/__init__.py +87 -0
- truthound_dashboard/core/checkpoint/adapters.py +814 -0
- truthound_dashboard/core/checkpoint/checkpoint.py +491 -0
- truthound_dashboard/core/checkpoint/runner.py +270 -0
- truthound_dashboard/core/connections.py +437 -10
- truthound_dashboard/core/converters/__init__.py +14 -0
- truthound_dashboard/core/converters/truthound.py +620 -0
- truthound_dashboard/core/cross_alerts.py +540 -320
- truthound_dashboard/core/datasource_factory.py +1672 -0
- truthound_dashboard/core/drift_monitor.py +216 -20
- truthound_dashboard/core/enterprise_sampling.py +1291 -0
- truthound_dashboard/core/interfaces/__init__.py +225 -0
- truthound_dashboard/core/interfaces/actions.py +652 -0
- truthound_dashboard/core/interfaces/base.py +247 -0
- truthound_dashboard/core/interfaces/checkpoint.py +676 -0
- truthound_dashboard/core/interfaces/protocols.py +664 -0
- truthound_dashboard/core/interfaces/reporters.py +650 -0
- truthound_dashboard/core/interfaces/routing.py +646 -0
- truthound_dashboard/core/interfaces/triggers.py +619 -0
- truthound_dashboard/core/lineage.py +407 -71
- truthound_dashboard/core/model_monitoring.py +431 -3
- truthound_dashboard/core/notifications/base.py +4 -0
- truthound_dashboard/core/notifications/channels.py +501 -1203
- truthound_dashboard/core/notifications/deduplication/__init__.py +81 -115
- truthound_dashboard/core/notifications/deduplication/service.py +131 -348
- truthound_dashboard/core/notifications/dispatcher.py +202 -11
- truthound_dashboard/core/notifications/escalation/__init__.py +119 -106
- truthound_dashboard/core/notifications/escalation/engine.py +168 -358
- truthound_dashboard/core/notifications/routing/__init__.py +88 -128
- truthound_dashboard/core/notifications/routing/engine.py +90 -317
- truthound_dashboard/core/notifications/stats_aggregator.py +246 -1
- truthound_dashboard/core/notifications/throttling/__init__.py +67 -50
- truthound_dashboard/core/notifications/throttling/builder.py +117 -255
- truthound_dashboard/core/notifications/truthound_adapter.py +842 -0
- truthound_dashboard/core/phase5/collaboration.py +1 -1
- truthound_dashboard/core/plugins/lifecycle/__init__.py +0 -13
- truthound_dashboard/core/quality_reporter.py +1359 -0
- truthound_dashboard/core/report_history.py +0 -6
- truthound_dashboard/core/reporters/__init__.py +175 -14
- truthound_dashboard/core/reporters/adapters.py +943 -0
- truthound_dashboard/core/reporters/base.py +0 -3
- truthound_dashboard/core/reporters/builtin/__init__.py +18 -0
- truthound_dashboard/core/reporters/builtin/csv_reporter.py +111 -0
- truthound_dashboard/core/reporters/builtin/html_reporter.py +270 -0
- truthound_dashboard/core/reporters/builtin/json_reporter.py +127 -0
- truthound_dashboard/core/reporters/compat.py +266 -0
- truthound_dashboard/core/reporters/csv_reporter.py +2 -35
- truthound_dashboard/core/reporters/factory.py +526 -0
- truthound_dashboard/core/reporters/interfaces.py +745 -0
- truthound_dashboard/core/reporters/registry.py +1 -10
- truthound_dashboard/core/scheduler.py +165 -0
- truthound_dashboard/core/schema_evolution.py +3 -3
- truthound_dashboard/core/schema_watcher.py +1528 -0
- truthound_dashboard/core/services.py +595 -76
- truthound_dashboard/core/store_manager.py +810 -0
- truthound_dashboard/core/streaming_anomaly.py +169 -4
- truthound_dashboard/core/tiering.py +1309 -0
- truthound_dashboard/core/triggers/evaluators.py +178 -8
- truthound_dashboard/core/truthound_adapter.py +2620 -197
- truthound_dashboard/core/unified_alerts.py +23 -20
- truthound_dashboard/db/__init__.py +8 -0
- truthound_dashboard/db/database.py +8 -2
- truthound_dashboard/db/models.py +944 -25
- truthound_dashboard/db/repository.py +2 -0
- truthound_dashboard/main.py +11 -0
- truthound_dashboard/schemas/__init__.py +177 -16
- truthound_dashboard/schemas/base.py +44 -23
- truthound_dashboard/schemas/collaboration.py +19 -6
- truthound_dashboard/schemas/cross_alerts.py +19 -3
- truthound_dashboard/schemas/drift.py +61 -55
- truthound_dashboard/schemas/drift_monitor.py +67 -23
- truthound_dashboard/schemas/enterprise_sampling.py +653 -0
- truthound_dashboard/schemas/lineage.py +0 -33
- truthound_dashboard/schemas/mask.py +10 -8
- truthound_dashboard/schemas/model_monitoring.py +89 -10
- truthound_dashboard/schemas/notifications_advanced.py +13 -0
- truthound_dashboard/schemas/observability.py +453 -0
- truthound_dashboard/schemas/plugins.py +0 -280
- truthound_dashboard/schemas/profile.py +154 -247
- truthound_dashboard/schemas/quality_reporter.py +403 -0
- truthound_dashboard/schemas/reports.py +2 -2
- truthound_dashboard/schemas/rule_suggestion.py +8 -1
- truthound_dashboard/schemas/scan.py +4 -24
- truthound_dashboard/schemas/schedule.py +11 -3
- truthound_dashboard/schemas/schema_watcher.py +727 -0
- truthound_dashboard/schemas/source.py +17 -2
- truthound_dashboard/schemas/tiering.py +822 -0
- truthound_dashboard/schemas/triggers.py +16 -0
- truthound_dashboard/schemas/unified_alerts.py +7 -0
- truthound_dashboard/schemas/validation.py +0 -13
- truthound_dashboard/schemas/validators/base.py +41 -21
- truthound_dashboard/schemas/validators/business_rule_validators.py +244 -0
- truthound_dashboard/schemas/validators/localization_validators.py +273 -0
- truthound_dashboard/schemas/validators/ml_feature_validators.py +308 -0
- truthound_dashboard/schemas/validators/profiling_validators.py +275 -0
- truthound_dashboard/schemas/validators/referential_validators.py +312 -0
- truthound_dashboard/schemas/validators/registry.py +93 -8
- truthound_dashboard/schemas/validators/timeseries_validators.py +389 -0
- truthound_dashboard/schemas/versioning.py +1 -6
- truthound_dashboard/static/index.html +2 -2
- truthound_dashboard-1.5.0.dist-info/METADATA +309 -0
- {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.0.dist-info}/RECORD +149 -148
- truthound_dashboard/core/plugins/hooks/__init__.py +0 -63
- truthound_dashboard/core/plugins/hooks/decorators.py +0 -367
- truthound_dashboard/core/plugins/hooks/manager.py +0 -403
- truthound_dashboard/core/plugins/hooks/protocols.py +0 -265
- truthound_dashboard/core/plugins/lifecycle/hot_reload.py +0 -584
- truthound_dashboard/core/reporters/junit_reporter.py +0 -233
- truthound_dashboard/core/reporters/markdown_reporter.py +0 -207
- truthound_dashboard/core/reporters/pdf_reporter.py +0 -209
- truthound_dashboard/static/assets/_baseUniq-BcrSP13d.js +0 -1
- truthound_dashboard/static/assets/arc-DlYjKwIL.js +0 -1
- truthound_dashboard/static/assets/architectureDiagram-VXUJARFQ-Bb2drbQM.js +0 -36
- truthound_dashboard/static/assets/blockDiagram-VD42YOAC-BlsPG1CH.js +0 -122
- truthound_dashboard/static/assets/c4Diagram-YG6GDRKO-B9JdUoaC.js +0 -10
- truthound_dashboard/static/assets/channel-Q6mHF1Hd.js +0 -1
- truthound_dashboard/static/assets/chunk-4BX2VUAB-DmyoPVuJ.js +0 -1
- truthound_dashboard/static/assets/chunk-55IACEB6-Bcz6Siv8.js +0 -1
- truthound_dashboard/static/assets/chunk-B4BG7PRW-Br3G5Rum.js +0 -165
- truthound_dashboard/static/assets/chunk-DI55MBZ5-DuM9c23u.js +0 -220
- truthound_dashboard/static/assets/chunk-FMBD7UC4-DNU-5mvT.js +0 -15
- truthound_dashboard/static/assets/chunk-QN33PNHL-Im2yNcmS.js +0 -1
- truthound_dashboard/static/assets/chunk-QZHKN3VN-kZr8XFm1.js +0 -1
- truthound_dashboard/static/assets/chunk-TZMSLE5B-Q__360q_.js +0 -1
- truthound_dashboard/static/assets/classDiagram-2ON5EDUG-vtixxUyK.js +0 -1
- truthound_dashboard/static/assets/classDiagram-v2-WZHVMYZB-vtixxUyK.js +0 -1
- truthound_dashboard/static/assets/clone-BOt2LwD0.js +0 -1
- truthound_dashboard/static/assets/cose-bilkent-S5V4N54A-CBDw6iac.js +0 -1
- truthound_dashboard/static/assets/dagre-6UL2VRFP-XdKqmmY9.js +0 -4
- truthound_dashboard/static/assets/diagram-PSM6KHXK-DAZ8nx9V.js +0 -24
- truthound_dashboard/static/assets/diagram-QEK2KX5R-BRvDTbGD.js +0 -43
- truthound_dashboard/static/assets/diagram-S2PKOQOG-bQcczUkl.js +0 -24
- truthound_dashboard/static/assets/erDiagram-Q2GNP2WA-DPje7VMN.js +0 -60
- truthound_dashboard/static/assets/flowDiagram-NV44I4VS-B7BVtFVS.js +0 -162
- truthound_dashboard/static/assets/ganttDiagram-JELNMOA3-D6WKSS7U.js +0 -267
- truthound_dashboard/static/assets/gitGraphDiagram-NY62KEGX-D3vtVd3y.js +0 -65
- truthound_dashboard/static/assets/graph-BKgNKZVp.js +0 -1
- truthound_dashboard/static/assets/index-C6JSrkHo.css +0 -1
- truthound_dashboard/static/assets/index-DkU82VsU.js +0 -1800
- truthound_dashboard/static/assets/infoDiagram-WHAUD3N6-DnNCT429.js +0 -2
- truthound_dashboard/static/assets/journeyDiagram-XKPGCS4Q-DGiMozqS.js +0 -139
- truthound_dashboard/static/assets/kanban-definition-3W4ZIXB7-BV2gUgli.js +0 -89
- truthound_dashboard/static/assets/katex-Cu_Erd72.js +0 -261
- truthound_dashboard/static/assets/layout-DI2MfQ5G.js +0 -1
- truthound_dashboard/static/assets/min-DYdgXVcT.js +0 -1
- truthound_dashboard/static/assets/mindmap-definition-VGOIOE7T-C7x4ruxz.js +0 -68
- truthound_dashboard/static/assets/pieDiagram-ADFJNKIX-CAJaAB9f.js +0 -30
- truthound_dashboard/static/assets/quadrantDiagram-AYHSOK5B-DeqwDI46.js +0 -7
- truthound_dashboard/static/assets/requirementDiagram-UZGBJVZJ-e3XDpZIM.js +0 -64
- truthound_dashboard/static/assets/sankeyDiagram-TZEHDZUN-CNnAv5Ux.js +0 -10
- truthound_dashboard/static/assets/sequenceDiagram-WL72ISMW-Dsne-Of3.js +0 -145
- truthound_dashboard/static/assets/stateDiagram-FKZM4ZOC-Ee0sQXyb.js +0 -1
- truthound_dashboard/static/assets/stateDiagram-v2-4FDKWEC3-B26KqW_W.js +0 -1
- truthound_dashboard/static/assets/timeline-definition-IT6M3QCI-DZYi2yl3.js +0 -61
- truthound_dashboard/static/assets/treemap-KMMF4GRG-CY3f8In2.js +0 -128
- truthound_dashboard/static/assets/unmerged_dictionaries-Dd7xcPWG.js +0 -1
- truthound_dashboard/static/assets/xychartDiagram-PRI3JC2R-CS7fydZZ.js +0 -7
- truthound_dashboard-1.4.4.dist-info/METADATA +0 -507
- {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.0.dist-info}/WHEEL +0 -0
- {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.0.dist-info}/entry_points.txt +0 -0
- {truthound_dashboard-1.4.4.dist-info → truthound_dashboard-1.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -27,9 +27,8 @@ from truthound_dashboard.core.plugins.validator_executor import ValidatorContext
|
|
|
27
27
|
from truthound_dashboard.db.models import PluginStatus as DBPluginStatus
|
|
28
28
|
from truthound_dashboard.db.models import PluginType as DBPluginType
|
|
29
29
|
from truthound_dashboard.db.models import Validation
|
|
30
|
+
from truthound_dashboard.schemas.base import MessageResponse
|
|
30
31
|
from truthound_dashboard.schemas.plugins import (
|
|
31
|
-
AddSignerRequest,
|
|
32
|
-
CodeAnalysisResult,
|
|
33
32
|
CustomReporterCreate,
|
|
34
33
|
CustomReporterListResponse,
|
|
35
34
|
CustomReporterResponse,
|
|
@@ -43,13 +42,6 @@ from truthound_dashboard.schemas.plugins import (
|
|
|
43
42
|
DependencyResolutionResponse,
|
|
44
43
|
DocumentationRenderRequest,
|
|
45
44
|
DocumentationRenderResponse,
|
|
46
|
-
ExtendedSecurityReport,
|
|
47
|
-
HookListResponse,
|
|
48
|
-
HookRegistration,
|
|
49
|
-
HookType,
|
|
50
|
-
HotReloadConfigRequest,
|
|
51
|
-
HotReloadResult,
|
|
52
|
-
HotReloadStatus,
|
|
53
45
|
MarketplaceSearchRequest,
|
|
54
46
|
MarketplaceStats,
|
|
55
47
|
PluginCreate,
|
|
@@ -69,17 +61,10 @@ from truthound_dashboard.schemas.plugins import (
|
|
|
69
61
|
PluginUninstallResponse,
|
|
70
62
|
PluginUpdate,
|
|
71
63
|
PluginUpdateCheckResponse,
|
|
72
|
-
RegisterHookRequest,
|
|
73
64
|
ReporterGenerateRequest,
|
|
74
65
|
ReporterGenerateResponse,
|
|
75
|
-
SecurityAnalysisRequest,
|
|
76
|
-
SecurityPolicyConfig,
|
|
77
|
-
TrustStoreResponse,
|
|
78
|
-
TrustedSigner,
|
|
79
66
|
ValidatorTestRequest,
|
|
80
67
|
ValidatorTestResponse,
|
|
81
|
-
VerifySignatureRequest,
|
|
82
|
-
VerifySignatureResponse,
|
|
83
68
|
)
|
|
84
69
|
|
|
85
70
|
from .deps import get_session
|
|
@@ -1212,7 +1197,7 @@ async def download_custom_report(
|
|
|
1212
1197
|
session: SessionDep,
|
|
1213
1198
|
reporter_id: str,
|
|
1214
1199
|
validation_id: str = Query(..., description="Validation ID to generate report from"),
|
|
1215
|
-
output_format: str = Query("html", description="Output format (html, json, csv
|
|
1200
|
+
output_format: str = Query("html", description="Output format (html, json, csv)"),
|
|
1216
1201
|
config: str | None = Query(None, description="JSON-encoded reporter configuration"),
|
|
1217
1202
|
) -> Any:
|
|
1218
1203
|
"""Download a report generated by a custom reporter.
|
|
@@ -1337,10 +1322,7 @@ def _get_extension(format_type: str) -> str:
|
|
|
1337
1322
|
"html": "html",
|
|
1338
1323
|
"json": "json",
|
|
1339
1324
|
"csv": "csv",
|
|
1340
|
-
"markdown": "md",
|
|
1341
|
-
"pdf": "pdf",
|
|
1342
1325
|
"xml": "xml",
|
|
1343
|
-
"junit": "xml",
|
|
1344
1326
|
}
|
|
1345
1327
|
return extensions.get(format_type.lower(), "txt")
|
|
1346
1328
|
|
|
@@ -1454,115 +1436,6 @@ async def transition_plugin_state(
|
|
|
1454
1436
|
)
|
|
1455
1437
|
|
|
1456
1438
|
|
|
1457
|
-
# =============================================================================
|
|
1458
|
-
# Plugin Hot Reload Endpoints
|
|
1459
|
-
# =============================================================================
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
@router.get("/plugins/{plugin_id}/hot-reload", response_model=HotReloadStatus)
|
|
1463
|
-
async def get_hot_reload_status(
|
|
1464
|
-
session: SessionDep,
|
|
1465
|
-
plugin_id: str,
|
|
1466
|
-
) -> HotReloadStatus:
|
|
1467
|
-
"""Get hot reload status for a plugin.
|
|
1468
|
-
|
|
1469
|
-
Args:
|
|
1470
|
-
session: Database session.
|
|
1471
|
-
plugin_id: Plugin ID.
|
|
1472
|
-
|
|
1473
|
-
Returns:
|
|
1474
|
-
Hot reload status.
|
|
1475
|
-
"""
|
|
1476
|
-
plugin = await plugin_registry.get_plugin(session, plugin_id=plugin_id)
|
|
1477
|
-
if not plugin:
|
|
1478
|
-
raise HTTPException(
|
|
1479
|
-
status_code=status.HTTP_404_NOT_FOUND,
|
|
1480
|
-
detail=f"Plugin {plugin_id} not found",
|
|
1481
|
-
)
|
|
1482
|
-
|
|
1483
|
-
# Return default status (would be managed by HotReloadManager in production)
|
|
1484
|
-
from truthound_dashboard.schemas.plugins import ReloadStrategy
|
|
1485
|
-
|
|
1486
|
-
return HotReloadStatus(
|
|
1487
|
-
plugin_id=plugin_id,
|
|
1488
|
-
enabled=False,
|
|
1489
|
-
watching=False,
|
|
1490
|
-
strategy=ReloadStrategy.MANUAL,
|
|
1491
|
-
has_pending_reload=False,
|
|
1492
|
-
)
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
@router.post("/plugins/{plugin_id}/hot-reload/configure", response_model=HotReloadStatus)
|
|
1496
|
-
async def configure_hot_reload(
|
|
1497
|
-
session: SessionDep,
|
|
1498
|
-
plugin_id: str,
|
|
1499
|
-
request: HotReloadConfigRequest,
|
|
1500
|
-
) -> HotReloadStatus:
|
|
1501
|
-
"""Configure hot reload for a plugin.
|
|
1502
|
-
|
|
1503
|
-
Args:
|
|
1504
|
-
session: Database session.
|
|
1505
|
-
plugin_id: Plugin ID.
|
|
1506
|
-
request: Hot reload configuration.
|
|
1507
|
-
|
|
1508
|
-
Returns:
|
|
1509
|
-
Updated hot reload status.
|
|
1510
|
-
"""
|
|
1511
|
-
plugin = await plugin_registry.get_plugin(session, plugin_id=plugin_id)
|
|
1512
|
-
if not plugin:
|
|
1513
|
-
raise HTTPException(
|
|
1514
|
-
status_code=status.HTTP_404_NOT_FOUND,
|
|
1515
|
-
detail=f"Plugin {plugin_id} not found",
|
|
1516
|
-
)
|
|
1517
|
-
|
|
1518
|
-
# In production, this would configure the HotReloadManager
|
|
1519
|
-
return HotReloadStatus(
|
|
1520
|
-
plugin_id=plugin_id,
|
|
1521
|
-
enabled=request.enabled,
|
|
1522
|
-
watching=request.enabled,
|
|
1523
|
-
strategy=request.strategy,
|
|
1524
|
-
has_pending_reload=False,
|
|
1525
|
-
)
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
@router.post("/plugins/{plugin_id}/hot-reload/trigger", response_model=HotReloadResult)
|
|
1529
|
-
async def trigger_hot_reload(
|
|
1530
|
-
session: SessionDep,
|
|
1531
|
-
plugin_id: str,
|
|
1532
|
-
) -> HotReloadResult:
|
|
1533
|
-
"""Manually trigger a hot reload for a plugin.
|
|
1534
|
-
|
|
1535
|
-
Args:
|
|
1536
|
-
session: Database session.
|
|
1537
|
-
plugin_id: Plugin ID.
|
|
1538
|
-
|
|
1539
|
-
Returns:
|
|
1540
|
-
Hot reload result.
|
|
1541
|
-
"""
|
|
1542
|
-
plugin = await plugin_registry.get_plugin(session, plugin_id=plugin_id)
|
|
1543
|
-
if not plugin:
|
|
1544
|
-
raise HTTPException(
|
|
1545
|
-
status_code=status.HTTP_404_NOT_FOUND,
|
|
1546
|
-
detail=f"Plugin {plugin_id} not found",
|
|
1547
|
-
)
|
|
1548
|
-
|
|
1549
|
-
# In production, this would trigger the HotReloadManager
|
|
1550
|
-
import time
|
|
1551
|
-
|
|
1552
|
-
start = time.perf_counter()
|
|
1553
|
-
# Simulate reload
|
|
1554
|
-
duration = (time.perf_counter() - start) * 1000
|
|
1555
|
-
|
|
1556
|
-
return HotReloadResult(
|
|
1557
|
-
success=True,
|
|
1558
|
-
plugin_id=plugin_id,
|
|
1559
|
-
old_version=plugin.version,
|
|
1560
|
-
new_version=plugin.version,
|
|
1561
|
-
duration_ms=duration,
|
|
1562
|
-
changes=[],
|
|
1563
|
-
)
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
1439
|
# =============================================================================
|
|
1567
1440
|
# Plugin Dependency Endpoints
|
|
1568
1441
|
# =============================================================================
|
|
@@ -1691,310 +1564,6 @@ async def resolve_dependencies(
|
|
|
1691
1564
|
)
|
|
1692
1565
|
|
|
1693
1566
|
|
|
1694
|
-
# =============================================================================
|
|
1695
|
-
# Plugin Security Endpoints
|
|
1696
|
-
# =============================================================================
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
@router.get("/plugins/security/trust-store", response_model=TrustStoreResponse)
|
|
1700
|
-
async def get_trust_store(session: SessionDep) -> TrustStoreResponse:
|
|
1701
|
-
"""Get the trust store containing trusted signers.
|
|
1702
|
-
|
|
1703
|
-
Args:
|
|
1704
|
-
session: Database session.
|
|
1705
|
-
|
|
1706
|
-
Returns:
|
|
1707
|
-
Trust store information.
|
|
1708
|
-
"""
|
|
1709
|
-
# In production, this would read from the actual TrustStore
|
|
1710
|
-
return TrustStoreResponse(
|
|
1711
|
-
signers=[],
|
|
1712
|
-
total_signers=0,
|
|
1713
|
-
)
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
@router.post("/plugins/security/trust-store/signers", response_model=TrustedSigner)
|
|
1717
|
-
async def add_trusted_signer(
|
|
1718
|
-
session: SessionDep,
|
|
1719
|
-
request: AddSignerRequest,
|
|
1720
|
-
) -> TrustedSigner:
|
|
1721
|
-
"""Add a trusted signer to the trust store.
|
|
1722
|
-
|
|
1723
|
-
Args:
|
|
1724
|
-
session: Database session.
|
|
1725
|
-
request: Signer information.
|
|
1726
|
-
|
|
1727
|
-
Returns:
|
|
1728
|
-
Added signer.
|
|
1729
|
-
"""
|
|
1730
|
-
from datetime import datetime
|
|
1731
|
-
|
|
1732
|
-
from truthound_dashboard.schemas.plugins import SecurityLevel
|
|
1733
|
-
|
|
1734
|
-
# In production, this would add to the actual TrustStore
|
|
1735
|
-
return TrustedSigner(
|
|
1736
|
-
signer_id=request.signer_id,
|
|
1737
|
-
name=request.name,
|
|
1738
|
-
public_key=request.public_key,
|
|
1739
|
-
algorithm=request.algorithm,
|
|
1740
|
-
added_at=datetime.utcnow(),
|
|
1741
|
-
expires_at=request.expires_at,
|
|
1742
|
-
is_active=True,
|
|
1743
|
-
trust_level=request.trust_level or SecurityLevel.VERIFIED,
|
|
1744
|
-
)
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
@router.delete("/plugins/security/trust-store/signers/{signer_id}")
|
|
1748
|
-
async def remove_trusted_signer(
|
|
1749
|
-
session: SessionDep,
|
|
1750
|
-
signer_id: str,
|
|
1751
|
-
) -> dict[str, bool]:
|
|
1752
|
-
"""Remove a trusted signer from the trust store.
|
|
1753
|
-
|
|
1754
|
-
Args:
|
|
1755
|
-
session: Database session.
|
|
1756
|
-
signer_id: Signer ID to remove.
|
|
1757
|
-
|
|
1758
|
-
Returns:
|
|
1759
|
-
Success status.
|
|
1760
|
-
"""
|
|
1761
|
-
# In production, this would remove from the actual TrustStore
|
|
1762
|
-
return {"success": True}
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
@router.get("/plugins/security/policy", response_model=SecurityPolicyConfig)
|
|
1766
|
-
async def get_security_policy(session: SessionDep) -> SecurityPolicyConfig:
|
|
1767
|
-
"""Get current security policy configuration.
|
|
1768
|
-
|
|
1769
|
-
Args:
|
|
1770
|
-
session: Database session.
|
|
1771
|
-
|
|
1772
|
-
Returns:
|
|
1773
|
-
Security policy configuration.
|
|
1774
|
-
"""
|
|
1775
|
-
from truthound_dashboard.schemas.plugins import (
|
|
1776
|
-
IsolationLevel,
|
|
1777
|
-
SecurityPolicyPreset,
|
|
1778
|
-
)
|
|
1779
|
-
|
|
1780
|
-
# Return default policy
|
|
1781
|
-
return SecurityPolicyConfig(
|
|
1782
|
-
preset=SecurityPolicyPreset.STANDARD,
|
|
1783
|
-
isolation_level=IsolationLevel.PROCESS,
|
|
1784
|
-
require_signature=True,
|
|
1785
|
-
min_signatures=1,
|
|
1786
|
-
memory_limit_mb=256,
|
|
1787
|
-
cpu_time_limit_sec=30,
|
|
1788
|
-
network_enabled=False,
|
|
1789
|
-
filesystem_read=False,
|
|
1790
|
-
filesystem_write=False,
|
|
1791
|
-
)
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
@router.put("/plugins/security/policy", response_model=SecurityPolicyConfig)
|
|
1795
|
-
async def update_security_policy(
|
|
1796
|
-
session: SessionDep,
|
|
1797
|
-
request: SecurityPolicyConfig,
|
|
1798
|
-
) -> SecurityPolicyConfig:
|
|
1799
|
-
"""Update security policy configuration.
|
|
1800
|
-
|
|
1801
|
-
Args:
|
|
1802
|
-
session: Database session.
|
|
1803
|
-
request: New policy configuration.
|
|
1804
|
-
|
|
1805
|
-
Returns:
|
|
1806
|
-
Updated policy configuration.
|
|
1807
|
-
"""
|
|
1808
|
-
# In production, this would persist the policy
|
|
1809
|
-
return request
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
@router.post("/plugins/{plugin_id}/security/analyze", response_model=ExtendedSecurityReport)
|
|
1813
|
-
async def analyze_plugin_security(
|
|
1814
|
-
session: SessionDep,
|
|
1815
|
-
plugin_id: str,
|
|
1816
|
-
request: SecurityAnalysisRequest | None = None,
|
|
1817
|
-
) -> ExtendedSecurityReport:
|
|
1818
|
-
"""Perform detailed security analysis on a plugin.
|
|
1819
|
-
|
|
1820
|
-
Args:
|
|
1821
|
-
session: Database session.
|
|
1822
|
-
plugin_id: Plugin ID.
|
|
1823
|
-
request: Analysis request.
|
|
1824
|
-
|
|
1825
|
-
Returns:
|
|
1826
|
-
Extended security report.
|
|
1827
|
-
"""
|
|
1828
|
-
from datetime import datetime
|
|
1829
|
-
|
|
1830
|
-
from truthound_dashboard.schemas.plugins import SecurityLevel
|
|
1831
|
-
|
|
1832
|
-
plugin = await plugin_registry.get_plugin(session, plugin_id=plugin_id)
|
|
1833
|
-
if not plugin:
|
|
1834
|
-
raise HTTPException(
|
|
1835
|
-
status_code=status.HTTP_404_NOT_FOUND,
|
|
1836
|
-
detail=f"Plugin {plugin_id} not found",
|
|
1837
|
-
)
|
|
1838
|
-
|
|
1839
|
-
# Perform security analysis
|
|
1840
|
-
code = request.code if request else None
|
|
1841
|
-
code_analysis = None
|
|
1842
|
-
|
|
1843
|
-
if code:
|
|
1844
|
-
code_analysis = CodeAnalysisResult(
|
|
1845
|
-
is_safe=True,
|
|
1846
|
-
issues=[],
|
|
1847
|
-
warnings=[],
|
|
1848
|
-
blocked_constructs=[],
|
|
1849
|
-
detected_imports=[],
|
|
1850
|
-
detected_permissions=[],
|
|
1851
|
-
complexity_score=0,
|
|
1852
|
-
)
|
|
1853
|
-
|
|
1854
|
-
return ExtendedSecurityReport(
|
|
1855
|
-
plugin_id=plugin_id,
|
|
1856
|
-
analyzed_at=datetime.utcnow(),
|
|
1857
|
-
risk_level=plugin.security_level or SecurityLevel.UNVERIFIED,
|
|
1858
|
-
issues=[],
|
|
1859
|
-
warnings=[],
|
|
1860
|
-
permissions_required=plugin.permissions or [],
|
|
1861
|
-
signature_valid=False,
|
|
1862
|
-
sandbox_compatible=True,
|
|
1863
|
-
code_analysis=code_analysis,
|
|
1864
|
-
signature_count=0,
|
|
1865
|
-
trust_level=plugin.security_level or SecurityLevel.UNVERIFIED,
|
|
1866
|
-
can_run_in_sandbox=True,
|
|
1867
|
-
code_hash="",
|
|
1868
|
-
recommendations=["Sign the plugin for production use"],
|
|
1869
|
-
)
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
@router.post("/plugins/security/verify-signature", response_model=VerifySignatureResponse)
|
|
1873
|
-
async def verify_plugin_signature(
|
|
1874
|
-
session: SessionDep,
|
|
1875
|
-
request: VerifySignatureRequest,
|
|
1876
|
-
) -> VerifySignatureResponse:
|
|
1877
|
-
"""Verify a plugin signature.
|
|
1878
|
-
|
|
1879
|
-
Args:
|
|
1880
|
-
session: Database session.
|
|
1881
|
-
request: Verification request.
|
|
1882
|
-
|
|
1883
|
-
Returns:
|
|
1884
|
-
Verification result.
|
|
1885
|
-
"""
|
|
1886
|
-
# In production, this would use the actual verification chain
|
|
1887
|
-
return VerifySignatureResponse(
|
|
1888
|
-
is_valid=False,
|
|
1889
|
-
error="Signature verification not implemented",
|
|
1890
|
-
)
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
# =============================================================================
|
|
1894
|
-
# Plugin Hooks Endpoints
|
|
1895
|
-
# =============================================================================
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
@router.get("/plugins/hooks", response_model=HookListResponse)
|
|
1899
|
-
async def list_hooks(
|
|
1900
|
-
session: SessionDep,
|
|
1901
|
-
hook_type: HookType | None = None,
|
|
1902
|
-
plugin_id: str | None = None,
|
|
1903
|
-
) -> HookListResponse:
|
|
1904
|
-
"""List registered hooks.
|
|
1905
|
-
|
|
1906
|
-
Args:
|
|
1907
|
-
session: Database session.
|
|
1908
|
-
hook_type: Filter by hook type.
|
|
1909
|
-
plugin_id: Filter by plugin ID.
|
|
1910
|
-
|
|
1911
|
-
Returns:
|
|
1912
|
-
List of registered hooks.
|
|
1913
|
-
"""
|
|
1914
|
-
# In production, this would query the HookManager
|
|
1915
|
-
return HookListResponse(
|
|
1916
|
-
hooks=[],
|
|
1917
|
-
total=0,
|
|
1918
|
-
by_type={},
|
|
1919
|
-
)
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
@router.post("/plugins/hooks", response_model=HookRegistration)
|
|
1923
|
-
async def register_hook(
|
|
1924
|
-
session: SessionDep,
|
|
1925
|
-
request: RegisterHookRequest,
|
|
1926
|
-
) -> HookRegistration:
|
|
1927
|
-
"""Register a new hook.
|
|
1928
|
-
|
|
1929
|
-
Args:
|
|
1930
|
-
session: Database session.
|
|
1931
|
-
request: Hook registration request.
|
|
1932
|
-
|
|
1933
|
-
Returns:
|
|
1934
|
-
Registered hook.
|
|
1935
|
-
"""
|
|
1936
|
-
import uuid
|
|
1937
|
-
|
|
1938
|
-
from truthound_dashboard.schemas.plugins import HookPriority
|
|
1939
|
-
|
|
1940
|
-
# In production, this would register with the HookManager
|
|
1941
|
-
return HookRegistration(
|
|
1942
|
-
id=str(uuid.uuid4()),
|
|
1943
|
-
hook_type=request.hook_type,
|
|
1944
|
-
plugin_id=request.plugin_id,
|
|
1945
|
-
function_name=request.function_name,
|
|
1946
|
-
priority=request.priority or HookPriority.NORMAL,
|
|
1947
|
-
is_async=False,
|
|
1948
|
-
is_enabled=True,
|
|
1949
|
-
description=request.description,
|
|
1950
|
-
)
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
@router.delete("/plugins/hooks/{hook_id}")
|
|
1954
|
-
async def unregister_hook(
|
|
1955
|
-
session: SessionDep,
|
|
1956
|
-
hook_id: str,
|
|
1957
|
-
) -> dict[str, bool]:
|
|
1958
|
-
"""Unregister a hook.
|
|
1959
|
-
|
|
1960
|
-
Args:
|
|
1961
|
-
session: Database session.
|
|
1962
|
-
hook_id: Hook ID to unregister.
|
|
1963
|
-
|
|
1964
|
-
Returns:
|
|
1965
|
-
Success status.
|
|
1966
|
-
"""
|
|
1967
|
-
# In production, this would unregister from the HookManager
|
|
1968
|
-
return {"success": True}
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
@router.get("/plugins/hooks/types")
|
|
1972
|
-
async def list_hook_types() -> list[dict[str, str]]:
|
|
1973
|
-
"""List available hook types.
|
|
1974
|
-
|
|
1975
|
-
Returns:
|
|
1976
|
-
List of hook types with descriptions.
|
|
1977
|
-
"""
|
|
1978
|
-
return [
|
|
1979
|
-
{"type": "before_validation", "description": "Runs before validation starts"},
|
|
1980
|
-
{"type": "after_validation", "description": "Runs after validation completes"},
|
|
1981
|
-
{"type": "on_issue_found", "description": "Runs when a validation issue is found"},
|
|
1982
|
-
{"type": "before_profile", "description": "Runs before data profiling"},
|
|
1983
|
-
{"type": "after_profile", "description": "Runs after data profiling"},
|
|
1984
|
-
{"type": "before_compare", "description": "Runs before drift comparison"},
|
|
1985
|
-
{"type": "after_compare", "description": "Runs after drift comparison"},
|
|
1986
|
-
{"type": "on_plugin_load", "description": "Runs when a plugin is loaded"},
|
|
1987
|
-
{"type": "on_plugin_unload", "description": "Runs when a plugin is unloaded"},
|
|
1988
|
-
{"type": "on_plugin_error", "description": "Runs when a plugin error occurs"},
|
|
1989
|
-
{"type": "before_notification", "description": "Runs before sending notifications"},
|
|
1990
|
-
{"type": "after_notification", "description": "Runs after sending notifications"},
|
|
1991
|
-
{"type": "on_schedule_run", "description": "Runs when a schedule executes"},
|
|
1992
|
-
{"type": "on_data_source_connect", "description": "Runs when connecting to a data source"},
|
|
1993
|
-
{"type": "on_schema_change", "description": "Runs when schema changes are detected"},
|
|
1994
|
-
{"type": "custom", "description": "Custom hook type"},
|
|
1995
|
-
]
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
1567
|
# =============================================================================
|
|
1999
1568
|
# Plugin Documentation Endpoints
|
|
2000
1569
|
# =============================================================================
|