211 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| # StellaOps Console Architecture (Sprint 23)
 | ||
| 
 | ||
| > **Ownership:** Console Guild • Docs Guild  
 | ||
| > **Delivery scope:** `StellaOps.Web` Angular workspace, Console Web Gateway routes (`/console/*`), Downloads manifest surfacing, SSE fan-out for Scheduler & telemetry.  
 | ||
| > **Related docs:** [Console overview](../ui/console-overview.md), [Navigation](../ui/navigation.md), [Runs workspace](../ui/runs.md), [Downloads](../ui/downloads.md), [Console security posture](../security/console-security.md), [Console observability](../observability/ui-telemetry.md), [Deployment guide](../deploy/console.md)
 | ||
| 
 | ||
| This dossier describes the end-to-end architecture of the StellaOps Console as delivered in Sprint 23. It covers the Angular workspace layout, API/gateway integration points, live-update channels, performance budgets, offline workflows, and observability hooks needed to keep the console deterministic and air-gap friendly.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 1 · Mission & Boundaries
 | ||
| 
 | ||
| - Present an operator-grade UI that surfaces Concelier, Excititor, Policy Engine, Scheduler, Attestor, and SBOM Service data **without** mutating aggregation or policy state.  
 | ||
| - Enforce Authority-issued scopes and tenant claims on every call through the Console Web Gateway.  
 | ||
| - Deliver deterministic builds (< 1 MB initial bundle) that can be mirrored in Offline Kits, with runtime configuration loaded from `/config.json`.  
 | ||
| - Stream live status (ingestion deltas, scheduler progress, telemetry) via SSE with graceful degradation to polling when offline or throttled.  
 | ||
| - Maintain CLI parity by embedding `stella` commands alongside interactive actions.
 | ||
| 
 | ||
| Non-goals: authoring ingestion logic, mutating Policy overlays, exposing internal Mongo collections, or performing cryptographic signing in-browser.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 2 · Workspace & Packages
 | ||
| 
 | ||
| The console is implemented in `src/Web/StellaOps.Web`, an Angular 17 workspace built on standalone components and Signals.
 | ||
| 
 | ||
| | Path | Purpose | Highlights |
 | ||
| |------|---------|------------|
 | ||
| | `src/app/core/auth` | DPoP + PKCE authentication, Authority session store, HTTP interceptors. | WebCrypto keygen (`crypto.subtle`), session metadata persisted in `sessionStorage`, DPoP nonce replay guard. |
 | ||
| | `src/app/core/api` | Typed API clients for Console gateway (`/console/*`) and downstream services. | DTOs for Scanner, Notify, Concelier exporters; fetch-based clients with abort signals. |
 | ||
| | `src/app/core/config` | Runtime configuration loader (`/config.json`), feature flag gating. | Supports air-gap overrides and injects API base URLs, Authority issuer/client. |
 | ||
| | `src/app/features/*` | Route-level shells (auth bootstrap, scans detail, notifications inbox, Trivy DB settings). | Each feature is a standalone module with lazy loading and Angular Signals state. |
 | ||
| | `src/app/testing` | Fixtures and harnesses used in unit tests and storybook-like previews. | Deterministic data used for Playwright and Jest scenarios. |
 | ||
| 
 | ||
| Workspace characteristics:
 | ||
| 
 | ||
| - **Toolchain:** Node 20.11+, npm 10.2+, Angular CLI 17.3. `npm run ci:install` primes dependencies without network audits; `scripts/verify-chromium.js` ensures headless Chromium availability for Karma.  
 | ||
| - **Build budgets:** `angular.json` enforces 500 KB warning / 1 MB error for initial bundle and 2 KB warning / 4 KB error per component stylesheet. Output hashing (`outputHashing: all`) keeps assets cache-safe.  
 | ||
| - **Testing:** Karma + Jasmine for unit tests, Playwright for e2e with dev server autotuning. CI (`DEVOPS-CONSOLE-23-001`) runs Lighthouse against the production bundle.  
 | ||
| - **Runtime config:** `/config.json` merged at bootstrap; gateways can rewrite it on the fly to avoid rebuilding for environment changes.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 3 · Runtime Topology & Data Flow
 | ||
| 
 | ||
| The console SPA relies on the Console Web Gateway to proxy tenant-scoped API calls to downstream services. Tenant isolation and Aggregation-Only guardrails are enforced at every hop.
 | ||
