Skip to main content

06 — UI & Reporting Architecture

Scope: Web UI for SecurityV0 — page specifications, component architecture, data fetching patterns, evidence pack rendering, and export. This document consumes the API contract from 04-api-layer.md and the entity/finding types from 01-data-model.md.

Graph visualization rationale: The @xyflow/react + Dagre decision, layout configuration, and alternatives analysis are documented in 00-overview.md §9. This document references that section — it does not repeat it.

Implementation status:

  • Core pages (Dashboard, Graph Explorer, Findings, Entities, Automations, Syncs, Temporal): [Implemented]
  • Execution chains page, new entity type colors/edges in graph: [Planned]
  • Entity model updated to 9 types per ADR-006.

1. Tech Stack

LayerTechnologyVersionPurpose
FrameworkReact19.xComponent model, hooks
LanguageTypeScript5.9.xType safety
BuildVite7.xDev server, bundling
Graph@xyflow/react12.xCanvas, pan/zoom, node interaction
LayoutDagre0.8.xHierarchical Sugiyama layout
Data FetchingTanStack Query5.xCaching, refetch, optimistic updates
Data Tables@tanstack/react-table8.xServer-side filtering, sorting, pagination
RoutingReact Router7.xClient-side navigation
StylingTailwind CSS4.xUtility-first CSS
Iconslucide-react0.5.xConsistent icon set

For the rationale behind @xyflow/react + Dagre over alternatives (force-graph-2d, Cytoscape.js, ELK.js), see 00-overview.md §9.


2. Route Structure & Navigation

2.1 Routes

PathPagePrimary API EndpointsStatus
/DashboardGET /findings, GET /syncs?limit=1[Implemented]
/automationsAutomations ListGET /entities?entity_type=identity&identity_subtype={automation_subtypes}[Implemented] — see note below
/automations/:idAutomation DetailGET /entities/{id}, GET /graph/subgraph[Implemented]
/findingsFindings ListGET /findings[Implemented]
/findings/:idFinding DetailGET /findings/{id}, GET /findings/{id}/evidence-pack[Implemented]
/graphGraph ExplorerGET /entities, GET /graph/subgraph[Implemented]
/entitiesEntities ListGET /entities[Implemented]
/entities/:idEntity DetailGET /entities/{id}, /timeline, /blast-radius[Implemented]
/syncsSync ManagementGET /syncs, GET /syncs/{id}[Implemented] — manual trigger (POST /syncs) is [Planned]
/temporalTemporal ComparisonGET /entities/{id}/diff[Implemented]
/execution-chainsExecution ChainsGET /execution-chains[Planned]

Automations query note: The platform does not yet have a dedicated automation entity type (ADR-006 is not yet implemented in code). The current UI queries automations via entity_type=identity with identity_subtype set to automation subtypes (business_rule, flow_designer_flow, scheduled_job, system_execution) and applies a default security_relevance=active_external,dormant_authority filter. When entity type reclassification is implemented, this will change to entity_type=automation.

2.2 Layout

+---------------------------------------------------+
| Navbar (h-16) |
| Logo - SecurityV0 - [tenant context] - search |
+----------+----------------------------------------+
| Sidebar | |
| (w-64) | Main Content Area |
| | |
| Dashboard| (page-specific content) |
| Automatio| |
| Graph | |
| Findings | |
| Entities | |
| Syncs | |
| Temporal | |
| | |
+----------+----------------------------------------+
  • Navbar: Fixed top. Displays tenant context (tenant name from auth token), global search input.
  • Sidebar: Fixed left, sticky. Navigation links with active-state highlighting. Icons from lucide-react.
  • Breadcrumbs: Rendered in main content area for drill-down paths (e.g., Findings > Finding Detail > Evidence Pack).

3. Dashboard Page (/)

Purpose: At-a-glance security posture — active findings, entity statistics, sync health.

3.1 KPI Cards

Four severity cards in a 4-column grid:

CardSourceColor
Critical FindingsGET /findings?status=active&severity=criticalRed border
High FindingsGET /findings?status=active&severity=highOrange border
Medium FindingsGET /findings?status=active&severity=mediumYellow border
Low FindingsGET /findings?status=active&severity=lowBlue border

