"""Completion tracker - monitors progress toward 100% feature completion.""" from app.db.session import AsyncSessionLocal from app.models.models import Finding, User, Asset, RiskScore, AttackPath, AuditReport from sqlalchemy import select, func from datetime import datetime, timedelta import logging logger = logging.getLogger(__name__) class CompletionTracker: """Track system completion and feature adoption.""" async def get_completion_metrics(self, tenant_id: str) -> dict: """Calculate completion percentage and breakdown.""" async with AsyncSessionLocal() as db: # Count entities users_result = await db.execute( select(func.count(User.id)).where(User.tenant_id == tenant_id) ) user_count = users_result.scalar() or 0 assets_result = await db.execute( select(func.count(Asset.id)).where(Asset.tenant_id == tenant_id) ) asset_count = assets_result.scalar() or 0 findings_result = await db.execute( select(func.count(Finding.id)).where(Finding.tenant_id == tenant_id) ) finding_count = findings_result.scalar() or 0 # Get critical findings from app.models.models import FindingSeverity, FindingStatus critical_result = await db.execute( select(func.count(Finding.id)).where( Finding.tenant_id == tenant_id, Finding.severity == FindingSeverity.critical ) ) critical_count = critical_result.scalar() or 0 resolved_result = await db.execute( select(func.count(Finding.id)).where( Finding.tenant_id == tenant_id, Finding.status == FindingStatus.resolved ) ) resolved_count = resolved_result.scalar() or 0 attack_paths_result = await db.execute( select(func.count(AttackPath.id)).where(AttackPath.finding_id.in_( select(Finding.id).where(Finding.tenant_id == tenant_id) )) ) attack_path_count = attack_paths_result.scalar() or 0 reports_result = await db.execute( select(func.count(AuditReport.id)).where(AuditReport.tenant_id == tenant_id) ) report_count = reports_result.scalar() or 0 # Calculate completion scores completion_scores = { "team_setup": min(100, (user_count / 2) * 100), # Goal: 2-3 users "asset_inventory": min(100, (asset_count / 4) * 100), # Goal: 4+ assets "risk_assessment": min(100, (finding_count / 10) * 100), # Goal: 10+ findings "remediation_progress": (resolved_count / max(1, finding_count)) * 100 if finding_count > 0 else 0, "critical_reduction": max(0, 100 - (critical_count * 10)), "threat_modeling": min(100, (attack_path_count / 5) * 50), # Goal: 5+ paths = 50% "reporting": min(100, (report_count / 2) * 100), # Goal: 2+ reports "ai_integration": min(100, (attack_path_count + report_count) / 10 * 100), # AI features used } # Overall completion overall = sum(completion_scores.values()) / len(completion_scores) return { "overall_completion": round(overall, 1), "status": "incomplete" if overall < 50 else "in_progress" if overall < 80 else "nearly_complete", "breakdown": {k: round(v, 1) for k, v in completion_scores.items()}, "metrics": { "users_added": user_count, "assets_tracked": asset_count, "findings_identified": finding_count, "findings_resolved": resolved_count, "critical_issues": critical_count, "attack_paths": attack_path_count, "reports_generated": report_count, }, "next_steps": self._get_next_steps(completion_scores, { "users": user_count, "assets": asset_count, "findings": finding_count, "resolved": resolved_count, }), } def _get_next_steps(self, scores: dict, metrics: dict) -> list: """Suggest next actions to improve completion.""" steps = [] if scores["team_setup"] < 100: steps.append("Invite IT team members to TrustOS for full team setup") if scores["asset_inventory"] < 100: steps.append("Add more assets (domains, APIs, cloud resources) to complete inventory") if scores["risk_assessment"] < 80: steps.append("Run automated scanning on all assets to identify more risks") if scores["remediation_progress"] < 50: steps.append("Create remediation plans and track resolution of identified findings") if scores["critical_reduction"] < 50: steps.append("Prioritize and resolve critical security issues") if scores["threat_modeling"] < 50: steps.append("Generate attack path visualizations for top risks") if scores["reporting"] < 80: steps.append("Create audit reports and baseline snapshots for stakeholders") if scores["ai_integration"] < 50: steps.append("Use AI features: get business impact translations and security coaching") return steps