Skip to main content

March Sprint Implementation Plan

SUPERSEDED — This plan was written before Sergey's feedback (2026-03-16) and contains decisions that were later overridden. It contradicts Sergey's decisions in at least 3 places (Phase 0.3: says "invert scores" — should be "remove"; Phase 1.2: says "A/B/C grades" — should be "plain English labels"; Phase 4.3: includes effort estimates — dropped by Sergey). Use the Consolidated Action Plan as the single source of truth.


Visual Overview

Sprint Roadmap

Sprint Roadmap

Who Sees What — Audience × Page Map

Audience Page Map

Phase 0 Blockers — Before / After

P0 Fixes Before After


Phase 0: Sprint Blockers (Fix Before Design Partner Demo)

0.1 Remediation applies_to Must Name Specific Objects

Priority: P0 — Sergey flagged this explicitly Effort: Medium (2-3 sessions) Agents that flagged this: CISO, Product QA, SecOps

Current state: Remediation actions return generic applies_to values:

  • "LLM endpoint access" → should be "Endpoint: Azure OpenAI Endpoint"
  • "execution path" → should be "Role: ap_write, ar_write on Identity: svc-invoice-bot"
  • "egress path" → should be "Connection: Billing_Payment_Methods (external)"

Root cause: The call site at src/api/routes/authority-paths.ts:108 invokes generatePathRemediation() without passing entityContext (the resolved entity/role display names from the path graph). Cluster-level remediation already passes this context, which is why cluster remediation has entity names but path-level does not.

Files to modify:

  • src/api/routes/authority-paths.ts:108Primary fix. Pass entityContext (path nodes, via_roles with display names) to generatePathRemediation(). This is the call site that's missing the context.
  • src/services/remediation-service.tsSecondary reference. The generatePathRemediation() method already accepts entityContext — it just isn't receiving it from the route handler. Verify it uses the context to resolve applies_to fields.
  • src/evidence/remediation.ts — Evidence pack remediation also generates applies_to and may need the same fix.

Implementation:

  1. In authority-paths.ts:108, construct entityContext from the authority path's nodes and via_roles arrays (display names already available from the path query)
  2. Pass it to generatePathRemediation() — the method already knows how to use it (see how cluster remediation works)
  3. The UI already renders action.applies_to — no frontend change needed

Acceptance criteria:

  • Path remediation applies_to includes at least one named entity/role from the path
  • Cluster remediation applies_to includes identity count and example names
  • No generic terms like "execution path" or "egress path" remain

0.2 Authority Path Role Visibility (Collapsing Fix)

Priority: P0 — Sergey flagged this explicitly Effort: Low-Medium (1-2 sessions) Agents that flagged this: CISO, Product QA, UX

Current state: Authority path table rows show workload → identity → destination with no role information. Roles only visible on row expand. An identity with 5 roles across 5 paths appears identical to one with 1 role.

Files to modify:

  • ui/src/pages/RiskClusterDetailPage.tsx — Cluster detail paths table
  • ui/src/pages/AuthorityPathsListPage.tsx — Authority paths list table (if exists as standalone)
  • ui/src/components/PathRiskClusterCard.tsx — If path summary is shown on cards

Implementation:

  1. Add a "Roles" column or badge to the authority paths table rows showing via_roles.length and first 2 role names:
    Roles: foundry_ai_executor (+2 more)
  2. In the expanded row, add "Identity total roles" aggregation. Group all paths by identity ID, count distinct roles:
    Total roles for svc-foundry-agent701: 5 roles across 5 paths
  3. In Standing Authority panel, remove slice(0, 2) truncation — show all roles or use a "show all" toggle.

Acceptance criteria:

  • Authority path table row shows role count or first role name without expanding
  • Expanded row shows identity's total role count across all paths
  • Standing Authority panel shows all roles (not truncated to 2)

0.3 Fix Impact Score Display (Not Inversion — Semantic Mismatch)

Priority: P0 Effort: Low (1 session) Agents that flagged this: Product QA, SecOps

