Files
git.stella-ops.org/docs/product-advisories/30-Nov-2025 - UI Micro-Interactions for StellaOps.md
StellaOps Bot 25254e3831 news advisories
2025-11-30 21:00:38 +02:00

17 KiB
Raw Blame History

Here are three tightly scoped UI micro-interactions you can drop into the next front-end sprint. Each maps to a single Angular task and reinforces StellaOps auditability, low-noise VEX gating, and evidence provenance for both air-gapped and online users.


1) Audit Trail “Why am I seeing this?” (per-row expandable reason)

Goal: Make every verdict/action explainable at a glance.

  • User flow: In Tables (Findings, Components, Policies), each row shows a tiny “ⓘ Why?” chip. Clicking expands an inline panel with the explanation capsule (policy that fired, rule hash, data inputs, and the deterministic graph revision ID).
  • Angular task:
    • Add ReasonCapsuleComponent (standalone) with inputs: policyName, ruleId, graphRevisionId, inputsDigest, timestamp, actor.
    • Drop it into tables via *ngTemplateOutlet so no table refactor.
    • Keyboard accessible (Enter/Space toggles).
  • Backend contract (read-only): GET /api/audit/reasons/:verdictId
    {
      "policy":"Default VEX Merge",
      "ruleId":"vex.merge.R12",
      "graphRevisionId":"grv_2025-11-18T12:03Z_b3e1",
      "inputsDigest":"sha256:…",
      "actor":"Vexer",
      "ts":"2025-11-18T12:03:22Z"
    }
    
  • Acceptance criteria:
    • Toggle persists open/closed per row in URL state (?open=rid1,rid3).
    • Copy-to-clipboard for graphRevisionId.
    • Works in offline bundle (served from local API).

2) Low-noise VEX Gate (inline, gated action with 3 evidence tiers)

Goal: Reduce false prompts and only block when evidence is meaningful.

  • User flow: On risky actions (promote image, approve import), the primary button morphs into a VEX Gate: a small dropdown right-aligned to the button label showing Green/Amber/Red status with the top blocking reason. Clicking opens a concise sheet (not a modal) with the minimal evidence set, and a single “Proceed anyway” path if policy allows.
  • Angular task:
    • Create VexGateButtonDirective that decorates existing <button> to append status chip + sheet host.
    • Create VexEvidenceSheetComponent that renders: top finding, reachability hint, last vendor VEX statement, and policy clause that blocks/allows.
  • Backend contract: POST /api/vex/gate with {artifactId, action}
    {
      "tier":"amber",
      "reason":"Reachable CVE with pending vendor statement",
      "policyClause":"gates.required.vendor_vex==true",
      "allowBypass":true,
      "expires":"2025-12-31T00:00:00Z"
    }
    
  • Acceptance criteria:
    • Button aria-label reflects state (“Promote — VEX Amber”).
    • Gate sheet loads <300ms cached; falls back to last known cache if offline.
    • “Proceed anyway” requires typed confirmation only when allowBypass=true and logs an audit event.

3) Evidence Provenance Chip (DSSE/receipt capture w/ one-tap export)

Goal: Make provenance obvious and exportable for audits.

  • User flow: Wherever we render an SBOM, VEX, or Attestation, show a Provenance chip (Signed • Verified • Logged) with an overflow menu: View DSSE, View Rekor/Receipt, Export bundle (.tar.zst). In air-gap mode, the “Logged” badge swaps to “Queued” with a tooltip.
  • Angular task:
    • ProvenanceChipComponent with inputs: sigStatus, dsseDigest, rekorInclusion, queued.
    • ProvenanceDialogComponent to show DSSE envelope (pretty-printed), inclusion proof (Merkle path), and copy buttons.
  • Backend contract:
    • GET /api/provenance/:artifactId → DSSE envelope + receipt (or offline queue record).
    • POST /api/provenance/export → streams application/zstd containing: envelope, payload, receipt, local trust anchors.
  • Acceptance criteria:
    • Chip states: Unsigned, Signed, Verified, Verified+Logged; offline shows Signed+Queued.
    • Export under 5s for 10MB payloads; filename includes graphRevisionId.
    • All views work with no internet; if Rekor unreachable, show last cached receipt with “not recently synced” hint.