| 
 | ||
| ```mermaid
 | ||
| graph TD
 | ||
|     subgraph Browser["Browser (Angular SPA)"]
 | ||
|         UI[Console Shell<br/>(Signals, Feature Modules)]
 | ||
|         SSE[EventSource / SSE Clients]
 | ||
|     end
 | ||
|     subgraph Gateway["Console Web Gateway"]
 | ||
|         Router[Minimal API / ASP.NET Core Router]
 | ||
|         StatusCache[Status Cache & Manifest signer]
 | ||
|     end
 | ||
|     Authority[Authority<br/>(DPoP + PKCE)]
 | ||
|     Concelier[Concelier.WebService]
 | ||
|     Excititor[Excititor.WebService]
 | ||
|     Scheduler[Scheduler.WebService]
 | ||
|     Policy[Policy Engine API]
 | ||
|     SBOM[SBOM Service]
 | ||
|     Attestor[Attestor API]
 | ||
|     Downloads[Downloads Manifest Store]
 | ||
| 
 | ||
|     UI -->|/config.json| Gateway
 | ||
|     UI -->|/console/* (Bearer+DPoP)| Router
 | ||
|     SSE -->|/console/status/stream| Router
 | ||
|     Router --> Authority
 | ||
|     Router --> Concelier
 | ||
|     Router --> Excititor
 | ||
|     Router --> Scheduler
 | ||
|     Router --> Policy
 | ||
|     Router --> SBOM
 | ||
|     Router --> Attestor
 | ||
|     Router --> Downloads
 | ||
|     StatusCache -.-> Gateway
 | ||
|     Gateway -.-> UI
 | ||
| ```
 | ||
| 
 | ||
| Key interactions:
 | ||
| 
 | ||
| - **Auth bootstrap:** UI retrieves Authority metadata and exchanges an authorization code + PKCE verifier for a DPoP-bound token (`aud=console`, `tenant=<id>`). Tokens expire in 120 s; refresh tokens rotate, triggering new DPoP proofs.  
 | ||
| - **Tenant switch:** Picker issues `Authority /fresh-auth` when required, then refreshes UI caches (`ui.tenant.switch` log). Gateway injects `X-Stella-Tenant` headers downstream.  
 | ||
| - **Aggregation-only reads:** Gateway proxies `/console/advisories`, `/console/vex`, `/console/findings`, etc., without mutating Concelier or Policy data. Provenance badges and merge hashes come directly from upstream responses.  
 | ||
| - **Downloads parity:** `/console/downloads` merges DevOps signed manifest and Offline Kit metadata; UI renders digest, signature, and CLI parity command.  
 | ||
| - **Offline resilience:** Gateway exposes `/console/status` heartbeat. If unavailable, UI enters offline mode, disables SSE, and surfaces CLI fallbacks.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 4 · Live Updates & SSE Design
 | ||
| 
 | ||
| Live surfaces use HTTP/1.1 SSE with heartbeat frames to keep operators informed without polling storms.
 | ||
| 
 | ||
| | Endpoint | Payload | Source | Behaviour |
 | ||
| |----------|---------|--------|-----------|
 | ||
| | `/console/status/stream` | `statusChanged`, `ingestionDelta`, `attestorQueue`, `offlineBanner` events | Concelier WebService, Excititor WebService, Attestor metrics | 5 s heartbeat; gateway disables proxy buffering (`X-Accel-Buffering: no`) and sets `Cache-Control: no-store`. |
 | ||
| | `/console/runs/{id}/stream` | `stateChanged`, `segmentProgress`, `deltaSummary`, `log` | Scheduler WebService SSE fan-out | Event payloads carry `traceId`, `runId`, `tenant`; UI reconnects with exponential backoff and resumes using `Last-Event-ID`. |
 | ||
| | `/console/telemetry/stream` | `metricSample`, `alert`, `collectorStatus` | Observability aggregator | Gated by `ui.telemetry` scope; disabled when `CONSOLE_TELEMETRY_SSE_ENABLED=false`. |
 | ||
| 
 | ||
| Sequence overview:
 | ||
| 
 | ||