Current state: "Restrict LLM endpoint access" has impact_score: 0 (renders as empty bar). "Reduce to least-privilege" has impact_score: 10.

Root cause (clarified by API audit): The impact_score is actually a computeCategoryRank() value where 0 = highest priority (egress-resolving) and higher numbers = lower priority. The backend ranking is correct — the problem is the UI displays it as a progress bar where 0 = empty and 10 = full, inverting the visual meaning.

Files to modify:

  • ui/src/pages/AuthorityPathDetailPage.tsx:471-483ImpactBar component renders score as a direct percentage
  • Consider renaming the field in the API response from impact_score to priority_rank for clarity

Implementation:

  1. In ImpactBar, invert the display: render (maxScore - score) / maxScore * 100 as the bar width, so rank 0 (highest priority) shows a full bar
  2. Or: convert to a label system ("High Impact" / "Medium" / "Low") instead of a bar, avoiding the numeric confusion entirely
  3. Add a tooltip explaining what the score means

Acceptance criteria:

  • "Restrict LLM endpoint access" (rank 0) renders as the visually largest/most prominent action
  • "Reduce to least-privilege" (rank 10) renders as less prominent than egress-resolving actions
  • The visual meaning is unambiguous — no empty bars for high-priority actions

Phase 1: CISO Clarity (This Sprint)

1.1 Invert Visual Hierarchy on Cluster Cards

Effort: Low (CSS/layout) Files: ui/src/components/PathRiskClusterCard.tsx

The verdict sentence ("3 autonomous identities accessed sensitive systems 681 times...") should be the dominant text element. The path count ("13 Paths") should be secondary. Currently inverted.

  • Make verdict sentence text-base font-medium (or larger)
  • Move path count to a smaller badge or secondary line
  • Keep priority badge and domain tags

1.2 Add Evidence Grade Badges (A/B/C)