Each card displays the count and a 30-day sparkline trend (derived from detected_at timestamps in the findings response).

3.2 Entity Statistics

Summary panel showing entity counts by type (9-type model per ADR-006):

Entity TypeSourceStatus
IdentitiesGET /entities?entity_type=identity -> meta.total_count[Implemented]
AutomationsGET /entities?entity_type=identity&identity_subtype=... -> meta.total_count[Implemented] — uses identity subtype workaround (see §2.1 note)
ConnectionsGET /entities?entity_type=connection -> meta.total_count[Planned]
CredentialsGET /entities?entity_type=credential -> meta.total_count[Implemented]
OwnersGET /entities?entity_type=owner -> meta.total_count[Implemented]
RolesGET /entities?entity_type=role -> meta.total_count[Implemented]
PermissionsGET /entities?entity_type=permission -> meta.total_count[Implemented]
ResourcesGET /entities?entity_type=resource -> meta.total_count[Implemented]
Execution EvidenceGET /entities?entity_type=execution_evidence -> meta.total_count[Planned]

3.3 Recent Findings Feed

Last 10 active findings sorted by detected_at descending. Each row shows:

  • Finding type badge (color-coded)
  • Entity name (link to entity detail)
  • Severity badge
  • Time ago (relative timestamp)

API: GET /findings?status=active&sort=-detected_at&limit=10

3.4 Sync Status

Last sync indicator: time since last completed sync, next scheduled sync (if configured), pass/fail status.

API: GET /syncs?sort=-completed_at&limit=1


4. Graph Explorer Page (/graph)

Purpose: Interactive hierarchical graph visualization of the entity-relationship graph. Primary tool for exploring execution paths and identifying structural anomalies.

4.1 Layout

3:9 column grid — filter sidebar (left) + graph canvas (right).

4.2 Filter Sidebar

Sticky sidebar with filter controls:

FilterTypeValues
Entity TypesCheckboxesidentity, automation, connection, credential, owner, role, permission, resource, execution_evidence
StatusCheckboxesactive, disabled, deleted, departed (owners only)
Source SystemDropdownDynamic from entities in graph
Has FindingsToggleShow finding badge overlay
Finding TypeMulti-selectorphaned_ownership, scope_drift, dormant_authority, privilege_justification_gap, ownership_degraded

Filters apply client-side against the loaded graph data. Entity type and status filters remove nodes and their connected edges. Finding filters toggle badge visibility without removing nodes.

4.3 Graph Canvas

@xyflow/react canvas with Dagre hierarchical layout (see 00-overview.md §9 for layout rationale and configuration).

Node rendering: Custom EntityNode component.

Entity TypeColorNode SizeStatus
identity#3B82F6 (blue)140x60[Implemented]
automation#F97316 (orange-500)140x60[Planned]
connection#06B6D4 (cyan-500)120x50[Planned]
credential#6B7280 (gray)120x50[Implemented]
owner#10B981 (green)120x50[Implemented]
role#8B5CF6 (purple)120x50[Implemented]
permission#F59E0B (amber)120x50[Implemented]
resource#EF4444 (red)140x60[Implemented]
execution_evidence#A855F7 (purple-400)100x40[Planned]

Node status overlays:

  • deleted: 50% opacity with "DELETED" overlay text
  • decayed: Red dashed border

Finding badge: Red circle positioned top-right of node, showing finding count or alert icon.

Edge styling:

Relationship TypeColorStyleStatus
OWNED_BYGreenSolid[Implemented]
HAS_ROLEPurpleSolid[Implemented]
GRANTSOrangeSolid[Implemented]
AUTHENTICATES_TOBlueSolid[Implemented]
APPLIES_TOGrayDotted[Implemented]
BELONGS_TOGreenDashed[Implemented]
CALLSOrangeDashed[Planned]
INVOKESCyanSolid[Planned]
USESGrayDashed[Planned]
AUTHENTICATES_ASBlueDashed[Planned]
RUNS_ASTealSolid[Implemented]
TRIGGERS_ONYellowDotted[Planned]
EXECUTES_ONRedSolid[Implemented] (narrowed: automation->resource only per ADR-007)
AUTHENTICATES_VIAGrayDashed(deprecated -- legacy only, see ADR-007)
DefaultGraySolid[Implemented]