| ```mermaid
 | ||
| sequenceDiagram
 | ||
|     autonumber
 | ||
|     participant UI as Console SPA
 | ||
|     participant GW as Console Gateway
 | ||
|     participant SCHED as Scheduler WebService
 | ||
| 
 | ||
|     UI->>GW: GET /console/runs/42/stream (Authorization + DPoP)
 | ||
|     GW->>SCHED: GET /runs/42/stream (X-Stella-Tenant)
 | ||
|     SCHED-->>GW: event: stateChanged data: {...}
 | ||
|     GW-->>UI: event: stateChanged data: {..., traceId}
 | ||
|     Note over UI,GW: Gateway injects retry-after + heartbeat every 15s
 | ||
|     UI-->>GW: (disconnect)
 | ||
|     UI->>GW: GET /console/runs/42/stream (Last-Event-ID: <seq>)
 | ||
|     GW->>SCHED: GET /runs/42/stream?since=<seq>
 | ||
| ```
 | ||
| 
 | ||
| Offline behaviour:
 | ||
| 
 | ||
| - If SSE fails three times within 60 s, UI falls back to polling (`/console/status`, `/console/runs/{id}`) every 30 s and shows an amber banner.  
 | ||
| - When `console.offlineMode=true`, SSE endpoints return `204` immediately; UI suppresses auto-reconnect to preserve resources.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 5 · Performance & Budgets
 | ||
| 
 | ||
| | Surface | Target | Enforcement |
 | ||
| |---------|--------|-------------|
 | ||
| | First meaningful paint (dashboard) | ≤ 2.5 s on 4 vCPU offline runner | Lighthouse CI gate (`DEVOPS-CONSOLE-23-001`), `ui_route_render_seconds` P95 alert. |
 | ||
| | Route hydration (feature shells) | ≤ 1.5 s after token acquisition | Angular Signals + lazy loading; route-level budgets tracked via custom telemetry. |
 | ||
| | Initial bundle size | Warn ≥ 500 KB, fail ≥ 1 MB | `angular.json` budgets; CI fails build on overflow. |
 | ||
| | Component stylesheet | Warn ≥ 2 KB, fail ≥ 4 KB | `angular.json` budgets; ensures Tailwind utilities stay tree-shaken. |
 | ||
| | SSE heartbeat | Every 15 s max | Gateway emits comment heartbeats; UI resets timers on each frame. |
 | ||
| 
 | ||
| Optimisation levers:
 | ||
| 
 | ||
| - Standalone components with `ChangeDetectionStrategy.OnPush` and Angular Signals avoid zone.js churn.  
 | ||
| - `fetch` + AbortController guard double fetches.  
 | ||
| - Assets served with immutable caching (`cache-control: public, max-age=31536000, immutable`) thanks to hashed filenames.  
 | ||
| - Compression (gzip/brotli) enabled at gateway; offline bundles include precompressed assets.  
 | ||
| - Command palette, tenants, and filters rely on IndexedDB caches to avoid refetching static metadata.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 6 · Offline & Configuration Workflows
 | ||
| 
 | ||
| - **Config manifest:** `/config.json` includes Authority issuer/client ID, gateway base URL, feature flags, telemetry endpoints, and offline hints. Operators can swap config by copying `src/config/config.sample.json` and editing before build, or by rewriting the response at gateway runtime.  
 | ||
| - **Deterministic install:** Documented in `src/Web/StellaOps.Web/docs/DeterministicInstall.md`—`npm run ci:install` plus Chromium provisioning ensures offline runners reproduce builds.  
 | ||
| - **Offline Kit parity:** UI validates downloads manifest signatures (cosign) and surfaces snapshot timestamps per tenant. When offline, buttons switch to CLI snippets (`stella runs export`, `stella downloads sync`).  
 | ||
| - **Feature flags:** `CONSOLE_FEATURE_FLAGS` toggles modules (`runs`, `downloads`, `telemetry`); offline bundles include flag manifest so UI can render only supported panes.  
 | ||
| - **Snapshot awareness:** Global banner shows snapshot timestamp and disables actions needing Authority fresh-auth when running in sealed mode.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 7 · Security & Tenancy
 | ||
| 
 | ||
| - **DPoP + PKCE:** Every request carries `Authorization` + `DPoP` header and gateway enforces nonce replay protection. Private keys live in IndexedDB and never leave the browser.  
 | ||
| - **Scope enforcement:** Gateway checks scope claims before proxying (`ui.read`, `runs.manage`, `downloads.read`, etc.) and propagates denials as `Problem+JSON` with `ERR_*` codes.  
 | ||
