feat(docs): Add comprehensive documentation for Vexer, Vulnerability Explorer, and Zastava modules
- Introduced AGENTS.md, README.md, TASKS.md, and implementation_plan.md for Vexer, detailing mission, responsibilities, key components, and operational notes. - Established similar documentation structure for Vulnerability Explorer and Zastava modules, including their respective workflows, integrations, and observability notes. - Created risk scoring profiles documentation outlining the core workflow, factor model, governance, and deliverables. - Ensured all modules adhere to the Aggregation-Only Contract and maintain determinism and provenance in outputs.
This commit is contained in:
		
							
								
								
									
										366
									
								
								docs/modules/ui/architecture.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										366
									
								
								docs/modules/ui/architecture.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,366 @@ | ||||
| # component_architecture_web_ui.md — **Stella Ops Web UI** (2025Q4) | ||||
|  | ||||
| > Consolidates Console requirements documented across the Policy, Graph, Vulnerability Explorer, Advisory AI, Orchestrator, and Notifications module guides and implementation plans. | ||||
|  | ||||
| > **Scope.** Implementation‑ready architecture for the **Angular SPA** that operators and developers use to drive Stella Ops. This document defines UX surfaces, module boundaries, data flows, auth, RBAC, real‑time updates, performance targets, i18n/a11y, security headers, testing and deployment. The UI is a *consumer* of backend APIs (Scanner, Policy, Excititor, Concelier, Attestor, Authority) and never performs scanning, merging, or signing on its own. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 0) Mission & non‑goals | ||||
|  | ||||
| **Mission.** Provide a **fast, explainable** console for: | ||||
|  | ||||
| * Scans (status, SBOMs, diffs, EntryTrace, attestation). | ||||
| * Policy management (rules, exemptions, VEX consumption view). | ||||
| * Vulnerability intel (Concelier status), VEX consensus exploration (Excititor). | ||||
| * Runtime posture (Zastava observer + admission). | ||||
| * Admin operations (tenants, tokens, quotas, licensing posture). | ||||
|  | ||||
| **Non‑goals.** No client‑side crypto signing; no Docker/CRI access; no direct registry access beyond fetching static assets or OCI referrer summaries exposed by backend. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 1) Technology baseline | ||||
|  | ||||
| * **Framework**: Angular 17+ (Stand‑alone APIs / Signals), TypeScript 5. | ||||
| * **Styling**: Tailwind CSS + headless component patterns; CSS variables for theming. | ||||
| * **Charts**: Lightweight SVG (uPlot or Apache ECharts via on‑demand import). | ||||
| * **State**: Angular **Signals** + `@ngrx/signals` store for cross‑page slices. | ||||
| * **Transport**: `fetch` + RxJS interop; **SSE** (EventSource) for progress streams. | ||||
| * **Build**: Angular CLI + Vite builder. | ||||
| * **Testing**: Jest + Testing Library, Playwright for e2e. | ||||
| * **Packaging**: Containerized NGINX (immutable assets, ETag + content hashing). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 2) High‑level module map | ||||
|  | ||||
| ``` | ||||
| /app | ||||
|  ├─ core/                 # bootstrap, config, auth, http, error boundary, i18n | ||||
|  ├─ shared/               # UI kit (tables, code-viewers, badges), pipes | ||||
|  ├─ dashboard/            # live tiles, fleet KPIs, feed/vex age, queue depth | ||||
|  ├─ scans/                # scan list, detail, SBOM viewer, diff-by-layer, EntryTrace | ||||
|  ├─ runtime/              # Zastava posture, drift events, admission decisions | ||||
|  ├─ policy/               # rules editor (YAML/Rego), exemptions, previews | ||||
|  ├─ vex/                  # VEX explorer (claims, consensus, conflicts) | ||||
|  ├─ concelier/              # source health, export cursors, rebuild/export triggers | ||||
|  ├─ attest/               # attestation proofs, verification bundles, Rekor links | ||||
|  ├─ admin/                # tenants, roles, clients, quotas, licensing posture | ||||
|  └─ plugins/              # route plug-ins (lazy remote modules, governed) | ||||
| ``` | ||||
|  | ||||
| Each feature folder builds as a **standalone route** (lazy loaded). All HTTP shapes live in `core/api/` clients with shared DTOs. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 3) Navigation & key views | ||||
|  | ||||
| ### 3.1 Dashboard | ||||
|  | ||||
| * **Tiles**: “New criticals (24h)”, “VEX suppressions applied”, “Attested SBOMs (7d)”, “Feed age per provider”, “Scanner queue depth”, “Admission events”. | ||||
| * **Trends**: sparkline for vulns/day, pass/fail rates, attestation throughput. | ||||
|  | ||||
| ### 3.2 Scans | ||||
|  | ||||
| * **Scan list** with status, image digest, repo, time, artifacts, attestation badge. | ||||
| * **Scan detail**: | ||||
|  | ||||
|   * **SBOM viewer**: Inventory/Usage toggle; component table (virtualized), filters by package type, severity, source. | ||||
|   * **Diff by layer**: A→B change grid (added/removed/upgraded), grouped by introducing/removing layer; tooltips show provenance and links to layer SBOM fragment. | ||||
|   * **EntryTrace**: shell chain with file:line breadcrumbs; jump‑to source viewer (read‑only, hexdump fallback). | ||||
|   * **Attestation**: Rekor UUID, index, inclusion proof; **Verify** button calls Attestor `/verify`. | ||||
|   * **Export**: download buttons (CycloneDX JSON, Protobuf, SPDX JSON); size shown; SHA‑256 inline. | ||||
|  | ||||
| ### 3.3 Runtime (Zastava) | ||||
|  | ||||
| * **Observer timeline**: container start/stop, drift, policy violations; faceted by namespace/owner. | ||||
| * **Live process view**: top N processes, loaded libs summary vs Usage SBOM. | ||||
| * **Admission decisions**: per‑namespace rules, allow/deny events, cache TTL, reasons. | ||||
|  | ||||
| ### 3.4 Policy | ||||
|  | ||||
| * **Policy bundles**: active vs staged; diff viewer with change summary. | ||||
| * **Editors**: | ||||
|  | ||||
|   * YAML rules (ignore lists, thresholds, vendor precedence overrides). | ||||
|   * Rego blocks (advanced gates) with **WASM** preview evaluator (client‑side sandbox) for “preview” against sample SBOMs. | ||||
| * **VEX inclusion controls**: weight sliders (visualization only), provider allow/deny toggles. | ||||
| * **Preview**: select SBOM (or image digest) → show verdict under staged policy. | ||||
|  | ||||
| ### 3.5 Excititor | ||||
|  | ||||
| * **Claims explorer**: search by vulnId/productKey/provider; show raw claim (status, justification, evidence). | ||||
| * **Consensus view**: rollup per (vuln, product) with accepted/rejected sources, weights, timestamps. | ||||
| * **Conflicts**: grid of top conflicts; filters for justification gates failed. | ||||
|  | ||||
| ### 3.6 Concelier | ||||
|  | ||||
| * **Sources** table: staleness, last run, errors. | ||||
| * **Advisory search**: by CVE/alias; show normalized affected ranges. | ||||
| * **Exports**: trigger full/delta JSON/Trivy DB; show manifest digests and Rekor link if attested. | ||||
|  | ||||
| ### 3.7 Attest | ||||
|  | ||||
| * **Proofs list**: last 7 days Rekor entries; filter by kind (sbom/report/vex). | ||||
| * **Verification**: paste UUID or upload bundle → verify; result with explanations (chain, Merkle path). | ||||
|  | ||||
| ### 3.8 Admin | ||||
|  | ||||
| * **Tenants/Installations**: view/edit, isolation hints. | ||||
| * **Clients & roles**: Authority clients, role→scope mapping, rotation hints. | ||||
| * **Quotas**: per license plan, counters, throttle events. | ||||
| * **Licensing posture**: last PoE introspection snapshot (redacted), release window. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 4) Auth, sessions & RBAC | ||||
|  | ||||
| ### 4.1 OIDC flow | ||||
|  | ||||
| * **Authorization Code + PKCE** to **Authority**. | ||||
| * **ID Token** for UX identity; **Access Token** (OpTok) for APIs (2–5 min TTL). | ||||
| * **DPoP (browser)**: generate ephemeral **WebCrypto** keypair; store public JWK in memory, private key in **IndexedDB** (non‑exportable if platform allows). Access token includes `cnf.jkt`; each API call adds `DPoP` proof; handle nonce challenges automatically. | ||||
| * **Refresh**: optional DPoP‑bound refresh tokens with rotation; otherwise silent renew. | ||||
|  | ||||
| ### 4.2 RBAC | ||||
|  | ||||
| * Roles (`ui.read`, `ui.admin`, plus service roles) are embedded in ID token or fetched via `/me` endpoint. | ||||
| * **Route guards** enforce access; **feature flags** hide admin pages for non‑admins. | ||||
|  | ||||
| ### 4.3 Session storage | ||||
|  | ||||
| * Access tokens & refresh metadata in memory; persist **only** minimal session (subject, expiries) in `sessionStorage`. Never persist raw JWTs to `localStorage`. Use **SameSite=Lax** cookies for anti‑CSRF if cookies are required (prefer pure bearer headers + DPoP). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 5) HTTP layer & API clients | ||||
|  | ||||
| * **`core/http/api-client.ts`** centralizes: | ||||
|  | ||||
|   * Base URLs (Scanner, Excititor, Concelier, Attestor). | ||||
|   * **Retry** policies on idempotent GETs (backoff + jitter). | ||||
|   * **Problem+JSON** parser → uniform error toasts with correlation ID. | ||||
|   * **SSE** helper (EventSource) with auto‑reconnect & backpressure. | ||||
|   * **DPoP** injector & nonce handling. | ||||
|  | ||||
| * Typed API clients (DTOs in `core/api/models.ts`): | ||||
|  | ||||
|   * `ScannerApi`, `PolicyApi`, `ExcititorApi`, `ConcelierApi`, `AttestorApi`, `AuthorityApi`. | ||||
|  | ||||
| **DTO examples (abbrev):** | ||||
|  | ||||
| ```ts | ||||
| export type ImageDigest = `sha256:${string}`; | ||||
| export interface ScanSummary { | ||||
|   imageDigest: ImageDigest; createdAt: string; | ||||
|   artifacts: { view: 'inventory'|'usage'; format: 'cdx-json'|'cdx-pb'|'spdx-json'; sha256: string; size: number }[]; | ||||
|   status: 'queued'|'running'|'completed'|'error'; | ||||
|   rekor?: { uuid: string; index?: number; url?: string }; | ||||
| } | ||||
| export interface DiffEntry { | ||||
|   key: string; change: 'added'|'removed'|'upgraded'|'downgraded'; | ||||
|   fromVersion?: string; toVersion?: string; layer: string; usedByEntrypoint?: boolean; | ||||
| } | ||||
| export interface VexConsensus { | ||||
|   vulnId: string; productKey: string; rollupStatus: 'affected'|'not_affected'|'fixed'|'under_investigation'; | ||||
|   sources: { providerId: string; status: string; weight: number; accepted: boolean; reason: string }[]; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| *Upcoming:* `NotifyApi` consumes delivery history using the new paginated envelope returned by `/api/v1/notify/deliveries`. | ||||
|  | ||||
| ```ts | ||||
| export interface NotifyDeliveryListResponse { | ||||
|   items: NotifyDelivery[]; | ||||
|   count: number; | ||||
|   continuationToken?: string; | ||||
| } | ||||
|  | ||||
| export interface NotifyDelivery { | ||||
|   deliveryId: string; | ||||
|   ruleId: string; | ||||
|   actionId: string; | ||||
|   status: 'pending'|'sent'|'failed'|'throttled'|'digested'|'dropped'; | ||||
|   rendered: NotifyDeliveryRendered; | ||||
|   metadata: Record<string, string>; // includes channelType, target, previewProvider, traceId, and provider-specific entries | ||||
|   createdAt: string; | ||||
|   sentAt?: string; | ||||
|   completedAt?: string; | ||||
| } | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 6) State, caching & real‑time | ||||
|  | ||||
| * **Per‑page stores** (Signals) for list filters, pagination, and selected entities. | ||||
| * **Normalized caches** keyed by `(imageDigest, view, format)`; artifacts are downloaded via pre‑signed URLs from Scanner and streamed; SHA‑256 verified client‑side before exposing “verified” badge. | ||||
| * **SSE channels**: | ||||
|  | ||||
|   * `/scans/{id}/events` → progress log. | ||||
|   * `/runtime/events/stream` (optional) → live drift/admission feed (rate‑limited). | ||||
| * **Cache invalidation** on job completion or explicit “refresh”. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 7) SBOM viewing & diff UX | ||||
|  | ||||
| * **Huge tables** rendered with **virtual scrolling** (CDK Virtual Scroll); sort/filter performed client‑side for ≤ 20k rows; beyond that, server‑side queries via BOM‑Index endpoints. | ||||
| * **Component row** shows purl, version, origin (OS pkg / metadata / linker / attested), licenses, and **used** badge (Usage view). | ||||
| * **Diff**: compact heatmap per layer; clicking opens a right‑pane with evidence: introducing paths, file hashes, VEX notes (from Excititor consensus) and links to advisories (Concelier). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 8) Policy editor & VEX integration | ||||
|  | ||||
| * **YAML editor**: Monaco‑based with schema hints; previews show which rules matched. | ||||
| * **Rego editor**: Monaco with WASM‑OPA sandbox for read‑only evaluation on sample SBOMs. | ||||
| * **VEX toggles**: per‑provider enable/disable; “explain” drawer shows why a claim was accepted/rejected (justification gate, signature state, weight). | ||||
| * **Staged → Active** promotion is a two‑step flow with confirmation and automatic policy digest computation. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 9) Accessibility, i18n & theming | ||||
|  | ||||
| * **A11y**: WCAG 2.2 AA; keyboard navigation, focus management, ARIA roles; color‑contrast tokens verified by unit tests. | ||||
| * **I18n**: Angular i18n + runtime translation loader (`/locales/{lang}.json`); dates/numbers localized via `Intl`. | ||||
| * **Languages**: English default; Bulgarian, German, Japanese as initial additions. | ||||
| * **Theming**: dark/light via CSS variables; persisted in `prefers-color-scheme` aware store. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 10) Performance budgets | ||||
|  | ||||
| * **TTI** ≤ 1.5 s on 4G/slow CPU (first visit), ≤ 0.6 s repeat (HTTP/2, cached). | ||||
| * **JS** initial < 300 KB gz (lazy routes). | ||||
| * **SBOM list**: render 10k rows in < 70 ms with virtualization; filter in < 150 ms. | ||||
| * **Diff view**: compute client‑side grouping for 5k changes in < 120 ms. | ||||
|  | ||||
| Techniques: route‑level code splitting; `ChangeDetectionStrategy.OnPush`; Signals; server compression (zstd/gzip), immutable assets with long max‑age (cache busting via hashes). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 11) Security headers & CSP | ||||
|  | ||||
| * **CSP**: `default-src 'self'; connect-src 'self' https://*.internal; img-src 'self' data:; script-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'none';` | ||||
| * **HSTS** enabled at gateway. | ||||
| * **Referrer Policy**: `no-referrer`. | ||||
| * **X‑Frame‑Options**: `DENY`. | ||||
| * **COOP/COEP** to enable faster cross‑origin isolation (for WASM OPA). | ||||
| * **Subresource Integrity (SRI)** for third‑party fonts (minimize third‑party). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 12) Error handling & UX hygiene | ||||
|  | ||||
| * **Global error boundary** surfaces Problem+JSON `title/detail/instance` with correlation ID. | ||||
| * **Retry toast** for 429 (quota throttles) with backoff timer. | ||||
| * **Auth expiry**: pre‑emptive refresh; unobtrusive banner when < 60 s TTL; re‑login modal if refresh fails. | ||||
| * **Network down**: offline banner with queued actions (idempotent resubmits). | ||||
| * **File verify**: show SHA‑256 mismatch warnings if artifact altered in transit. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 13) Observability | ||||
|  | ||||
| * **Front‑end telemetry** (OpenTelemetry Web): route timings, API latency by service, error counts; sampled to 1–5% and shipped to backend OTLP endpoint. | ||||
| * **User actions** logged anonymously (no PII): “policy promote”, “scan export”, “attest verify”. | ||||
| * **Metrics dash** in admin shows SLOs and recent front‑end errors. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 14) Testing strategy | ||||
|  | ||||
| * **Unit**: pure component logic via Jest + Testing Library (no TestBed when possible). | ||||
| * **Component harness** for table, code viewer, diff heatmap. | ||||
| * **Contract tests**: OpenAPI schemas pulled at build time; DTOs validated; breaking changes fail CI. | ||||
| * **e2e**: Playwright scenarios (login, scan detail, diff, policy edit, admit deny). | ||||
| * **A11y**: axe-core CI checks; color‑contrast lints. | ||||
| * **i18n**: key coverage tests (no missing translations in supported locales). | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 15) Deployment & ops | ||||
|  | ||||
| * **Container**: `stellaops/web-ui:<ver>-<rev>`; NGINX with `gzip_static` + brotli; immutable assets under `/static/<hash>/…`. | ||||
| * **Config**: `/config.json` served by gateway (injected at runtime): API base URLs, authority issuer, telemetry sampling. | ||||
| * **Version banner**: footer shows UI & backend versions; warns on major mismatches. | ||||
| * **CDN** (optional): cache static bundle; APIs stay behind internal gateway. | ||||
| * **Feature flags**: environment gates (staged policies, eBPF runtime) readable from config. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 16) Plugin system (route plug‑ins) | ||||
|  | ||||
| * **Manifest**: Backend provides a signed plug‑in manifest with remote module URLs and **cosign signature** per JS bundle. | ||||
| * **Loader**: dynamic import with **SRI** and signature verification (WebCrypto). | ||||
| * **Sandbox**: plug‑ins are routed modules receiving a limited **UI SDK** (navigation, theme, API gateway). No direct token access; API calls proxied through the UI SDK which enforces RBAC. | ||||
| * **Examples**: custom reports, vendor dashboards, regulated TLS config UIs. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 17) Wire sequences (representative) | ||||
|  | ||||
| **A) View scan progress** | ||||
|  | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   participant UI | ||||
|   participant Auth as Authority | ||||
|   participant SW as Scanner.WebService | ||||
|  | ||||
|   UI->>Auth: /authorize (PKCE) | ||||
|   Auth-->>UI: code → token (DPoP-bound) | ||||
|   UI->>SW: GET /scans/{id} (Authorization+DPoP) | ||||
|   SW-->>UI: { status: running } | ||||
|   UI->>SW: (SSE) GET /scans/{id}/events | ||||
|   SW-->>UI: progress events … | ||||
|   SW-->>UI: terminal event { status: completed, artifacts[] } | ||||
| ``` | ||||
|  | ||||
| **B) Verify attestation** | ||||
|  | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   participant UI | ||||
|   participant AT as Attestor | ||||
|   UI->>AT: POST /rekor/verify { uuid } | ||||
|   AT-->>UI: { ok:true, index, logURL } | ||||
| ``` | ||||
|  | ||||
| **C) Promote policy & preview** | ||||
|  | ||||
| ```mermaid | ||||
| sequenceDiagram | ||||
|   autonumber | ||||
|   participant UI | ||||
|   participant BE as Scanner.WebService (Policy endpoint) | ||||
|   UI->>BE: POST /policy/stage { yaml, rego } | ||||
|   BE-->>UI: { policyRevision, diagnostics } | ||||
|   UI->>BE: POST /policy/preview { imageDigest, policyRevision } | ||||
|   BE-->>UI: { verdict: pass|fail, reasons[] } | ||||
|   UI->>BE: POST /policy/promote { policyRevision } | ||||
|   BE-->>UI: { ok:true } | ||||
| ``` | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 18) Security hard lines | ||||
|  | ||||
| * Never store JWTs in `localStorage`. | ||||
| * Enforce DPoP for API calls; if DPoP unsupported for a service, require **SameSite=Lax** cookies with CSRF token header. | ||||
| * Block mixed‑content; only HTTPS origins allowed. | ||||
| * Validate and render only **escaped** user content; code viewer uses safe highlighter. | ||||
| * Downloaded artifacts are treated as **opaque binaries**; no HTML rendering. | ||||
|  | ||||
| --- | ||||
|  | ||||
| ## 19) Roadmap | ||||
|  | ||||
| * **PWA** offline shell (read‑only) for dashboards and cached scan details. | ||||
| * **SBOM graph** visualization (force‑directed) for small components sets. | ||||
| * **Runtime session replay** (privacy‑safe) to debug operator workflows (opt‑in). | ||||
| * **Assistive wizards** for policy creation with guided templates. | ||||
		Reference in New Issue
	
	Block a user