Commit Graph

7 Commits

Author SHA1 Message Date
SaelixCode d42a30967d fix: reduce masthead rail opacity to match login page pattern
Changed all MastheadRail background classes from 100% to 70% opacity
(bg-brand → bg-brand/70, etc.) so the shimmer highlight reads as a surface
reflection rather than a detached floating bar. Matches the AuthCanvas
login card precedent.
2026-07-02 12:13:25 -04:00
Anso 322d337d20 fix: polish sidebar and masthead chrome, scroll setup preflight (#1522)
Remove redundant nav and label dots, move desktop masthead status to animated left rails, and let AuthCanvas scroll long preflight content on small viewports.
2026-06-29 20:29:06 -04:00
Anso b1630788ba feat(security): prioritization-led Overview charts (posture + exploit intel) (#1427)
* feat(security): rework Overview charts around posture and exploit intel

Replace the three severity-variation charts (severity donut, top exposed images,
findings by type) with prioritization views, keeping the risk trend for context:

- Action posture: bars of fixable / known-exploited / needs-review / accepted /
  not-affected with a known-exploited headline, derived from the existing
  overview facts (no new fetch).
- Top exploit-risk findings: ranked actionable Critical/High by KEV, then EPSS,
  then CVSS, each row opening its scan.
- Severity x exploitability: a CVSS-by-EPSS quadrant that separates
  scary-but-not-exploitable from act-first.

The two intel panels are fed by a new bounded GET /security/overview/exploit-intel
(latest-scan Critical/High, suppression-filtered, KEV/EPSS joined at read time)
and degrade to clear empty states until exploit intel is fetched and images are
rescanned.

* fix(security): drop the redundant SECURITY kicker from the desktop masthead

The desktop nav strip already names the page, so the masthead's "SECURITY" label
above the posture word was redundant. Make PageMasthead's kicker optional (pages
that pass one render unchanged) and omit it on the Security masthead. The mobile
masthead keeps its kicker, since on the phone layout it is the page identity and
there is no nav strip.

* docs(security): describe the prioritization-led Overview charts

Update the Security overview docs for the reworked chart set (risk trend, action
posture, top exploit-risk, and the severity-by-exploitability quadrant) and note
the exploit-risk charts populate once exploit intelligence is enabled.

* fix(security): move the scanner-detections note into a masthead info icon

Replace the standing "scanner detections show vulnerable components..." caption
below the masthead (desktop and mobile) with an info affordance next to the
scanned-images count in the masthead subtitle. Declutters the overview while
keeping the disclaimer one hover away.

* fix(security): apply "assume it's automatable" to exploit-risk ranking

Absence of exploitability evidence must not be treated as low risk. Rank the top
exploit-risk list by tier (known-exploited > known-high EPSS > unknown EPSS >
known-low EPSS) so an unrated finding outranks one with evidence of low
likelihood; label unrated findings "EPSS n/a"; and reword the quadrant footnote
so excluded findings read as unrated rather than lower risk.
2026-06-23 21:55:11 -04:00
Anso 8d9e6574cc feat(appearance): add Calm/Signature visual style, readability mode, and chart palette (#1407)
* feat(appearance): add Calm/Signature visual style, readability mode, and chart palette

Turn the "too intense / italic headers hurt / the security graph fights my
eyes" feedback into a token-driven Visual style with Calm as the new default
and Signature one click back to the prior look.

- Heading family routes through a `.font-heading` utility driven by
  `--font-heading`/`--heading-style`: operational headings render upright in the
  interface face under Calm and italic Instrument Serif under Signature. Base
  rule sets family + style only, so each call site keeps its own weight/tracking
  and Signature stays a true no-op; the Calm lift is a `[data-headings="clean"]`
  descendant rule. Brand lockup, empty-state heroes, and onboarding stay serif.
- Severity charts resolve through `--sev-*` tokens with Muted, Heat, and
  Signature palettes; FindingsByType routes its series through the severity ramp
  plus a neutral so no brand-cyan sits next to rose. The risk trend flattens its
  gradient under Muted/Heat/reduced and keeps the gradient under Signature.
- Appearance settings gain Visual style cards, a Security visualization palette,
  a Readability master toggle, a Motion & effects group, and a "Reset to default"
  button (restores the Calm axes, disabled while readability is on). Contrast
  moves under Readability and Ambient glow under Motion & effects. A card is
  selected only while the stored sub-axes match its preset, so a custom
  combination de-selects both.
- The topbar Theme quick-switch swaps the interface/data font pickers for a
  Visual style switch and a Readability toggle (text size kept); its footer
  Settings link jumps straight to Appearance.
- Readability is a sticky master that forces the calm resolution and a contrast
  lift at apply time without mutating the stored sub-axes.
- New users default to Calm; any pre-existing persisted appearance state keeps
  the Signature look. The pre-paint script mirrors the store.
- SegmentedControl gains a `disabled` prop and a nullable value (no active
  segment for a custom combination, with a roving-tabindex keyboard anchor).
  Adds unit/component coverage for the store, migration, chart shape logic, the
  disabled control, the reset/de-selection, and the quick-switch.

* fix(appearance): migrate Blueprint serif headings and surface readability locks

- Migrate the two operational Blueprint headings (catalog tile name, drift-policy
  option title) from font-serif italic to the .font-heading utility; the first
  pass only covered font-display, so Calm still left these italic. font-serif and
  font-display both resolve to the same display face, so this is the same fix.
- Lock the Visual style cards under Readability (parity with the topbar switch and
  the on-screen guidance to turn Readability off to choose a style by hand).
- Lock the Border brightness slider under Readability and show its forced +0.03
  readout, since Readability overrides the stored value; dragging it previously
  appeared to do nothing.
- Correct the Appearance docs sentence for the topbar quick switch (it listed
  fonts; the quick switch now carries visual style, readability, and text size).
2026-06-22 00:19:57 -04:00
Anso 6cbab661a0 feat: match the Security masthead to the primary-page hero and make History search realtime (#1365)
- Masthead: add `size` and `subtitle` to PageMasthead and render the Security
  masthead at the hero title size with a one-line posture summary, so its height
  and weight match the Home and Fleet mastheads. The compact size with no
  subtitle stays the default, so Settings, Console, and Logs are unchanged.
- History search now applies as you type (a short debounce, no Enter press),
  matching the Fleet overview search. It stays server-side so the query searches
  every completed scan, not just the loaded page.
2026-06-12 18:21:37 -04:00
Anso eead195529 feat(settings): dress the page to match the audit (#849)
* feat(settings): dress the page to match the audit (cyan rail, italic serif, two-column rows)

Brings the full-page Settings route into the Sencho voice. The page now
opens with a full-width PageMasthead (cyan rail, mono crumb, italic
serif title, contextual stat strip) above a sidebar and main-content
panel, each as a rounded-xl card inset on the dark background.

Sidebar drops the duplicate "Settings" header and the candy tier badges.
Group headers carry mono labels with visible/total counts; gated rows
get a neutral uppercase lock chip and dim. Active rows keep the cyan
2px rail.

Five new primitives (SettingsSection, SettingsField, SettingsCallout,
SettingsActions / SettingsPrimaryButton, TierLockChip) replace the
stacked label-input-help shadcn defaults and the per-section ad-hoc
chrome. AccountSection, AppearanceSection, LicenseSection, SystemSection,
NotificationsSection, DeveloperSection, AppStoreSection, AboutSection,
and SupportSection are migrated to the new layout. The list-driven
sections (Webhooks, Routing, Users, Labels, Security, CloudBackup,
ApiTokens, Registries, NodeManager, SSO) keep their list cards but get
the new chrome and primary CTAs.

Each section can publish contextual stats to the masthead via a small
context channel: 2FA state on Account, plan/trial/renews on License,
edited count on System, channel counts on Notifications, etc.

* refactor(settings): drop react-router-dom and align with DESIGN.md

The Settings page was the only surface using react-router-dom for sub-section
navigation. Every other primary view (Home, Fleet, Resources, App Store,
Schedules, etc.) drives view switching through a single activeView useState in
EditorLayout. This change removes the dependency end-to-end:

- App.tsx drops BrowserRouter
- EditorLayout adds 'settings' to the activeView union; SettingsPage renders
  inside the same flex-1 overflow-y-auto p-6 wrapper as siblings
- UserProfileDropdown receives an onOpenSettings callback instead of
  useNavigate. SettingsPage owns currentSection via props lifted to
  EditorLayout, so cross-component navigation (openLabelManager,
  onManageNodes, ConfigurationStatus rows) can route to a sub-section
- SettingsSidebar items become buttons (no more NavLink); SectionGate's
  redirect-on-invisible falls back through SettingsPage's safeSection memo
- e2e/nodes.spec.ts updates the Nodes selector from link to button role
- react-router-dom removed from package.json + package-lock.json

The visual treatment is brought into alignment with frontend/DESIGN.md,
which was rewritten this week to be the normative extract of the audit:

- PageMasthead: title text-3xl → text-[22px] Section rung italic; kicker
  11px → 10px Label rung; stat label tracking 0.22em → 0.18em; stat value
  font-medium for mono Stat-rung family discipline
- SettingsField helper: mono → sans Body rung 14/22; success tone now uses
  --success green (was incorrectly mapped to brand cyan)
- SettingsCallout: title tracking 0.18em; subtitle Body rung 14px; success
  tone now genuinely uses --success green; new brand tone for promotional
  callouts (Trial CTA, Admiral upgrade) that should read cyan
- SettingsActions: SettingsPrimaryButton renders mono uppercase tracked,
  size sm by default. DESIGN §9.10 requires "small mono uppercase, cyan-
  filled" for every Settings primary CTA
- TierLockChip: 9px → 10px Label rung floor
- SettingsSidebar: group header tracking 0.18em; ⌘K kbd 9px → 10px;
  aside gains text-card-foreground transition-colors per §10 canonical
  card class
- SettingsPage main panel: text-card-foreground transition-colors added;
  uses h-full overflow-auto p-6 to mirror FleetView's wrapper rhythm
- Field rows, section headers, action rows now consume var(--density-*)
  tokens with literal fallbacks so Settings respects the comfortable/
  compact toggle

* fix(e2e): update mfa openAccountSettings to match settings redesign

Settings now opens to the Account section by default when accessed from
the profile dropdown, and the Account section no longer renders an h2
heading element. Update the openAccountSettings helper to open the
correct section and assert on the Password h3 heading that SettingsSection
renders instead.

* test(e2e): fix MFA enrolment assertion after settings redesign

The 2FA enrolment badge was replaced with a kicker/field pattern.
Assert on the 'enrolled' text that the new design renders instead of
the removed Enabled badge.

* test(e2e): fix low-backup-codes warning assertions after settings redesign

Update two assertions in the 'low backup codes warning' test that
referenced UI text removed in the settings redesign:
- '1 backup code remaining' -> '1 remaining' (SettingsField body text)
- 'Regenerate now' button -> callout subtitle text, which uniquely
  identifies the zero-codes error card without hitting strict-mode
  from two identically-labelled Regenerate buttons on the page

* test(e2e): navigate to root before re-opening settings for mock refresh

The settings redesign uses a nested full-page route. Navigating to the
same URL a second time does not remount the component, so AccountSection
retains cached MFA state and the 0-codes branch never fetches. A
page.goto('/') ensures full unmount before the second openAccountSettings
call, so the refreshed mock is actually hit.

* test(e2e): scroll zero-codes callout into view before asserting visibility

The callout sits below the Disable 2FA section in the MFA settings page
and is scrolled out of the clipped content area on initial render.
scrollIntoViewIfNeeded() brings it into the visible viewport before the
toBeVisible assertion.

* test(e2e): scroll Radix ScrollArea viewport for zero-codes callout assertion

The settings page wraps content in a Radix ScrollArea whose Root has
overflow:hidden, so the browser's native scrollIntoView cannot scroll
the inner viewport. Wait for the callout to attach (confirms mock data
loaded), then programmatically set scrollTop on the Radix viewport
element before asserting visibility.

* test(e2e): use toBeAttached for zero-codes callout to avoid Radix clip issue

The callout renders below the Disable 2FA section, outside the visible
clip area of the Radix ScrollArea Root (overflow:hidden) on a standard
viewport. Playwright's visibility check uses the clip intersection, so
toBeVisible() fails even after programmatic scroll. toBeAttached()
confirms the component rendered the warning card for backupCodesRemaining:0
without depending on the element's scroll position.
2026-04-30 19:37:38 -04:00
Anso b95442c8f7 feat(ui): redesign global logs as cockpit surface (#699)
Rework the Logs view into the cockpit language: a PageMasthead strip with
cyan rail, pulsing live dot, italic state word, and tracked-mono kicker;
a SignalRail of EVENTS/MIN (with rolling 60s sparkline), ERRORS, WARNINGS,
and CONTAINERS tiles; a segmented filter strip; a day-banded feed with
severity dots and whole-row tint on ERROR/WARN; and a floating glass chip
strip for pause/resume, clear, and download.

Decouple the live log stream from the Developer Mode toggle so SSE runs by
default for everyone, with polling as an invisible fallback when
EventSource is unavailable. Drop the Standard Log Polling Rate setting
and the global_logs_refresh key it persisted; Developer Mode still gates
Real-Time Metrics and Debug Diagnostics and nothing else.

Introduces the shared PageMasthead and SignalRail primitives for reuse
across other cockpit pages.
2026-04-19 16:25:54 -04:00