| - **Tenant propagation:** `X-Stella-Tenant` header derived from token; downstream services reject mismatches. Tenant switches log `ui.tenant.switch` and require fresh-auth for privileged actions.  
 | ||
| - **CSP & headers:** Default CSP forbids third-party scripts, only allows same-origin `connect-src`. HSTS, Referrer-Policy `no-referrer`, and `Permissions-Policy` configured via gateway (`deploy/console.md`).  
 | ||
| - **Evidence handling:** Downloads never cache secrets; UI renders SHA-256 + signature references and steers users to CLI for sensitive exports.  
 | ||
| - See [Console security posture](../security/console-security.md) for full scope table and threat model alignment.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 8 · Observability & Telemetry
 | ||
| 
 | ||
| - **Metrics:** Prometheus scrape at `/metrics` (enabled when `CONSOLE_METRICS_ENABLED=true`). Key histograms/counters documented in [Console observability](../observability/ui-telemetry.md) (`ui_route_render_seconds`, `ui_tenant_switch_total`, `ui_download_manifest_refresh_seconds`).  
 | ||
| - **Logs:** Structured JSON with `traceId`, `tenant`, `action`. Categories include `ui.action`, `ui.tenant.switch`, `ui.security.anomaly`. Sampled per feature flag to balance volume.  
 | ||
| - **Traces:** Browser OTLP exporter ships spans to configured collector; gateway adds server-side spans so traces cross client/server boundary.  
 | ||
| - **Alerts:** Burn-rate rules for route latency, telemetry batch failures, download manifest refresh, and SSE stalls integrate with Notifier.  
 | ||
| - **Correlation:** SSE events carry `traceId` so operators can jump from UI to backend logs using shared correlation IDs.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 9 · Integration Points & Dependencies
 | ||
| 
 | ||
| | Service | Console dependency | Notes |
 | ||
| |---------|-------------------|-------|
 | ||
| | Authority | OIDC, DPoP tokens, tenant catalog, fresh-auth | Requires client `console-ui` with scopes listed in security guide. |
 | ||
| | Concelier WebService | `/console/advisories`, feed health, export triggers | Gateway must enforce Aggregation-Only guardrails and surface merge hashes. |
 | ||
| | Excititor WebService | `/console/vex`, consensus overlays | SSE ticker shows provider deltas. |
 | ||
| | Policy Engine | Findings views, policy previews, simulation diffs | Console never writes overlays; uses `effective_finding_*` data via API. |
 | ||
| | Scheduler WebService | Runs dashboard, SSE streams, queue metrics | Heartbeat drives status ticker; cancellation actions require `runs.manage`. |
 | ||
| | SBOM Service | SBOM explorer tree, component lookup | Responses cached per tenant; offline bundles preload snapshots. |
 | ||
| | Attestor | Attestation verification, evidence links | Console displays verification status and CLI parity commands. |
 | ||
| | DevOps downloads pipeline | Signed manifest for `/console/downloads` | Manifest signatures validated with cosign key shipped in Offline Kit. |
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| ## 10 · Compliance Checklist
 | ||
| 
 | ||
| - [ ] Frontend package map (core/auth/api/config + feature shells) documented with ownership and tooling details.  
 | ||
| - [ ] Data flow diagram captures SPA ↔ Gateway ↔ downstream services with tenant & scope enforcement notes.  
 | ||
| - [ ] SSE design documented (endpoints, payloads, heartbeat, retry/backoff, offline fallback).  
 | ||
| - [ ] Performance budgets (< 1 MB initial bundle, route hydration ≤ 1.5 s, SSE heartbeat) stated alongside enforcement mechanisms.  
 | ||
| - [ ] Offline workflows (`/config.json`, deterministic install, Offline Kit parity) described with operator guidance.  
 | ||
| - [ ] Security section references DPoP, scopes, CSP, evidence handling, and tenancy propagation.  
 | ||
| - [ ] Observability metrics/logs/traces coverage listed with alert hooks.  
 | ||
| - [ ] Integration dependencies table links Console responsibilities to upstream services.  
 | ||
| - [ ] Document cross-references validated (UI guides, security, observability, deployment).  
 | ||
| - [ ] Last updated timestamp refreshed after review.
 | ||
| 
 | ||
| ---
 | ||
| 
 | ||
| *Last updated: 2025-10-27 (Sprint 23).* 
 | ||
| 
 |