From 77fbe5b38cead52bb8d4de04d8299376610f6d3f Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:39:19 +0000 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Dynamic=20ZT=20pr?= =?UTF-8?q?ogress=20and=20report=20navigation=20enhancements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Define ZT_PILLAR_DOMAINS constant and get_maturity_pct helper for consistency. - Enhance generate_ssp with dynamic ZT pillar progress bars. - Add "Back to Top" navigation links and findings summary to SSP report. - Update status emoji for not_implemented to 🚫. - Refactor get_dashboard to use shared ZT pillar definitions. Co-authored-by: AGI-Corporation <186229839+AGI-Corporation@users.noreply.github.com> --- backend/routers/reports.py | 64 ++++++++++++++++++++++++++++---------- tests/test_palette_ux.py | 15 +++++++++ 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/backend/routers/reports.py b/backend/routers/reports.py index 5f2660b..9edaf15 100644 --- a/backend/routers/reports.py +++ b/backend/routers/reports.py @@ -23,6 +23,30 @@ router = APIRouter() +# Zero Trust Pillar to CMMC Domain mapping +ZT_PILLAR_DOMAINS = { + "User": ["AC", "IA", "PS"], + "Device": ["CM", "MA", "PE"], + "Network": ["SC", "AC"], + "Application": ["CM", "CA", "SI"], + "Data": ["MP", "SC", "AU"], + "Visibility & Analytics": ["AU", "IR", "RA"], + "Automation & Orchestration": ["IR", "SI", "CA"], +} + + +def get_maturity_pct(assessments: List[AssessmentRecord]) -> float: + """Calculate maturity percentage with 0.5 weight for partial implementations.""" + if not assessments: + return 0.0 + implemented = sum(1 for a in assessments if a.status == "implemented") + partial = sum( + 1 + for a in assessments + if a.status in ["partial", "partially_implemented", "planned"] + ) + return ((implemented + (partial * 0.5)) / len(assessments)) * 100 + def get_status_emoji(status: str) -> str: """Map implementation status to a visual emoji for better scannability.""" @@ -31,7 +55,7 @@ def get_status_emoji(status: str) -> str: "partial": "🟡", "partially_implemented": "🟡", "planned": "📝", - "not_implemented": "🛑", + "not_implemented": "🚫", "na": "⚪", "not_started": "⚪", } @@ -102,6 +126,16 @@ async def generate_ssp( ) progress_bar = get_progress_bar(compliance_pct) + # Calculate ZT Pillar progress + zt_alignment_rows = "" + for pillar, domains in ZT_PILLAR_DOMAINS.items(): + pillar_assessments = [ + a for a in assessments + if any(a.control_id.startswith(d) for d in domains) + ] + maturity = get_maturity_pct(pillar_assessments) + zt_alignment_rows += f"| {pillar} | {', '.join(domains)} | {get_progress_bar(maturity)} |\n" + ssp = f"""# System Security Plan (SSP) ## {system_name} @@ -136,23 +170,22 @@ async def generate_ssp( | Not Implemented | {get_status_emoji('not_implemented')} {status_counts['not_implemented']} | | N/A | {get_status_emoji('na')} {status_counts['na']} | +[↑ Back to Top](#system-security-plan-ssp) + ## 2. Control Implementation Summary ### Zero Trust Pillar Alignment | ZT Pillar | CMMC Domains | Status | |-----------|--------------|--------| -| User | AC, IA, PS | See assessment | -| Device | CM, MA, PE | See assessment | -| Network | SC, AC | See assessment | -| Application | CM, CA, SI | See assessment | -| Data | MP, SC, AU | See assessment | -| Visibility & Analytics | AU, IR, RA | See assessment | -| Automation & Orchestration | IR, SI, CA | See assessment | +{zt_alignment_rows} + +[↑ Back to Top](#system-security-plan-ssp) ## 3. Assessment Findings -*Note: Only the first 20 assessment findings are displayed in this summary.* +*Showing {min(20, len(assessments))} of {len(assessments)} findings.* + """ @@ -171,6 +204,11 @@ async def generate_ssp( - **Notes:** {a.notes or 'None'} - **Evidence IDs:** {', '.join(a.evidence_ids or []) or 'None'} +""" + + ssp += """ +[↑ Back to Top](#system-security-plan-ssp) + """ ssp += """ @@ -300,13 +338,7 @@ async def get_dashboard( round(implemented / total_controls * 100, 1) if total_controls else 0 ), "zt_pillars": [ - {"pillar": "User", "domains": ["AC", "IA", "PS"]}, - {"pillar": "Device", "domains": ["CM", "MA", "PE"]}, - {"pillar": "Network", "domains": ["SC", "AC"]}, - {"pillar": "Application", "domains": ["CM", "CA", "SI"]}, - {"pillar": "Data", "domains": ["MP", "SC", "AU"]}, - {"pillar": "Visibility & Analytics", "domains": ["AU", "IR", "RA"]}, - {"pillar": "Automation & Orchestration", "domains": ["IR", "SI", "CA"]}, + {"pillar": p, "domains": d} for p, d in ZT_PILLAR_DOMAINS.items() ], "agents": [ {"name": "orchestrator", "endpoint": "/api/orchestrator"}, diff --git a/tests/test_palette_ux.py b/tests/test_palette_ux.py index 04bed3a..c4284a2 100644 --- a/tests/test_palette_ux.py +++ b/tests/test_palette_ux.py @@ -73,3 +73,18 @@ async def test_ssp_ux_elements(): assert "⭐⭐⭐⭐⭐" in content # 0.5 confidence should have 3 stars: ⭐⭐⭐☆☆ (based on int(0.5 * 5 + 0.5) = 3) assert "⭐⭐⭐☆☆" in content + + # Check for navigation links + assert "[↑ Back to Top](#system-security-plan-ssp)" in content + + # Check for summary findings line + assert "Showing 2 of 2 findings." in content + + # Check for ZT pillars in the alignment table + assert "User" in content + assert "Device" in content + assert "Network" in content + assert "Application" in content + assert "Data" in content + assert "Visibility & Analytics" in content + assert "Automation & Orchestration" in content From 9040394cfd709eac22988b2b4c67230710f715a2 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:43:10 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Dynamic=20ZT=20pr?= =?UTF-8?q?ogress=20and=20report=20navigation=20enhancements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Define ZT_PILLAR_DOMAINS constant and get_maturity_pct helper for consistency. - Enhance generate_ssp with dynamic ZT pillar progress bars. - Add "Back to Top" navigation links and findings summary to SSP report. - Update status emoji for not_implemented to 🚫. - Refactor get_dashboard to use shared ZT pillar definitions. - Resolved PEP8 linting issues in backend/routers/reports.py. Co-authored-by: AGI-Corporation <186229839+AGI-Corporation@users.noreply.github.com> --- backend/routers/reports.py | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/backend/routers/reports.py b/backend/routers/reports.py index 9edaf15..f48f9b3 100644 --- a/backend/routers/reports.py +++ b/backend/routers/reports.py @@ -8,17 +8,15 @@ import csv import io -import json from datetime import UTC, date, datetime -from typing import Any, Dict, List +from typing import List from fastapi import APIRouter, Depends from fastapi.responses import PlainTextResponse from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession -from backend.db.database import (AssessmentRecord, ControlRecord, - EvidenceRecord, get_db, +from backend.db.database import (AssessmentRecord, ControlRecord, get_db, get_latest_assessments) router = APIRouter() @@ -118,14 +116,6 @@ async def generate_ssp( ) sprs_estimate = max(-203, round(sprs_estimate, 0)) - total_controls_count = len(controls) - compliance_pct = ( - (status_counts["implemented"] / total_controls_count * 100) - if total_controls_count > 0 - else 0 - ) - progress_bar = get_progress_bar(compliance_pct) - # Calculate ZT Pillar progress zt_alignment_rows = "" for pillar, domains in ZT_PILLAR_DOMAINS.items(): @@ -139,10 +129,10 @@ async def generate_ssp( ssp = f"""# System Security Plan (SSP) ## {system_name} -**Classification:** {classification} +**Classification:** {classification} **Generated:** {datetime.now(UTC).strftime('%Y-%m-%d %H:%M UTC')} -**Framework:** CMMC 2.0 Level 2 / NIST SP 800-171 Rev 2 -**SPRS Score Estimate:** {sprs_estimate} +**Framework:** CMMC 2.0 Level 2 / NIST SP 800-171 Rev 2 +**SPRS Score Estimate:** {sprs_estimate} **Overall Compliance:** {get_progress_bar(implemented_pct)} --- @@ -287,7 +277,7 @@ async def generate_poam( content=csv_content, media_type="text/csv", headers={ - "Content-Disposition": f'attachment; filename="poam_{system_name.replace(" ","_")}.csv"' + "Content-Disposition": f'attachment; filename="poam_{system_name.replace(" ", "_")}.csv"' }, ) From 227f3b9e5cdedd7bd23f1f25e25a3eca50aff1a6 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:46:04 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Dynamic=20ZT=20pr?= =?UTF-8?q?ogress=20and=20report=20navigation=20enhancements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Define ZT_PILLAR_DOMAINS constant and get_maturity_pct helper for consistency. - Enhance generate_ssp with dynamic ZT pillar progress bars. - Add "Back to Top" navigation links and findings summary to SSP report. - Update status emoji for not_implemented to 🚫. - Refactor get_dashboard to use shared ZT pillar definitions. - Resolved all remaining PEP8 linting issues in backend/routers/reports.py. Co-authored-by: AGI-Corporation <186229839+AGI-Corporation@users.noreply.github.com> From dd1f5874d39a21ea6d4af86a1578247ce5ccdfff Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:49:49 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Dynamic=20ZT=20pr?= =?UTF-8?q?ogress=20and=20report=20navigation=20enhancements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Define ZT_PILLAR_DOMAINS constant and get_maturity_pct helper for consistency. - Enhance generate_ssp with dynamic ZT pillar progress bars. - Add "Back to Top" navigation links and findings summary to SSP report. - Update status emoji for not_implemented to 🚫. - Refactor get_dashboard to use shared ZT pillar definitions. - Resolved all PEP8 linting issues in backend/routers/reports.py. Co-authored-by: AGI-Corporation <186229839+AGI-Corporation@users.noreply.github.com>