Dev notes (quick drop-in)

  • Module placement: apps/console/src/app/shared/micro/… (standalone components, tree-shakable).
  • Theme: Consume existing Tailwind tokens; no new colors (use semantic classes).
  • Testing:
    • Unit: input contracts + a11y snapshot.
    • E2E: Cypress happy path per interaction (open/close, bypass, export).
  • Telemetry/Audit: Emit a single ui_event per interaction with graphRevisionId, policyClause, artifactId.
  • Offline kits: All three rely only on local API; Rekor calls are optional/cached.

If you want, I can turn this into three Jira tickets (with checklists) and a PR scaffold (ng g component stubs + sample mocks) so your team can start today. Heres a v0.1 “StellaOps UX Guidelines” you can hand to your UX devs and iterate on. Ill keep it concrete and opinionated, tuned to your world: SBOMs, evidence, attestations, VEX, online + airgap.


0. Who these guidelines are for

These guidelines are for people who:

  • Build UI in Angular for the StellaOps console
  • Design workflows around evidence, SBOMs, VEX, and policy decisions
  • Need to keep highassurance users (security, compliance, infra) happy without drowning them in noise

Whenever in doubt: opt for clarity, traceability, and low noise.


1. Core StellaOps UX Principles

These are the “north star” rules. Every screen and interaction should support them:

  1. Everything is explainable

    • Every verdict, badge, and gating decision must have an explicit “why” nearby.
    • Implement via the Reason Capsule (“Why am I seeing this?” expanders) on rows, cards, and actions.
  2. Evidence in one hop

    • The user should never click more than once from a verdict to the underlying evidence (SBOM, attestation, DSSE, log receipt).
    • Use: side panel / drawer or inline expansion instead of forcing navigation to a separate page.
  3. Noise is a bug

    • Prompts, warnings, and banners are exceptions, not the default.
    • High-severity blocking states must be rare, justified, and explicitly tied to a policy clause.
  4. Deterministic, not magical

    • If something is inferred or uncertain, label it clearly (“Inferred reachability”, “Heuristic match”).
    • Never present a guess as a fact.
  5. Safe by default, reversible when possible

    • Default to the safer path (e.g., “Block promotion” if in doubt).

    • If a potentially risky override is allowed, make it:

      • Explicit
      • Audited
      • Slightly “hard” (typed confirmation, not just a single click)
  6. Online and airgapped parity

    • The same mental model must work whether online or airgapped.
    • When external services are unavailable, show degraded but honest states (“Verified + Queued” vs “Verified + Logged”).
  7. Fast for experts

    • Keyboard accessible, dense data tables, predictable shortcuts.
    • Avoid wizards for frequent tasks; use in-place controls and drawers instead.

2. Domain model in the UI (what users should always see)

Make these concepts feel consistent across all screens:

  • Artifact: image, package, or component.
  • Evidence: SBOMs, attestations, VEX docs, logs, receipts, scans.
  • Policy: the rules that drive decisions.
  • Verdict / Status: “Allowed / Blocked / Needs Review / Unknown”.
  • Graph Revision ID: the immutable “snapshot ID” of the decision state.
  • Audit Event: who did what, when, and based on which graph revision.

Guideline: Any place the user sees a verdict or action, they should also see:

  • The policy that drove it
  • The graph revision ID
  • A one-click path to evidence and audit trail

Our 3 microinteractions (Reason Capsule, VEX Gate, Provenance Chip) exist to make this easy.


3. Core Interaction Patterns

3.1 Reason Capsule: “Why am I seeing this?”

Used in tables, lists, and detail views.

Where to place

  • In tables: right side of each row as a small chip or icon: ⓘ Why?
  • In cards/detail headers: as a text link: “Why this verdict?”

Behavior

  • Click/Enter/Space toggles an inline expansion under the row or section.

  • Show:

    • Policy name (with pill: e.g., Policy: Default VEX Merge)
    • Rule ID (e.g., vex.merge.R12)
    • Graph revision ID (copyable)
    • Key inputs (SBOM digest, VEX source, relevant CVE IDs)
    • Actor (“Vexer”, “User override: alice@example.com”)
    • Timestamp