Dagre layout configuration:

rankdir: 'LR'     // Left-to-right flow
nodesep: 80 // Vertical spacing between nodes in same rank
ranksep: 200 // Horizontal spacing between ranks
align: 'UL' // Upper-left alignment

Rank assignment: Entity types map to column positions — execution_evidence (-1), automation (0), identity (1), connection (2), credential (3), owner (4), role (5), permission (6), resource (7).

4.4 Node Interaction

  • Click: Selects node, highlights direct neighbors (1-hop), opens detail panel below canvas.
  • Detail panel: Shows entity label, type, status, source system, finding types (if any). Links to Entity Detail page.
  • Double-click: Navigates to /entities/:id.

4.5 Path Highlighting

When an identity node is selected, its execution paths are highlighted:

  • Execution path edges glow with increased stroke width
  • Non-path nodes dim to 40% opacity
  • Path tooltip shows auth chain depth for cross-system paths

API: GET /identities/{id}/blast-radius on identity selection.

4.6 Legend & Controls

  • Legend panel: Color swatches for all 9 entity types (identity, automation, connection, credential, owner, role, permission, resource, execution_evidence), positioned bottom-left.
  • Node count panel: Total visible nodes, positioned top-right.
  • Zoom controls: @xyflow/react built-in (+/- buttons, fit-view).

5. Findings List Page (/findings)

Purpose: Filterable, sortable table of all findings.

5.1 Filters

Three filter controls in a horizontal bar above the table:

FilterTypeOptions
Finding TypeDropdownAll / orphaned_ownership / scope_drift / dormant_authority / privilege_justification_gap / ownership_degraded
SeverityDropdownAll / critical / high / medium / low
StatusDropdownAll / active / acknowledged / remediated / false_positive

Filters are applied as query parameters: GET /findings?finding_type=scope_drift&severity=high&status=active.

5.2 Table

ColumnSource FieldSortable
Typefinding_typeYes
Severityseverity (badge)Yes
Entityentity_name (link)Yes
Detecteddetected_at (relative time)Yes (default: desc)
Statusstatus (badge)Yes
Affected Resourcesderived from evidenceNo

Row click navigates to /findings/:id.

5.3 Bulk Actions

Checkbox selection on rows enables bulk actions:

  • AcknowledgePATCH /findings/{id}/status with { status: "acknowledged" }
  • Mark False PositivePATCH /findings/{id}/status with { status: "false_positive", reason: "..." }

5.4 Pagination

Cursor-based pagination matching the API contract. Footer shows: "Showing 1-25 of {total_count}" with Next/Previous buttons.


6. Finding Detail Page (/findings/:id)

Purpose: Full finding context with evidence pack rendering and status workflow.

6.1 Header

  • Finding type badge (color-coded by type)
  • Severity badge (color-coded: critical=red, high=orange, medium=yellow, low=blue)
  • Status badge with transition dropdown
  • Entity name as link to /entities/:id
  • Detection timestamps: first detected, last updated

6.2 Deterministic Explanation

Full-width panel displaying deterministic_explanation text. This is the human-readable, no-inference explanation of the finding.

6.3 Evidence Completeness Report

Visual indicator for each evidence category:

CategoryAvailableUnavailablePartial
current_rolesGreen dotRed dot + reasonYellow dot + note
role_historyGreen dotRed dot + reasonYellow dot + note
execution_evidenceGreen dotRed dot + reasonYellow dot + note
ownership_recordsGreen dotRed dot + reasonYellow dot + note
approval_recordsGreen dotRed dot + reasonYellow dot + note
credential_stateGreen dotRed dot + reasonYellow dot + note

Source: evidence_completeness field on the finding (see 01-data-model.md).

Each category shows its EvidenceAvailability status and the corresponding note from evidence_completeness.notes.

