# StellaOps Web Frontend ## Mission Design and build the StellaOps web user experience that surfaces backend capabilities (Authority, Concelier, Exporters) through an offline-friendly Angular application. ## Team Composition - **UX Specialist** ??? defines user journeys, interaction patterns, accessibility guidelines, and visual design language. - **Angular Engineers** ??? implement the SPA, integrate with backend APIs, and ensure deterministic builds suitable for air-gapped deployments. ## Technology Stack - **Framework**: Angular 21 (standalone components, signals, built-in control flow) - **Language**: TypeScript 5.9 - **UI Library**: Angular Material 21 + Angular CDK 21 - **State**: Angular Signals - **Build**: `@angular/build:application` (esbuild-based) - **Unit Tests**: Vitest via `@angular/build:unit-test` builder (Jasmine compatibility shim in `src/test-setup.ts`) - **E2E Tests**: Playwright - **Storybook**: Storybook 10 with `@storybook/angular` - **Node.js**: ^20.19.0 || ^22.12.0 || ^24.0.0 ## Operating Principles - Favor modular Angular architecture (feature modules, shared UI kit) with strong typing via latest TypeScript/Angular releases. - Align UI flows with backend contracts; coordinate with Authority and Concelier teams for API changes. - Keep assets and build outputs deterministic and cacheable for Offline Kit packaging. - Coordinate cross-module changes via docs/implplan/SPRINT*.md files updates and PR descriptions. - Console admin flows use Authority `/console/admin/*` APIs and enforce fresh-auth for privileged actions. - Branding uses Authority `/console/branding` and applies only whitelisted CSS variables. ## Key Paths - `src/Web/StellaOps.Web` ??? Angular workspace (to be scaffolded). - `docs/` ??? UX specs and mockups (to be added). - `ops/` ??? Web deployment manifests for air-gapped environments (future). ## Reachability Drift UI (Sprint 3600) ### Components - **PathViewerComponent** (`app/features/reachability/components/path-viewer/`) - Interactive call path visualization - Displays entrypoint ??? key nodes ??? sink paths - Highlights changed nodes with change kind indicators - Supports collapse/expand for long paths - **RiskDriftCardComponent** (`app/features/reachability/components/risk-drift-card/`) - Summary card for drift analysis - Shows newly reachable / mitigated path counts - Displays associated CVEs - Action buttons for drill-down ### Models - `PathNode` - Node in a reachability path with symbol, file, line - `CompressedPath` - Compact path representation - `DriftedSink` - Sink with reachability change and cause - `DriftCause` - Explanation of why reachability changed ### Services - `DriftApiService` (`app/core/services/drift-api.service.ts`) - API client for drift endpoints - Mock implementations available for offline development ### Integration Points - Scan detail page includes PathViewer for reachability visualization - Drift results linked to DSSE attestations for evidence chain - Path export supports JSON and SARIF formats ## Witness UI (Sprint 3700) - TODO ### Planned Components - **WitnessModalComponent** - Modal for viewing witness details - **PathVisualizationComponent** - Detailed path rendering with gates - **ConfidenceTierBadgeComponent** - Tier indicators (Confirmed/Likely/Present/Unreachable) - **GateBadgeComponent** - Auth gate visualization ### Planned Services - `witness.service.ts` - API client for witness endpoints - Browser-based Ed25519 signature verification ## Coordination - Sync with DevEx for project scaffolding and build pipelines. - Partner with Docs Guild to translate UX decisions into operator guides. - Collaborate with Security Guild to validate authentication flows and session handling. ## Required Reading - `docs/modules/platform/architecture-overview.md` - `docs/technical/architecture/console-admin-rbac.md` - `docs/technical/architecture/console-branding.md` ## Working Agreement - 1. Update task status to `DOING`/`DONE` in both correspoding sprint file `/docs/implplan/SPRINT_*.md` when you start or finish work. - 2. Review this charter and the Required Reading documents before coding; confirm prerequisites are met. - 3. Keep changes deterministic (stable ordering, timestamps, hashes) and align with offline/air-gap expectations. - 4. Coordinate doc updates, tests, and cross-guild communication whenever contracts or workflows change. - 5. Revert to `TODO` if you pause the task without shipping changes; leave notes in commit/PR descriptions for context. ## Metric / KPI Cards Convention (MANDATORY) All metric badges, stat cards, KPI tiles, and summary indicators **must** use ``. Do NOT create custom `.stat-card`, `.summary-card`, `.kpi-card`, or `.posture-card` elements. **Components:** - `shared/components/stella-metric-card/stella-metric-card.component.ts` — individual card - `shared/components/stella-metric-card/stella-metric-grid.component.ts` — responsive grid wrapper **Usage:** ```html ``` **Design rules:** - Cards are **uncolored** — no severity/status color backgrounds - Icon is mandatory (SVG path d, multi-path via `|||`) - Subtitle is 5-10 words explaining the metric - If `route` is set: card is clickable with hover lift + arrow - If no `route`: static display, no hover effect ## Horizontal Scroll Card Lane Pattern (Reusable) A reusable pattern for displaying actionable items as horizontally scrollable cards with gradient fades and scroll arrows. Used in the dashboard (environment cards, pending actions) and the approvals inbox (approval cards with inline actions). ### Architecture Three layers: 1. **Wrapper** (`*-lane-wrapper`) — relative-positioned container with `::before`/`::after` gradient pseudo-elements 2. **Scroll container** (`*-lane`) — flex row with `overflow-x: auto`, hidden scrollbar, `scroll-behavior: smooth` 3. **Cards** — fixed-width (`280px`) flex items with `flex-shrink: 0` ### Scroll arrow signals (TypeScript) ```typescript @ViewChild('myScroll') myScrollRef?: ElementRef; readonly showLeftArrow = signal(false); readonly showRightArrow = signal(false); onScroll(): void { this.updateArrows(); } scrollCards(direction: 'left' | 'right'): void { this.myScrollRef?.nativeElement?.scrollBy({ left: direction === 'left' ? -300 : 300, behavior: 'smooth' }); } private updateArrows(): void { const el = this.myScrollRef?.nativeElement; if (!el) { this.showLeftArrow.set(false); this.showRightArrow.set(false); return; } this.showLeftArrow.set(el.scrollLeft > 1); this.showRightArrow.set(el.scrollWidth - el.scrollLeft - el.clientWidth > 1); } ``` ### Gradient fades (CSS) ```scss .my-wrapper.can-scroll-left::before { content: ''; position: absolute; top: 0; left: 0; bottom: 0; width: 56px; background: linear-gradient(to right, var(--color-surface-primary) 0%, transparent 100%); pointer-events: none; z-index: 1; } .my-wrapper.can-scroll-right::after { /* mirror for right side */ } ``` ### Confirmation dialogs for card actions - **Production approve**: `` with `variant="warning"` and `ViewChild` ref, call `.open()` programmatically - **Reject with reason**: Custom inline dialog overlay with `