UX rules

  • Keep it 35 lines max by default; use “Show more” for full detail.

  • Always lead with a plain-language sentence:

    • “This artifact is blocked because policy Prod Promotion requires a vendor VEX statement for reachable critical CVEs.”
  • Include a copy-to-clipboard affordance for graphRevisionId.

  • Remember accessibility:

    • aria-expanded reflects state
    • The expander is focusable and operable via keyboard

3.2 VEX Gate: Gated primary actions

Used on high-impact actions: promote image, approve import, mark as compliant, etc.

Pattern

  • Primary button is enhanced by a VEX status chip:

    • Label pattern: Promote + VEX: Green/Amber/Red chip.
  • Clicking the chip or a small caret opens a compact sheet anchored to the button.

  • The sheet shows:

    • Tier: Green (no blocking issues), Amber (warning), Red (blocking)
    • Top reason in plain language
    • Policy clause that applies
    • Minimal evidence summary: 12 key findings, last vendor VEX statement, reachability
    • Whether bypass is allowed and what it implies

Noise rules

  • Dont show a blocking modal unless absolutely necessary:

    • Prefer anchored sheets or drawers that dont break context.
  • Only require typed confirmation if:

    • Tier is Red and
    • Policy explicitly allows bypass

Copy guidelines

  • Green:

    • “No blocking VEX findings for this artifact under Prod Promotion policy.”
  • Amber:

    • “Found reachable CVE with pending vendor VEX. Policy allows promotion with review.”
  • Red:

    • “Blocking: reachable critical CVE without compensating VEX or mitigation documented.”

Offline/airgapped

  • If gate info is coming from cache:

    • Label: “Based on last local evaluation (not recently synced).”
  • The action should still be possible if the policy says so, even when external VEX feeds are offline.


3.3 Provenance Chip: Attestations, DSSE, receipts

Appears next to any evidence object (SBOM, attestation, VEX doc) and on artifact details.

States

Use a small chip with an icon + label:

  • Unsigned
  • Signed
  • Signed • Verified
  • Signed • Verified • Logged
  • Offline variant: Signed • Verified • Queued

Behavior

  • Clicking opens a Provenance dialog:

    • DSSE envelope (structured view with collapsing sections)
    • Subject digest(s)
    • Inclusion proof / log receipt (if online)
    • Trust anchor summary (what keys were trusted)
    • Export CTA for full bundle

Rules

  • The chip state must never lie. If Rekor (or similar) is unreachable:

    • Show last known receipt + “not recently synced” note.
  • Export action:

    • Single button: “Export provenance bundle (.tar.zst)”
    • Filename should include artifactId and graphRevisionId.

4. Layout & Information Density

4.1 Tables and lists

  • Default to tables for any list of artifacts, findings, or evidence.

  • Per row:

    • Left side: identity (name, version, image tag)
    • Middle: key status chips (severity, policy verdicts, provenance state)
    • Right: row actions + Reason Capsule

Column order guideline

  1. Artifact / Evidence identifier
  2. Primary status (Allowed/Blocked/Needs Review)
  3. Severity / Risk
  4. Provenance status
  5. Last updated / source
  6. Actions + “Why?”

Avoid more than 7 columns at once; beyond that, use:

  • Column visibility toggles
  • A compact “More details” drawer

4.2 Detail views (artifact / policy / evidence)

Use a two-pane layout:

  • Left: core summary; main actions; VEX Gate button
  • Right: tabs or sections: Evidence, Policies, Audit trail

In the summary header:

  • Show:

    • Artifact identity
    • Primary verdict
    • Graph revision ID
    • Provenance chip
  • Provide the one-tap path to:

    • Policy explanation (Reason Capsule)
    • Provenance dialog

5. Copy & Microcopy Guidelines

Your users are experts; dont over-simplify. But also dont write walls of text.

5.1 Tone

  • Neutral, precise, never blamey.
  • Prefer “This artifact is blocked because…” over “You cant do this because…”.
  • Avoid overloaded acronyms unless they are core to the domain (SBOM, VEX, CVE are fine).