Effort: Low-Medium (component + conditional rendering) Severity: CRITICAL (upgraded per review — all 5 agents independently called this the #1 missing differentiator) Files: ui/src/components/ (new badge), ui/src/pages/AuthorityPathDetailPage.tsx, ui/src/pages/RiskClusterDetailPage.tsx

The platform's primary claim is "we show what DID execute, not what COULD." Without visible grades, this claim is unverifiable to the user. Data already exists:

  • Grade A (Execution Confirmed): execution_30d > 0
  • Grade B (Temporal Correlation): has execution evidence but execution_30d == 0 recently
  • Grade C (Standing Authority Only): execution_30d == 0, no execution evidence

Display as badge on: authority path table rows, path detail header, cluster card summary counts.


1.3 Add OWASP/Business Relevance Tags

Effort: Low (mapping table + badge) Files: ui/src/lib/ (new mapping), finding/cluster components

Mapping from existing spec:

  • orphaned_ownership → ASI03 (Identity & Privilege Abuse)
  • scope_drift → ASI10 (Rogue Agents)
  • llm_egress → ASI02 (Tool Misuse)
  • reachability_drift → ASI08 (Insufficient Control)

Render as small tags on cluster cards and finding detail pages.


1.4 Fix Governance Checklist Deduplication

Effort: Low (label mapping fix) Files: ui/src/pages/RiskClusterDetailPage.tsx:119-169 (GovernanceChecklist)

Use distinct labels:

  • orphaned_ownership → "Orphaned identities"
  • unknown_identity_binding → "Unbound identity"
  • ownership_drift → "Ownership decay"
  • reachability_drift → "Reachability expansion"
  • scope_drift → "Scope drift"

Also add path counts: "Scope drift (3 paths)" by counting finding occurrences.


1.5 Promote Highest-Risk Path in Cluster

Effort: Low (data already sorted) Files: ui/src/pages/RiskClusterDetailPage.tsx Section A

Add a callout in Section A (What Happened): "Highest risk: Agent Ascribe_Summarizer → GP_Clinical_Notes (127 executions, orphaned, LLM egress)". Use the first authority path from the cluster (already sorted by risk).


1.6 Replace Secondary Stat Cards with Business Metrics

Effort: Low (data available in posture summary + clusters) Files: ui/src/pages/OverviewPage.tsx

Replace "Active Autonomous: 5 Identities" / "Dormant Authority: 2" / "Autonomous: 7 Workloads" / "Operator-Assisted: 3" with:

  • "Sensitive Domains Reached: 6"
  • "Departed Owners Unresolved: 2"
  • "LLM Endpoints Invoked: 3"

1.7 Add "What Changed Since Yesterday" Filter

Effort: Medium (API + UI) Promoted from Phase 2 — SecOps analyst rated this the #1 daily workflow blocker. For the Deloitte managed services use case (ongoing operations, not just point-in-time assessments), this is demo-blocking. Files: src/api/routes/findings.ts, ui/src/pages/OverviewPage.tsx or FindingsList.tsx

Add ?changed_since=<ISO8601> query parameter to findings endpoint. Filter by detected_at or updated_at. On Overview, add "New since last visit" section (store last-visit timestamp in localStorage).


Phase 2: Operator Clarity (This Sprint)

2.1 Remove Finding Intervals (was 2.2)

Effort: Low Files: ui/src/pages/AuthorityPathDetailPage.tsx:360-380

Remove the intervals rendering block from FindingTile. Keep only the drift breakdown components.


2.3 Fix Ownership Section to Use Actual Names

Effort: Low Files: ui/src/pages/AuthorityPathDetailPage.tsx:584-586

Replace hardcoded "Service principal owner departed" with owner_descriptions from the finding's evidence_refs: "Maria Lopez (departed)".


2.4 Fix Breadcrumbs

Effort: Low-Medium Files: ui/src/components/Layout.tsx:59-64 (formatBreadcrumbSegment)

For authority path routes: display workload → destination chain. For cluster routes: display cluster label. For entity routes: display entity name. Use already-fetched page data.


Phase 3: Data Quality (This Sprint if Possible)

3.1 Fix added_roles Population in Evidence Packs

Effort: Medium Files: src/evidence/ — scope drift evidence assembly

When baseline_role_count=0 and current_role_count=2, added_roles must contain the 2 role names. Currently returns empty array. Also fix evidence pack text "Review 0 role assignments" → should say "Review 2 role assignments".


3.2 Fix Posture Summary Path Count

Effort: Low-Medium Files: src/services/risk-cluster-service.ts or posture aggregation

Posture summary says 32 paths (29 active + 3 dormant) but authority-paths list returns 30. Investigate discrepancy — likely removed paths being counted in posture but excluded from list.


3.3 Populate Execution Evidence target_resource

Effort: Medium-High (depends on connector data) Files: src/ingestion/ or seed script

All execution evidence records have target_resource: "". If connector doesn't provide this, the seed script should populate it. If it should come from production connectors, document the gap.


Phase 4: Reports & Deliverables Service (Next Sprint — Strategic)

One report engine, many delivery channels. The platform UI is one of them.

Architecture:

Reports Architecture

Reports are a backend service (src/services/report-service.ts) that generates structured report objects. These objects can be delivered through any channel — rendered as pages in the platform UI, sent as email/Slack digests, or exported as PDF. The report content is the same everywhere; only the presentation differs.

Report types:

ReportTriggerAudienceLength
Scan DigestAfter each scan completesSecurity leader, team leads1 page — key metrics, top 3 risks, trend
Assessment ReportOn-demand or scheduledCIO, board, partner clients6 pages — full executive summary with compliance mapping
Evidence ExportOn-demand per cluster/pathAuditors, compliance teamsVariable — sealed evidence packs with integrity hashes

All three share the same data layer (posture summary, clusters, findings, compliance mapping, remediation with effort estimates) and the same support libraries (business glossary, compliance mapping table, effort estimation).

See full strategy: Enterprise Executive Review v2

4.1 Add Compliance Mapping to Data Layer

Effort: 1-2 sessions Lives in: Platform API + UI (useful for ALL audiences — analysts, reports, exports)

Add compliance_references array to findings and clusters. Static deterministic mapping:

Finding TypeOWASP ASINIST CSFRegulatory
orphaned_ownershipASI03 (Identity & Privilege Abuse)AC-2 (Account Management)SOX: Segregation of duties
scope_driftASI10 (Rogue Agents)AC-6 (Least Privilege)SOX: Change management
llm_egressASI02 (Tool Misuse)SC-7 (Boundary Protection)HIPAA / GDPR
reachability_driftASI08 (Insufficient Control)AC-6 (Least Privilege)SOX: Access control
external_egressASI02 (Tool Misuse)SC-7 (Boundary Protection)GDPR: Data transfer

Files: Create src/lib/compliance-mapping.ts. Inject into API responses. Render as tags in UI. Source: sv0-documentation/docs/product/notion-synced/mapping-to-owasp-top-10-for-agentic-applications.md

This benefits analysts too — ticket justification, audit response, compliance reporting.

4.2 Build Report Service + Store

Effort: 3-4 sessions Files: src/services/report-service.ts, src/storage/mongo/adapters/report-adapter.ts, src/api/routes/reports.ts

The core engine. Generates report objects and stores them in MongoDB (reports collection).

Report object structure:

interface ReportDoc {
id: string;
tenant_id: string;
report_type: "scan_digest" | "assessment" | "evidence_export";
generated_at: string; // ISO8601
scan_id?: string; // links to the scan that triggered it
title: string; // "Assessment Report — March 2026"
summary: string; // 2-3 sentence executive summary
content: ReportContent; // structured sections (see below)
format_versions: { // pre-rendered for each channel
markdown: string;
html: string;
};
metadata: {
finding_count: number;
cluster_count: number;
severity_distribution: Record<string, number>;
compliance_frameworks: string[];
};
}

API endpoints:

  • GET /api/v1/reports — list reports for tenant (paginated, filtered by type)
  • GET /api/v1/reports/:id — get report detail
  • GET /api/v1/reports/:id/pdf — download PDF render
  • POST /api/v1/reports/generate — trigger on-demand generation

Generation: Can be triggered by:

  • Post-scan worker (automatic after ingestion + evaluation completes)
  • API call (on-demand from UI or partner integration)
  • CLI script (for testing: npx tsx scripts/generate-report.ts --tenant demo-w1 --type assessment)

4.3 Build Report Templates

Effort: 3-4 sessions

Scan Digest template:

  • Executive summary (4-5 sentences, business language via glossary)
  • Top 3 risks with compliance tags and effort estimates
  • Governance status checklist (passing / failing / not assessed)
  • Trend vs prior period (delta metrics)
  • Link to platform for full details

Assessment Report template (6 pages):

  1. Cover page (tenant name, date, assessment period, branding placeholder)
  2. Executive summary (1 page, pure business language — no system names)
  3. Findings summary (table with compliance mapping, severity distribution)
  4. Risk detail per cluster (verdict sentences, compliance tags, domain impact)
  5. Remediation roadmap (business terms: effort, responsible role, complexity)
  6. Appendix: methodology, evidence integrity, data sources

Shared components:

  • src/lib/business-glossary.ts — "service principal" → "automated account", "egress" → "outbound data flow", etc. Used ONLY in report rendering, not in platform UI.
  • src/lib/effort-estimation.ts — maps action categories to hours/days/weeks and responsible roles
  • src/lib/compliance-mapping.ts — (from 4.1, shared with platform)

4.4 Platform Reports Page

Effort: 2-3 sessions Files: ui/src/pages/ReportsPage.tsx, ui/src/pages/ReportDetailPage.tsx

New page in the platform sidebar: Reports

  • List of generated reports (scan digests + assessments), sorted by date
  • Each report is readable in-browser (rendered HTML) and downloadable as PDF
  • Filter by report type, date range
  • "Generate Report" button for on-demand assessment reports
  • Report detail page renders the full HTML version with print-friendly styling

This gives every user access to the executive layer without leaving the platform. The CISO opens the app, clicks "Reports", reads the latest digest. The partner downloads the assessment PDF. The analyst stays in Authority Paths.

4.5 Delivery Channels

Effort: 2-3 sessions total (incremental, one channel at a time)

Wire the report service to delivery channels:

Email: Post-scan digest sent to configured recipients. Uses the markdown/HTML format version. Include "View in platform" and "Download PDF" links. Configuration in tenant settings or env vars.

Slack: Webhook posts a condensed digest (summary + top 3 risks + link). Uses Slack Block Kit for formatting. Configure webhook URL in tenant settings.

PDF: GET /api/v1/reports/:id/pdf renders the HTML version to PDF via puppeteer (headless Chromium, already available from Playwright dependency). Also accessible from the Reports page download button.

API: GET /api/v1/reports is the integration point for partners building their own delivery. They can pull reports programmatically and wrap them in their own branded templates.

Each channel is additive — build email first (highest partner value), then Slack, then others as needed.

Phase 5: Polish (Following Sprint)

5.1 Add Findings Summary Strip

Render meta.bySeverity and meta.byType as a distribution bar above the findings table.

5.2 Enable "Create Ticket" Button

Even a copy-to-clipboard of structured remediation brief unblocks the workflow.

5.3 Resolve Navigation Orphans

Add Exposures, Findings, Execution Chains to sidebar under "Analyst" section separator.

5.4 Remove Legacy Dashboard

Redirect /dashboard to /. Remove legacy terminology (RG1/RG2).

5.5 Add Posture Trend Chart

Show executions, paths, orphaned count over 90 days using posture_snapshots collection.

5.6 Deduplicate Cluster-Level Remediation

When same action appears in 3 clusters, show once with "Applies across 3 clusters".

5.7 Standardize Ownership Terminology

Pick one term per state: "orphaned" → "No active owner", "invalid" → remove, "degraded" → consolidate with drift.


Effort Summary

PhaseItemsTotal EffortSprint Fit
Phase 0: Demo Blockers3 items (object names, role collapsing, impact display)4-6 sessionsMUST this sprint
Phase 1: Platform Clarity6 items (visual hierarchy, evidence grades, OWASP tags, governance, stat cards, "what changed")6-8 sessionsSHOULD this sprint
Phase 1 + 4.1: Compliance Mapping1 item — add compliance_references to data layer1-2 sessionsSHOULD this sprint (benefits analysts + reports)
Phase 2: Operator Detail3 items (intervals, ownership names, breadcrumbs)2-3 sessionsSHOULD this sprint
Phase 3: Data Quality3 items (added_roles, path counts, execution evidence)3-5 sessionsCAN this sprint
Phase 4.2-4.5: Report Service4 items (service + store, templates, Reports page, delivery channels)9-14 sessionsNext sprint — full project
Phase 5: Polish7 items6-10 sessionsFollowing sprint

Parallel backlog (separate track): Security hardening — JWT signature verification, tenant header validation, diagnostics endpoint. Tracked at sv0-platform#82. Fix before any auth-enabled deployment, but does not block the demo/clarity sprint work.

Critical path for platform: Phase 0 (blockers) → Phase 1 (clarity) → Phase 2 (detail). Moves from "internal demo" → "design partner demo."

Critical path for partner enablement: Phase 4.1 compliance mapping (this sprint) → Phase 4.2-4.3 MVP report generator (next sprint, start with CLI script, validate template with Deloitte before building full service) → Phase 4.4-4.5 Reports page + delivery channels (after template validated). Use Playwright/Chromium (already available) for PDF rendering — no new dependency needed.

Pending product decision: Delta badges on Overview KPI cards — UX says remove (per Feb 22 spec), CISO says keep. Needs Sergey's call before acting. Currently counted as "contested" in progress tracking, not "closed."

Decision for Sergey: Which critical path is the constraint given the Deloitte timeline — platform demo readiness or partner assessment deliverable? This determines whether 4.1 compliance mapping gets pulled into this sprint (recommended) or waits.