Example rendering:

Evidence Completeness
* current_roles Available
* role_history Unavailable -- sys_audit_role not enabled in target instance
* execution_evidence Partial -- syslog_transaction accessible, retention window: 30d
* ownership_records Available
* approval_records Unavailable -- no approval system configured
* credential_state Available

6.4 Evidence Pack Viewer

Rendered from GET /findings/{id}/evidence-pack. The evidence pack contains structured sections:

SectionContent
Identity SummaryEntity properties, source system, creation date, status
Authority SnapshotCurrent roles, permissions, execution paths
Ownership TimelineOwner chain with status (active/decayed/departed), assignment dates
Blast RadiusMaterialized execution paths as a mini-graph (@xyflow/react subgraph)
RemediationRecommended actions from recommended_actions[]

Integrity badge: If the evidence pack includes a hash, display a verification indicator (checkmark if hash matches, warning if mismatch).

6.5 Status Workflow

Finding status transitions via PATCH /findings/{id}/status:

active -> acknowledged -> remediated
active -> false_positive
acknowledged -> active (reopen)
acknowledged -> remediated
acknowledged -> false_positive

Each transition requires:

  • acknowledged: optional acknowledged_by
  • remediated: required resolved_by, optional resolution_notes
  • false_positive: required reason

6.6 Actions

  • Export JSON: Download evidence pack as JSON file
  • Export Markdown: GET /findings/{id}/evidence-pack?format=markdown
  • Export PDF (Optional, post-MVP): Added as a separate phased enhancement using Markdown/HTML-to-PDF conversion

7. Entity Detail Page (/entities/:id)

Purpose: Complete view of a single entity — properties, graph context, timeline, ownership chain.

7.1 Tabs

TabContentAPI Endpoint
PropertiesKey-value display of entity fieldsGET /entities/{id}
GraphMini @xyflow/react showing 1-hop neighborhoodGET /entities/{id} (relationships)
TimelineChronological eventsGET /entities/{id}/timeline
OwnershipOwner chain with status indicatorsGET /entities/{id} (ownership edges)
FindingsFindings referencing this entityGET /findings?entity_id={id}

7.2 Properties Tab

Key-value table from entity properties object. Includes:

  • source_metadata fields (allowlisted subset — see 01-data-model.md Source Metadata Policy)
  • source_metadata_hash displayed as truncated hash with copy button
  • Credential summary (if entity is identity with credentials): credential type, status, expiry

7.3 Graph Tab

Mini @xyflow/react canvas (400px height) centered on the current entity. Shows:

  • The entity node (highlighted)
  • All directly connected nodes (1-hop)
  • Edges between them

Same Dagre layout, entity colors, and edge styles as the full Graph Explorer. Click on neighbor node navigates to that entity's detail page.

7.4 Timeline Tab

Chronological event list from GET /entities/{id}/timeline:

2026-02-07 14:30:22  role_assigned    HAS_ROLE -> admin_role    (sync: abc-123)
2026-02-06 09:15:00 entity_created sp-hr-onboarding (sync: abc-122)

Each event shows: timestamp, event type badge, description, sync reference link.

7.5 Ownership Tab

Owner chain visualization:

Primary Owners
* Alex Johnson (active) assigned 2025-11-01
o Sam Wilson (departed) decayed 2026-01-15, reason: "user disabled in IdP"

Secondary Owners
* Maria Garcia (active) assigned 2025-12-01

Inherited Owners
* IT Security Team (active) via: BELONGS_TO -> Engineering Dept

Status indicators: filled circle = active, empty circle = decayed/departed.


8. Temporal Comparison Page (/temporal)

Purpose: Side-by-side diff of an entity's state at two points in time.

8.1 Controls

  • Entity selector (search/autocomplete against GET /entities)
  • Two date pickers: "Before" (t1) and "After" (t2)
  • Compare button triggers GET /entities/{id}/diff?from={t1}&to={t2}

8.2 Diff Display

Side-by-side panels showing:

Change TypeVisual
Added relationshipGreen highlight, "+" prefix
Removed relationshipRed highlight, "-" prefix
Changed propertyYellow highlight, old -> new
Added execution pathGreen path in graph
Removed execution pathRed (dashed) path in graph

8.3 Graph Diff

Mini @xyflow/react canvas showing the union of both states:

  • Nodes present in both: normal rendering
  • Nodes added in t2: green border
  • Nodes removed in t2: red dashed border
  • Edges follow same added/removed coloring

9. Sync Management Page (/syncs)

Purpose: Monitor and trigger connector sync operations.

9.1 Sync List

Table of recent syncs from GET /syncs:

ColumnSource
Connector Typeconnector_type
Statusstatus (badge: completed/running/failed)
Startedstarted_at
Durationcomputed from started_at / completed_at
Entities Affectedmetrics.entities_affected
Events Createdmetrics.events_created

9.2 Sync Detail

Drill into GET /syncs/{id} for:

  • Sync metrics (audit_records_fetched, events_created, entities_affected, paths_recomputed)
  • Error log (if failed)
  • Evidence completeness report from the connector health check

9.3 Manual Trigger [Planned]

"Trigger Sync" button -> POST /syncs with source system selector. Confirmation dialog before executing. Requires the POST /syncs endpoint (see 04-api-layer.md).


9A. Execution Chains Page (/execution-chains) -- [Planned]

Purpose: List, filter, and explore execution chains — the typed paths from automation entry points through connections and credentials to destination identities and their authorized resources.

Status: [Planned] — This page is designed in ADR-008 but not yet implemented. The execution_chains collection and API endpoints are pending.

9A.1 Chain List

Table of execution chains from GET /api/v1/execution-chains:

ColumnSource FieldSortable
NamenameYes
Triggersummary.triggerYes
Destinationsummary.destinationYes
Egress Categorysummary.egress_category (badge)Yes
Ownershipsummary.ownership_status (badge)Yes
Max Sensitivitysummary.max_sensitivity (badge)Yes (default: desc)
Entitiesentity_refs.lengthYes
Last Seenlast_seen_atYes

9A.2 Chain Filters

FilterTypeValues
Egress CategoryDropdownidentity_provider, itsm, monitoring, unknown
Ownership StatusDropdownowned, orphaned, degraded
Max SensitivityDropdownpublic, internal, confidential, restricted
Blast Radius DomainMulti-selectDynamic from summary.blast_radius_domains

9A.3 Chain Detail

Drill into GET /api/v1/execution-chains/{id}:

  • Chain summary panel: trigger, destination, egress_category, ownership_status, total_roles, canonical_permissions
  • Entity chain graph: Mini @xyflow/react showing the chain's entity_refs as a linear graph with role labels on each node
  • Blast radius panel: Domains reachable via this chain with sensitivity levels
  • Composition hash: Displayed for change tracking (SHA256 fingerprint)
  • Temporal info: first_detected_at, last_seen_at, sync_version

10. Data Fetching Patterns

10.1 TanStack Query Hooks

All API calls wrapped in custom hooks using TanStack Query:

HookQuery KeyEndpointStatus
useEntity(id)['entities', id]GET /entities/{id}[Implemented]
useEntities(filters)['entities', filters]GET /entities[Implemented]
useEntityTimeline(id)['entities', id, 'timeline']GET /entities/{id}/timeline[Implemented]
useBlastRadius(id)['blast-radius', id]GET /identities/{id}/blast-radius[Implemented]
useAccessibleBy(id)['accessible-by', id]GET /resources/{id}/accessible-by[Implemented]
useCrossSystemPaths(id)['cross-system-paths', id]GET /identities/{id}/cross-system-paths[Implemented]
useFinding(id)['findings', id]GET /findings/{id}[Implemented]
useFindings(filters)['findings', filters]GET /findings[Implemented]
useEvidencePack(id)['evidence-pack', id]GET /findings/{id}/evidence-pack[Implemented]
useEntityDiff(id, t1, t2)['entities', id, 'diff', t1, t2]GET /entities/{id}/diff[Implemented]
useSyncs(filters)['syncs', filters]GET /syncs[Implemented]
useSync(id)['syncs', id]GET /syncs/{id}[Implemented]
useSubgraph(seedId, mode, depth)['subgraph', seedId, mode, depth]GET /graph/subgraph[Implemented]
useExecutionChains(filters)['execution-chains', filters]GET /execution-chains[Planned]
useExecutionChain(id)['execution-chains', id]GET /execution-chains/{id}[Planned]