5.2 Phrase patterns

Verdicts

  • “Allowed by policy X.”
  • “Blocked by policy X (rule R12: requires vendor VEX for critical CVEs).”
  • “Needs review: incomplete evidence for X.”

Uncertainty

  • “Inferred reachable based on call graph analysis.”
  • “Vendor VEX statement not found in local cache.”

Offline

  • “Using cached results from 20251129. External logs not reachable.”

Overrides

  • “Override applied by alice@example.com on 20251118: promotion allowed despite Red VEX gate.”

5.3 Donts

  • Dont use “Unknown error”. Always say what failed (e.g., “Failed to fetch Rekor receipt: TLS handshake error”).
  • Dont just show raw IDs without labels (e.g., “grv_...” → always “Graph revision: grv_...”).
  • Dont hide policy names; they are how users think about business intent.

6. States: Loading, Errors, Offline, Edge Cases

6.1 Loading

  • For tables: use skeleton rows, not giant spinners.

  • For buttons with gates:

    • Show inline “Checking VEX…” with a subtle spinner in the chip area only.
  • Maximum loading time before showing a message: ~23 seconds; after that, show:

    • “Still evaluating VEX; you can proceed with last known result from 20251118, or wait.”

6.2 Error states

For any failed fetch related to:

  • Provenance
  • Log receipts
  • Policy evaluation

…show:

  • A neutral banner in the relevant area:

    • “Could not refresh provenance from log. Using last known verification from 20251110.”
  • A clear fallback behavior:

    • Block or proceed according to policy, not “best guess”.

6.3 Offline & Airgapped

Golden rule: Never pretend to be online when youre not.

  • Make offline clearly visible but not screaming:

    • Small badge in the header: Air-gapped mode or Offline mode
  • Provenance chip:

    • Use the Queued variant when receipts havent been synced.
  • Export path:

    • Always work without internet (local export).

7. Accessibility & Keyboard Support

Your users will live in this tool; keyboard and a11y arent nice-to-haves.

Minimums

  • All interactive chips (Reason Capsule, Provenance Chip, VEX Gate) must:

    • Be reachable via Tab
    • Be clickable via Enter / Space
    • Have descriptive aria-labels (e.g., “Explain verdict for artifact nginx:1.24.0”)
  • Use visible focus outlines that fit your design tokens.

  • Do not rely solely on color:

    • VEX tiers need both color and text (Green, Amber, Red).

8. Implementation Handshake (Design ⇄ Dev)

A simple workflow you can standardize on:

  1. Design defines the pattern

    • For each reusable microinteraction (Reason Capsule, VEX Gate, Provenance Chip), the designer:

      • Specifies inputs/props
      • Lists states (default, loading, error, offline)
      • Provides content examples
  2. Dev builds a standalone Angular component

    • One component per pattern:

      • ReasonCapsuleComponent
      • VexGateButtonDirective + VexEvidenceSheetComponent
      • ProvenanceChipComponent + ProvenanceDialogComponent
    • All styling via shared tokens (no hardcoded colors).

  3. Shared acceptance criteria

    • Each pattern must have:

      • a11y behavior defined
      • Loading and error behavior defined
      • At least one offline scenario defined
    • E2E check:

      • Can a user go from a verdict to:

        1. Why it happened,
        2. Evidence that supports it,
        3. Audit record of who acted …in ≤ 2 clicks?

9. Quick “Do This, Not That” Cheat Sheet

  • Do: Show Blocked • Why? → inline explanation → evidence link Dont: Show just Blocked with no context.

  • Do: Attach VEX Gate logic to existing primary buttons as a small extension. Dont: Introduce a separate, second “Check VEX” action the user has to remember.

  • Do: Use small chips for provenance state (Signed • Verified • Logged). Dont: Hide signature/log info in a separate “Advanced” tab.

  • Do: Be honest about offline/cached states. Dont: Fake a “Verified + Logged” status when the log sync actually failed.


If youd like, I can also turn this into:

  • A one-page “UX checklist per screen” your devs can run through before shipping, and
  • Concrete Angular interface definitions for each of the shared components so design/dev are literally talking about the same props.