722 lines
17 KiB
Markdown
722 lines
17 KiB
Markdown
Below is a **concrete Angular 17+ standalone component breakdown** aligned to the **new flagship UI** (evidence-based release control plane + hybrid reachability), using **standalone components**, **signals**, and **lazy-loaded feature route trees**.
|
||
|
||
I’m optimizing for:
|
||
|
||
* **Diff-first + decision-first** UX (Approvals, Release Detail)
|
||
* **Evidence-first** navigation (Evidence always one click away)
|
||
* **Digest-first identity** everywhere (no tag ambiguity)
|
||
* **Determinism & replay** surfaced as first-class metadata
|
||
* **Minimum cognitive load** (fewer “product area” silos; more “release lifecycle” flows)
|
||
|
||
---
|
||
|
||
# 1) Folder and ownership model (standalone-first)
|
||
|
||
## 1.1 High-level structure
|
||
|
||
```
|
||
src/app/
|
||
core/ # auth, api client, guards, nav config, app init
|
||
layout/ # app shell, sidebar, topbar, page scaffolding
|
||
shared/
|
||
ui/ # design system primitives (buttons, chips, tables...)
|
||
domain/ # domain widgets (digest chip, gate badges, evidence link)
|
||
overlays/ # drawers/modals (evidence drawer, witness drawer)
|
||
pipes/ # formatting
|
||
util/ # helpers, comparators, trackBy fns
|
||
features/
|
||
control-plane/
|
||
releases/
|
||
approvals/
|
||
environments/
|
||
deployments/
|
||
security/
|
||
evidence/
|
||
reachability/
|
||
operations/
|
||
settings/
|
||
```
|
||
|
||
## 1.2 Container vs presentational convention
|
||
|
||
* **`Page` components**: own routing params, assemble layout, bind stores, handle page-level actions.
|
||
|
||
* Suffix: `...PageComponent`
|
||
* **`Container` components**: own feature state, wire subcomponents, and orchestrate queries.
|
||
|
||
* Suffix: `...ContainerComponent`
|
||
* **Pure UI components**: take `@Input()` signals/values + emit outputs (events), no data fetching.
|
||
|
||
* Suffix: `...Component` / `...WidgetComponent`
|
||
|
||
All use:
|
||
|
||
* `changeDetection: ChangeDetectionStrategy.OnPush`
|
||
* Signals for view-model state (computed selectors, effects)
|
||
* `inject()` + `DestroyRef` instead of `ngOnDestroy` boilerplate
|
||
|
||
---
|
||
|
||
# 2) Core layout components (shared across all pages)
|
||
|
||
## 2.1 App Shell
|
||
|
||
### `AppShellComponent`
|
||
|
||
* **Selector**: `app-shell`
|
||
* **Responsibility**: Top-level layout wrapper with topbar + sidebar + router outlet + overlay hosts.
|
||
* **Contains**:
|
||
|
||
* `<app-topbar />`
|
||
* `<app-sidebar />`
|
||
* `<app-breadcrumb />`
|
||
* `<router-outlet />`
|
||
* `<app-command-palette />`
|
||
* `<app-toast-host />`
|
||
* `<app-overlay-host />` (drawers/modals portal)
|
||
|
||
### `AppTopbarComponent`
|
||
|
||
* Shows global context + global search.
|
||
* **Children**:
|
||
|
||
* `GlobalSearchComponent`
|
||
* `TenantBadgeComponent`
|
||
* `OfflineStatusChipComponent`
|
||
* `FeedSnapshotChipComponent`
|
||
* `PolicyBaselineChipComponent`
|
||
* `EvidenceModeChipComponent`
|
||
* `UserMenuComponent`
|
||
|
||
### `AppSidebarComponent`
|
||
|
||
* Left nav: CONTROL PLANE / RELEASES / APPROVALS / SECURITY / EVIDENCE / OPERATIONS / SETTINGS.
|
||
* **Children**:
|
||
|
||
* `SidebarNavGroupComponent`
|
||
* `SidebarNavItemComponent`
|
||
* `SidebarPinnedItemsComponent` (optional “pins”: Prod, Pending approvals, etc.)
|
||
|
||
### `BreadcrumbComponent`
|
||
|
||
* Builds from router data.
|
||
* Supports “context crumbs” (Release v1.2.5, Env Staging).
|
||
|
||
---
|
||
|
||
# 3) Shared UI primitives (low-level, reusable)
|
||
|
||
These should live under `shared/ui/` and be used everywhere.
|
||
|
||
* `PageHeaderComponent`
|
||
|
||
* Title, subtitle, primary CTA area, secondary actions area
|
||
* `FilterBarComponent`
|
||
|
||
* Search box + filter chips + “Reset” + saved views
|
||
* `DataTableComponent<T>`
|
||
|
||
* Virtual scroll option, sticky header, column templates
|
||
* `SplitPaneComponent`
|
||
|
||
* Left list + right details; collapsible
|
||
* `TabbedNavComponent`
|
||
|
||
* Controlled tabs, supports router-based tabs
|
||
* `StatusBadgeComponent`
|
||
|
||
* OK/WARN/BLOCK/FAILED etc.
|
||
* `MetricCardComponent`
|
||
|
||
* number + label + delta + sparkline slot
|
||
* `TimelineListComponent`
|
||
|
||
* for audit/evidence/deploy events
|
||
* `EmptyStateComponent`
|
||
* `InlineCodeComponent` (for digests/IDs)
|
||
* `CopyToClipboardButtonComponent`
|
||
|
||
---
|
||
|
||
# 4) Shared domain widgets (your “moat UI”: digest, gates, evidence, witness)
|
||
|
||
These are the **high-leverage** components that encode Stella’s differentiators and make the product feel coherent.
|
||
|
||
## 4.1 Digest identity
|
||
|
||
### `DigestChipComponent`
|
||
|
||
* Inputs: `digest: string`, `label?: string`, `variant?: 'bundle'|'image'|'artifact'`
|
||
* Outputs: `(open)`, `(copy)`
|
||
* Behavior: displays `sha256:abc…123`, copy on click, hover reveals full digest.
|
||
|
||
### `BundleDigestHeaderComponent`
|
||
|
||
* Inputs: `releaseId`, `bundleDigest`, `createdAt`, `sourceRef`
|
||
* Renders release identity block (consistent across Release/Approval/Evidence pages).
|
||
|
||
## 4.2 Gate system (Policy + Reachability + VEX)
|
||
|
||
### `GateBadgeComponent`
|
||
|
||
* Inputs: `state: 'PASS'|'WARN'|'BLOCK'|'SKIP'`, `label: string`
|
||
* Used in lists and summaries.
|
||
|
||
### `GateSummaryPanelComponent`
|
||
|
||
* Inputs: `gates: GateResult[]`, `policyRef`, `snapshotRef`
|
||
* Outputs: `(openExplain)`, `(openEvidence)`
|
||
* Renders the compact gate list, with drill-down.
|
||
|
||
### `GateExplainDrawerComponent` (overlay)
|
||
|
||
* Inputs: `gateRunId` or `decisionDigest`
|
||
* Shows: rule hits, K4 lattice explanation, evidence anchors.
|
||
|
||
## 4.3 Evidence UX
|
||
|
||
### `EvidenceLinkComponent`
|
||
|
||
* Inputs: `evidenceId`, `type`, `verified`, `signed`
|
||
* Output: `(open)`
|
||
* Always consistent link target (drawer or page).
|
||
|
||
### `EvidencePacketSummaryComponent`
|
||
|
||
* Inputs: `EvidencePacketHeaderVM`
|
||
* Displays Who/What/Why/How/When in compact audit-friendly block.
|
||
|
||
### `ProofChainLinkComponent`
|
||
|
||
* Inputs: `subjectDigest`
|
||
* Output: `(open)`
|
||
* Standard entry to proof chain.
|
||
|
||
## 4.4 Reachability witness UX
|
||
|
||
### `ReachabilityStateChipComponent`
|
||
|
||
* Inputs: `state: 'Reachable'|'Unreachable'|'Uncertain'`, `confidence: number`
|
||
* Output: `(openWitness)`
|
||
|
||
### `WitnessPathPreviewComponent`
|
||
|
||
* Inputs: `path: string[]`, `guards: GuardSummary`, `deterministic: boolean`
|
||
* Output: `(openFull)`
|
||
* Used on Approval Detail + Release Detail.
|
||
|
||
### `WitnessViewerComponent` (page core)
|
||
|
||
* Inputs: `witnessId` or `sliceRef`
|
||
* Slots: exports (DOT/Mermaid), replay verify action.
|
||
|
||
---
|
||
|
||
# 5) Feature-by-feature component trees (flagship pages)
|
||
|
||
Below, each page includes:
|
||
|
||
* **Page component** (route-bound)
|
||
* **Container** (state + orchestration)
|
||
* **Widgets** (UI)
|
||
* **Drawers** used
|
||
|
||
---
|
||
|
||
## 5.1 CONTROL PLANE (`/`)
|
||
|
||
### `ControlPlanePageComponent`
|
||
|
||
* Owns route; sets page title and CTAs.
|
||
|
||
### `ControlPlaneContainerComponent`
|
||
|
||
* Loads:
|
||
|
||
* environment pipeline state
|
||
* action inbox counts
|
||
* pending promotions list
|
||
* drift/risk deltas summary
|
||
|
||
**Children widgets:**
|
||
|
||
* `PageHeaderComponent` (CTA: Create Release)
|
||
* `EnvironmentPipelineWidgetComponent`
|
||
* `ActionInboxWidgetComponent`
|
||
* `DriftRiskDeltaWidgetComponent`
|
||
* `PendingPromotionsTableComponent`
|
||
|
||
**Overlays used:**
|
||
|
||
* Evidence drawer, Approval drawer quick-open, Deployment detail drawer (optional)
|
||
|
||
---
|
||
|
||
## 5.2 RELEASES LIST (`/releases`)
|
||
|
||
### `ReleasesListPageComponent`
|
||
|
||
### `ReleasesListContainerComponent`
|
||
|
||
* Loads release list; supports filters + saved views.
|
||
|
||
**Children:**
|
||
|
||
* `PageHeaderComponent` (Create Release)
|
||
* `FilterBarComponent`
|
||
* `ReleasesTableComponent`
|
||
|
||
* row actions: View, Compare, Request Promotion, Export Evidence
|
||
|
||
**Row widgets:**
|
||
|
||
* `DigestChipComponent` (bundle digest)
|
||
* `GateBadgeComponent` summary cell
|
||
* `EvidenceLinkComponent`
|
||
|
||
---
|
||
|
||
## 5.3 RELEASE DETAIL (`/releases/:releaseId`)
|
||
|
||
### `ReleaseDetailPageComponent`
|
||
|
||
* Reads `releaseId` param.
|
||
|
||
### `ReleaseDetailContainerComponent`
|
||
|
||
* Loads:
|
||
|
||
* release bundle metadata (digest map)
|
||
* deployed environments map
|
||
* gate summary (policy run refs)
|
||
* security impact summary (new CVEs, reachable)
|
||
* evidence latest packet
|
||
* tabs data on demand
|
||
|
||
**Children:**
|
||
|
||
* `BundleDigestHeaderComponent`
|
||
* `ReleaseDeploymentMapWidgetComponent`
|
||
* `ReleaseTabsComponent` (router tabs)
|
||
|
||
* `ReleaseOverviewTabComponent`
|
||
* `ReleaseComponentsTabComponent`
|
||
* `ReleaseGatesTabComponent`
|
||
* `ReleasePromotionsTabComponent`
|
||
* `ReleaseDeploymentsTabComponent`
|
||
* `ReleaseEvidenceTabComponent`
|
||
* `ReleaseProofChainTabComponent`
|
||
|
||
**Key widgets:**
|
||
|
||
* `GateSummaryPanelComponent`
|
||
* `SecurityImpactWidgetComponent`
|
||
* `EvidencePacketCardComponent` (compact)
|
||
* `WitnessPathPreviewComponent` embedded when “critical reachable” exists
|
||
|
||
**Overlays:**
|
||
|
||
* `GateExplainDrawerComponent`
|
||
* `EvidencePacketDrawerComponent`
|
||
* `WitnessDrawerComponent`
|
||
|
||
---
|
||
|
||
## 5.4 APPROVALS INBOX (`/approvals`)
|
||
|
||
### `ApprovalsInboxPageComponent`
|
||
|
||
### `ApprovalsInboxContainerComponent`
|
||
|
||
* Loads approvals by status, env, policy baseline.
|
||
|
||
**Children:**
|
||
|
||
* `PageHeaderComponent`
|
||
* `FilterBarComponent`
|
||
* `ApprovalsInboxListComponent`
|
||
|
||
* composed of `ApprovalInboxCardComponent` rows
|
||
|
||
**Card children:**
|
||
|
||
* `ApprovalSummaryHeaderComponent` (release/from/to/requested-by)
|
||
* `DiffSummaryInlineComponent` (what changed)
|
||
* `GateBadgeRowComponent`
|
||
* Actions bar:
|
||
|
||
* `OpenApprovalButton`, `OpenEvidenceButton`, `OpenWitnessButton`
|
||
* `ApproveButton`, `RejectButton`, `RequestExceptionButton`
|
||
|
||
---
|
||
|
||
## 5.5 APPROVAL DETAIL (`/approvals/:approvalId`)
|
||
|
||
### `ApprovalDetailPageComponent`
|
||
|
||
### `ApprovalDetailContainerComponent`
|
||
|
||
* Loads:
|
||
|
||
* approval metadata
|
||
* diff summary + detail
|
||
* gate evaluation + explanations
|
||
* reachability witness (preview + links)
|
||
* evidence packet / proof chain
|
||
* comment thread
|
||
|
||
**Children:**
|
||
|
||
* `ApprovalHeaderComponent` (context bar)
|
||
* `SplitPaneComponent`
|
||
|
||
* Left:
|
||
|
||
* `DiffFirstPanelComponent`
|
||
* `GateResultsPanelComponent`
|
||
* Right:
|
||
|
||
* `DecisionPanelComponent` (approve/reject/comment)
|
||
* `CommentsPanelComponent`
|
||
* `ReachabilityWitnessPanelComponent` (below split)
|
||
* `EvidenceQuickPanelComponent`
|
||
|
||
**Overlays:**
|
||
|
||
* `GateExplainDrawerComponent`
|
||
* `EvidencePacketDrawerComponent`
|
||
* `WitnessViewerDrawerComponent` (or open full page)
|
||
|
||
---
|
||
|
||
## 5.6 ENVIRONMENTS LIST (`/environments`)
|
||
|
||
### `EnvironmentsListPageComponent`
|
||
|
||
### `EnvironmentsListContainerComponent`
|
||
|
||
* Loads env list with current release, freeze, targets count, policy baseline.
|
||
|
||
**Children:**
|
||
|
||
* `EnvironmentsTableComponent`
|
||
|
||
* cells: current release link, freeze chip, last deploy
|
||
|
||
---
|
||
|
||
## 5.7 ENVIRONMENT DETAIL (`/environments/:envId`)
|
||
|
||
### `EnvironmentDetailPageComponent`
|
||
|
||
### `EnvironmentDetailContainerComponent`
|
||
|
||
* Loads:
|
||
|
||
* env metadata (freeze windows, baseline)
|
||
* current release
|
||
* target inventory + status
|
||
* promotions and deployments history
|
||
* drift status
|
||
* evidence ledger
|
||
|
||
**Children:**
|
||
|
||
* `EnvironmentHeaderComponent`
|
||
* `TabbedNavComponent` (router tabs)
|
||
|
||
* `EnvOverviewTabComponent`
|
||
* `EnvTargetsTabComponent`
|
||
* `EnvPromotionsTabComponent`
|
||
* `EnvDeploymentsTabComponent`
|
||
* `EnvDriftTabComponent`
|
||
* `EnvEvidenceTabComponent`
|
||
|
||
**Widgets:**
|
||
|
||
* `ReleaseLedgerWidgetComponent`
|
||
* `TargetsQuickTableComponent`
|
||
* `RiskSnapshotWidgetComponent`
|
||
|
||
---
|
||
|
||
## 5.8 DEPLOYMENTS LIST (`/deployments`)
|
||
|
||
### `DeploymentsListPageComponent`
|
||
|
||
### `DeploymentsListContainerComponent`
|
||
|
||
**Children:**
|
||
|
||
* `FilterBarComponent`
|
||
* `DeploymentsTableComponent`
|
||
|
||
* row includes: env, release, duration, status, evidence link
|
||
|
||
---
|
||
|
||
## 5.9 DEPLOYMENT DETAIL (`/deployments/:deployId`)
|
||
|
||
### `DeploymentDetailPageComponent`
|
||
|
||
### `DeploymentDetailContainerComponent`
|
||
|
||
* Loads:
|
||
|
||
* deployment run metadata
|
||
* workflow DAG nodes + node logs
|
||
* produced artifacts + hashes
|
||
* targets results
|
||
* evidence packet
|
||
|
||
**Children:**
|
||
|
||
* `DeploymentHeaderComponent`
|
||
* `TabbedNavComponent`
|
||
|
||
* `DeploymentWorkflowTabComponent`
|
||
|
||
* `WorkflowDagWidgetComponent`
|
||
* `DeploymentTargetsTabComponent`
|
||
* `DeploymentArtifactsTabComponent`
|
||
|
||
* `ArtifactListComponent` (immutable outputs)
|
||
* `DeploymentLogsTabComponent`
|
||
* `DeploymentEvidenceTabComponent`
|
||
|
||
---
|
||
|
||
## 5.10 EVIDENCE CENTER (`/evidence`)
|
||
|
||
### `EvidenceCenterPageComponent`
|
||
|
||
### `EvidenceCenterContainerComponent`
|
||
|
||
* Loads evidence packets with filters; verification status; export actions.
|
||
|
||
**Children:**
|
||
|
||
* `PageHeaderComponent` (Create Audit Bundle / Export)
|
||
* `FilterBarComponent`
|
||
* `EvidenceTableComponent`
|
||
* Optional right detail drawer:
|
||
|
||
* `EvidencePacketDrawerComponent`
|
||
|
||
---
|
||
|
||
## 5.11 EVIDENCE PACKET VIEWER (`/evidence/:evidenceId`)
|
||
|
||
### `EvidencePacketPageComponent`
|
||
|
||
### `EvidencePacketContainerComponent`
|
||
|
||
* Loads header + contents manifest (SBOM, verdict, witness slice, VEX, attestations).
|
||
|
||
**Children:**
|
||
|
||
* `EvidencePacketSummaryComponent` (Who/What/Why/How/When)
|
||
* `EvidenceContentsListComponent`
|
||
|
||
* each row uses `EvidenceArtifactRowComponent` with [View] [Download]
|
||
* `VerifyEvidencePanelComponent` (signature + Rekor inclusion proofs)
|
||
|
||
---
|
||
|
||
## 5.12 SECURITY FINDINGS (`/security/findings`)
|
||
|
||
### `SecurityFindingsPageComponent`
|
||
|
||
### `SecurityFindingsContainerComponent`
|
||
|
||
* Loads findings with reachability + “impacts releases/envs”.
|
||
|
||
**Children:**
|
||
|
||
* `FilterBarComponent`
|
||
* `FindingsImpactTableComponent`
|
||
* `FindingDetailDrawerComponent` (row click)
|
||
|
||
* witness preview
|
||
* VEX status
|
||
* exceptions
|
||
* “Impacts” list with links to approvals/releases
|
||
|
||
---
|
||
|
||
## 5.13 VULNERABILITY DETAIL (`/security/vulnerabilities/:cveId`)
|
||
|
||
### `VulnerabilityDetailPageComponent`
|
||
|
||
### `VulnerabilityDetailContainerComponent`
|
||
|
||
* Loads CVE intel + affected components + deployed impacts + gate impacts + witness summary.
|
||
|
||
**Children:**
|
||
|
||
* `VulnerabilityHeaderComponent`
|
||
* `ImpactSummaryWidgetComponent`
|
||
* `DeployedImpactListComponent`
|
||
* `ReachabilitySummaryPanelComponent`
|
||
* `FixPathPanelComponent`
|
||
* `VexConsensusPanelComponent`
|
||
|
||
---
|
||
|
||
## 5.14 WITNESS VIEWER (`/witness/:witnessId`)
|
||
|
||
### `WitnessPageComponent`
|
||
|
||
### `WitnessContainerComponent`
|
||
|
||
* Loads witness graph slice + explanation + exports + replay verification.
|
||
|
||
**Children:**
|
||
|
||
* `WitnessHeaderComponent`
|
||
* `WitnessPathPreviewComponent`
|
||
* `WitnessExplanationPanelComponent`
|
||
* `WitnessGraphCollapsedPanelComponent` (expand to graph viewer)
|
||
* `WitnessExportActionsComponent` (DOT/Mermaid)
|
||
* `ReplayVerifyPanelComponent`
|
||
|
||
---
|
||
|
||
# 6) State, services, and API clients (signals-first)
|
||
|
||
## 6.1 API client pattern
|
||
|
||
`core/api/`:
|
||
|
||
* `ApiClient` (wraps HttpClient, error handling, auth headers)
|
||
* Feature clients:
|
||
|
||
* `ReleasesApi`
|
||
* `ApprovalsApi`
|
||
* `EnvironmentsApi`
|
||
* `DeploymentsApi`
|
||
* `EvidenceApi`
|
||
* `SecurityApi`
|
||
* `ReachabilityApi`
|
||
* `PolicyApi`
|
||
|
||
Each returns typed DTOs.
|
||
|
||
## 6.2 Signal store pattern (recommended)
|
||
|
||
For each major page/container, create a store service:
|
||
|
||
Example:
|
||
|
||
* `ReleaseDetailStore`
|
||
|
||
* `state = signal<ReleaseDetailState>({...})`
|
||
* `release = computed(...)`
|
||
* `gateSummary = computed(...)`
|
||
* `load(releaseId)` triggers effects + sets loading/error
|
||
* `refresh()` re-runs
|
||
* `requestPromotion()` command method
|
||
|
||
Stores live in:
|
||
`features/<feature>/state/`
|
||
|
||
This avoids global NgRx complexity while keeping logic testable.
|
||
|
||
## 6.3 Cross-cutting stores
|
||
|
||
* `AppContextStore`
|
||
|
||
* tenant, user, offline mode, feed snapshot, evidence mode
|
||
* `GlobalSearchStore`
|
||
|
||
* query → aggregated results across types
|
||
* `OverlayStore`
|
||
|
||
* open/close drawers (evidence, witness, gate explain)
|
||
|
||
---
|
||
|
||
# 7) Overlays (drawers/modals) to keep pages “small”
|
||
|
||
These are essential to your “small pages, deep drill-down” requirement.
|
||
|
||
* `EvidencePacketDrawerComponent`
|
||
|
||
* opens from anywhere; renders same core as Evidence Packet page but condensed.
|
||
* `WitnessDrawerComponent`
|
||
|
||
* preview witness path + quick export + “open full”
|
||
* `GateExplainDrawerComponent`
|
||
|
||
* show K4 lattice reasoning + rule hits + evidence anchors
|
||
* `CreateReleaseModalComponent`
|
||
* `RequestPromotionModalComponent`
|
||
* `RollbackModalComponent`
|
||
* `RequestExceptionModalComponent`
|
||
|
||
---
|
||
|
||
# 8) Concrete component inventory (by section)
|
||
|
||
## Layout (layout/)
|
||
|
||
* `AppShellComponent`
|
||
* `AppTopbarComponent`
|
||
* `AppSidebarComponent`
|
||
* `BreadcrumbComponent`
|
||
* `GlobalSearchComponent`
|
||
* `CommandPaletteComponent`
|
||
* `ToastHostComponent`
|
||
* `OverlayHostComponent`
|
||
|
||
## Shared domain (shared/domain/)
|
||
|
||
* `DigestChipComponent`
|
||
* `GateBadgeComponent`
|
||
* `GateSummaryPanelComponent`
|
||
* `ReachabilityStateChipComponent`
|
||
* `EvidenceLinkComponent`
|
||
* `EvidencePacketSummaryComponent`
|
||
* `ProofChainLinkComponent`
|
||
* `WitnessPathPreviewComponent`
|
||
|
||
## Features (features/*)
|
||
|
||
* `ControlPlanePageComponent` + widgets
|
||
* `ReleasesListPageComponent`, `ReleaseDetailPageComponent` + tabs
|
||
* `ApprovalsInboxPageComponent`, `ApprovalDetailPageComponent`
|
||
* `EnvironmentsListPageComponent`, `EnvironmentDetailPageComponent` + tabs
|
||
* `DeploymentsListPageComponent`, `DeploymentDetailPageComponent` + tabs
|
||
* `EvidenceCenterPageComponent`, `EvidencePacketPageComponent`
|
||
* `SecurityFindingsPageComponent`, `VulnerabilityDetailPageComponent`
|
||
* `WitnessPageComponent`
|
||
|
||
---
|
||
|
||
# 9) Implementation details that matter (so the UX feels “best-in-class”)
|
||
|
||
1. **One “context header” pattern**
|
||
`PageHeaderComponent` + `ContextChipsRowComponent` (Offline, Snapshot, Policy, Evidence) used everywhere.
|
||
|
||
2. **Tables are consistent**
|
||
One `DataTableComponent<T>` powering releases/approvals/deployments/evidence/findings so keyboard nav, filters, row actions behave identically.
|
||
|
||
3. **Drawers always open with stable deep links**
|
||
Drawer open should push a URL query param (e.g., `?evidence=EVD-...`) so refresh/back works:
|
||
|
||
* `?evidence=...`
|
||
* `?witness=...`
|
||
* `?explainGateRun=...`
|
||
|
||
4. **Diff-first everywhere it matters**
|
||
|
||
* Approvals: diff summary is always above gates.
|
||
* Release detail: security impact summary is above evidence link.
|
||
|
||
5. **Witness is a product feature, not an internal detail**
|
||
Always show: state + confidence + why + export + replay verify.
|
||
|
||
---
|
||
|
||
|