10.2 Cache Strategy

  • Stale time: 30 seconds for entity/finding data (refreshed frequently during active use)
  • Cache time: 5 minutes (keep cached data for quick back-navigation)
  • Refetch on window focus: Enabled for findings and sync status

10.3 Cache Invalidation

Sync completion invalidates dependent queries:

On sync completed (detected via polling GET /syncs/{id}):
-> invalidate ['entities']
-> invalidate ['findings']
-> invalidate ['blast-radius']
-> invalidate ['accessible-by']
-> invalidate ['cross-system-paths']
-> invalidate ['subgraph']
-> invalidate ['execution-chains']

Finding status mutations invalidate:

On PATCH /findings/{id}/status:
-> invalidate ['findings', id]
-> invalidate ['findings'] (list may change)

10.4 Loading & Error States

Every data-fetching component handles three states:

  • Loading: Spinner with contextual message (e.g., "Loading graph data...")
  • Error: Red error panel with message and retry button
  • Empty: Contextual empty state (e.g., "No findings match your filters")

10.5 Pagination Integration

For paginated endpoints, hooks accept cursor parameters and expose navigation:

const { data, fetchNextPage, hasNextPage } = useFindings({
status: 'active',
limit: 25,
});
// data.cursor.next used for fetchNextPage
// data.cursor.has_more controls hasNextPage

11. Component Architecture

11.1 Shared Components

ComponentPurposeUsed ByStatus
EntityBadgeEntity type label with colorGraph, Findings, Entity Detail[Implemented]
FindingSeverityBadgeSeverity label (critical/high/medium/low)Findings List, Finding Detail, Dashboard[Implemented]
FindingTypeBadgeFinding type label with iconFindings List, Finding Detail[Implemented]
StatusIndicatorStatus dot + labelEntity Detail, Findings, Syncs[Implemented]
EvidenceCompletenessBarCategory availability visualFinding Detail[Implemented]
EntityNodeCustom @xyflow/react nodeGraph Explorer, Entity Detail graph tab, Finding blast radius[Implemented]
MiniGraphSmall @xyflow/react canvas (1-hop)Entity Detail, Finding Detail[Implemented]
TimelineEventSingle event rowEntity Timeline, Dashboard recent activity[Implemented]
CursorPaginationNext/Prev with count displayFindings List, Entity List, Syncs[Implemented]
DataTableEnterprise data table with server-side featuresEntities, Findings, Chains[Implemented]
AutomationNodeCustom node for automation entitiesGraph Explorer, Chain Detail[Planned]
ConnectionNodeCustom node for connection entitiesGraph Explorer, Chain Detail[Planned]
ChainCardExecution chain summary cardChain List, Dashboard[Planned]

11.2 File Structure

src/ui/
├── App.tsx # Router setup
├── Layout.tsx # Navbar + sidebar + outlet
├── api.ts # API client functions
├── hooks/ # TanStack Query hooks
│ ├── useEntity.ts
│ ├── useFindings.ts
│ ├── useBlastRadius.ts
│ ├── useSyncs.ts
│ └── ...
├── pages/
│ ├── DashboardPage.tsx
│ ├── GraphExplorerPage.tsx
│ ├── FindingsPage.tsx
│ ├── FindingDetailPage.tsx
│ ├── EntityDetailPage.tsx
│ ├── EntitiesListPage.tsx # [Implemented]
│ ├── AutomationsPage.tsx # [Implemented]
│ ├── AutomationDetailPage.tsx # [Implemented]
│ ├── TemporalComparePage.tsx
│ ├── SyncsPage.tsx
│ └── ExecutionChainsPage.tsx # [Planned]
├── components/
│ ├── graph/
│ │ ├── GraphCanvas.tsx
│ │ ├── EntityNode.tsx
│ │ ├── MiniGraph.tsx
│ │ ├── GraphLegend.tsx
│ │ ├── GraphFilterSidebar.tsx
│ │ ├── GraphNodeDetailsDrawer.tsx
│ │ ├── AutomationNode.tsx # [Planned]
│ │ ├── ConnectionNode.tsx # [Planned]
│ │ └── layout.ts # Dagre layout config
│ ├── findings/
│ │ ├── EvidenceCompletenessBar.tsx
│ │ ├── EvidencePackViewer.tsx
│ │ └── StatusWorkflow.tsx
│ ├── chains/ # [Planned]
│ │ ├── ChainCard.tsx
│ │ ├── ChainGraph.tsx
│ │ └── ChainFilters.tsx
│ ├── shared/
│ │ ├── EntityBadge.tsx
│ │ ├── FindingSeverityBadge.tsx
│ │ ├── StatusIndicator.tsx
│ │ ├── CursorPagination.tsx
│ │ └── TimelineEvent.tsx
│ ├── table/
│ │ ├── DataTable.tsx # [Implemented]
│ │ ├── DataTableFilters.tsx # [Implemented]
│ │ └── DataTablePagination.tsx # [Implemented]
│ └── temporal/
│ ├── DiffDisplay.tsx
│ └── GraphDiff.tsx
└── types/
└── api.ts # Response type definitions

12. Export & Reporting

12.1 Evidence Pack Export

Evidence packs are the primary reporting artifact. Export formats:

FormatMethodUse Case
JSONGET /findings/{id}/evidence-packMachine-readable, API consumers
MarkdownGET /findings/{id}/evidence-pack?format=markdownHuman-readable, email-friendly
PDF (post-MVP optional)Separate phased add-on (Markdown/HTML-to-PDF conversion)Formal reports, compliance attachments

MVP priority is JSON and Markdown export. PDF is not required for v0.2; if enabled later, it should be generated from Markdown/HTML via a dedicated conversion step.

12.2 Entity List Export

CSV export from the findings list or entity queries:

  • User applies filters on findings or entity list page
  • "Export CSV" button serializes current result set
  • Client-side CSV generation (no server endpoint needed for MVP)
  • Columns match the visible table columns

12.3 Graph Snapshot

PNG export of the current graph view:

  • "Export PNG" button on Graph Explorer toolbar
  • Client-side capture via html2canvas or @xyflow/react's built-in toImage() method
  • Captures current viewport (zoom level, filters applied)

13. MVP Exclusions

The following are explicitly out of scope for MVP:

FeatureRationale
Reporting templatesCustom report builder adds complexity without MVP value
Mobile responsivenessDesktop-first for security analysts
Real-time WebSocket updatesPolling sync status is sufficient at MVP scale
Admin / settings pagesConfiguration via environment variables for MVP
User role management UISingle-tenant, single-role for MVP
Dark modeCosmetic, not functional
Custom dashboardsFixed dashboard layout sufficient for MVP
Scheduled report deliveryManual export covers MVP needs
Native PDF evidence-pack exportDeferred. Optional post-MVP phase using Markdown/HTML-to-PDF conversion
GraphQLREST API covers all MVP query patterns
Webhooks / subscriptionsPolling is sufficient at MVP sync frequency

14. Cross-Reference Summary

This DocumentReferences
§4 Graph Explorer layout rationale00-overview.md §9
§2-§9A All API endpoints04-api-layer.md
§3.2 Entity statistics (9-type model)ADR-006
§4.3 Edge styling (typed execution edges)ADR-007
§9A Execution chains pageADR-008
§6.3 Evidence completeness categories01-data-model.md EvidenceAvailability
§6.4 Evidence pack structure01-data-model.md Finding schema
§7.2 Source metadata policy01-data-model.md Source Metadata Policy
§4.3 Entity type colors, node sizesImplemented in src/ui/components/graph/EntityNode.tsx
§4.3 Dagre configImplemented in src/ui/components/graph/layout.ts