Commit Graph

697 Commits

Author SHA1 Message Date
SaelixCode 366add027b chore: merge main into fix/ui-polish 2026-07-04 04:05:57 -04:00
SaelixCode 23a52aedf0 fix: restore missing closing bracket on TabsTrigger tag 2026-07-04 01:02:37 -04:00
SaelixCode dedf19c9f2 fix: match Resources tab font size to Fleet and Security
Removed explicit text-xs from Resources TabsTrigger elements so they
use the default text-sm, matching Fleet and Security tab typography.
2026-07-04 01:00:45 -04:00
SaelixCode c9b3e578b6 fix: restructure Resources page tabs to match Fleet/Security pattern
Moved tab band out of the outer card into a standalone full-width
element. Replaced custom FilterToggle with Fleet-style Button
toggles. Added search inputs per tab. Wrapped each resource table
in a card container matching the Security Images table design.
2026-07-04 00:55:40 -04:00
SaelixCode 32b6f05866 fix: change tab highlight from neutral to brand color
Replaced bg-glass-highlight with bg-brand/20 on all TabsHighlight
instances and updated TabsTrigger active state to text-brand,
matching the SegmentedControl selected style. Works on both
dark and light themes.
2026-07-03 23:52:15 -04:00
Anso 1fac6f797f refactor: replace PNG logos with SVG (#1559)
Swap sencho-logo PNGs for SVGs in frontend/public. Update all references
in index.html, SidebarBrand.tsx, and README.md.
2026-07-03 23:29:27 -04:00
SaelixCode 9117ca13cf feat: add copy button to execution history details column
Replaced the plain truncated Details cell with a flex layout containing
a copy button. Users can now copy the full error/output text instead
of relying on the native title tooltip to read long messages.
2026-07-03 23:16:17 -04:00
SaelixCode dd6874f1ae fix: replace native title tooltips with Radix tooltips on Schedules and Settings pages
Converted Run now, Execution history, Edit, Delete buttons on Schedules;
Download/Delete on Cloud Backup; Send test/Edit/Delete on Notification
Routing; Reset 2FA on Users; and Edit/Remove suppression on
Suppressions panel. Skipped SettingsSection/Modal title props which
are React component props, not native HTML attributes.
2026-07-03 19:42:48 -04:00
SaelixCode 5a18be8667 fix: replace native title tooltips with Radix tooltips on Security page
Converted scanner info icon, exploitability n/a badge, and scan
image button from native HTML title attributes to the shared Radix
Tooltip component.
2026-07-03 19:35:13 -04:00
SaelixCode 717d956593 fix: replace native title tooltips with Radix tooltips on Resources page
Converted all actionable button tooltips (Open stack, Inspect image,
Scan, Browse volume, and delete buttons) plus the SenchoBadge
informational tooltip. Wrapped disabled protected-resource delete
buttons in span triggers so tooltips fire on disabled elements.
2026-07-03 19:27:18 -04:00
SaelixCode dd35f45062 fix: replace native title tooltip on Fleet Snapshots upload button 2026-07-03 19:15:59 -04:00
SaelixCode 244f10fcec fix: replace native title tooltips with Radix tooltips on Fleet toolbar
Converted Refresh, Export Dossier, Search, Sort direction, Node Update,
and Manage Nodes buttons from native HTML title attributes to the shared
Radix Tooltip component so they match the app-wide glass tooltip design.
2026-07-03 19:13:37 -04:00
Anso 4a350e7a0a feat: add Docker label audit across Fleet and Stack views (#1531) 2026-07-03 18:26:09 -04:00
SaelixCode 9546334946 fix: apply glass/blur design to shadcn tooltip component
Replaced the solid bg-foreground/text-background style with the app's
glass design: bg-popover, border-glass-border, backdrop-blur, and
text-popover-foreground. Kept the shadcn structure (Portal, Arrow,
slide/fade animations).
2026-07-03 15:40:50 -04:00
SaelixCode f0874862f0 fix: replace custom tooltip with shadcn/ui Radix tooltip
Replaced the glass/blur-styled tooltip with the standard shadcn/ui
pattern: bg-foreground/text-background, arrow pointer, proper
slide/fade animations, and w-fit max-w-xs sizing. This gives all
tooltips a consistent dark-solid look across the entire app.
2026-07-03 15:31:51 -04:00
SaelixCode ef85f57cf2 fix: bake standard tooltip styling into TooltipContent component
Added font-mono tabular-nums text-stat-value directly to the
TooltipContent base styles so every tooltip in the app inherits
the same look without per-instance wrappers. Removed the now-
redundant span from StackRow's RowTooltip.
2026-07-03 15:22:36 -04:00
SaelixCode f83f01417c Revert "fix: standardize all tooltips to match sidebar RowTooltip design"
This reverts commit 9e1d97d39e.
2026-07-03 15:21:35 -04:00
SaelixCode 9e1d97d39e fix: standardize all tooltips to match sidebar RowTooltip design
Wrapped every TooltipContent child in a font-mono text-xs
tabular-nums text-stat-value span so all tooltips across the app
share a consistent look. Previously some used plain text, others
used <p> elements with different fonts and sizes.
2026-07-03 14:45:48 -04:00
SaelixCode 8494e53e4c Revert "fix: remove custom tooltip styling, use standard TooltipContent defaults"
This reverts commit 209fbd2742.
2026-07-03 14:42:08 -04:00
SaelixCode 209fbd2742 fix: remove custom tooltip styling, use standard TooltipContent defaults
The RowTooltip wrapped its label in a font-mono text-stat-value span
instead of using the TooltipContent base styling (text-xs
text-popover-foreground) like every other tooltip in the app.
2026-07-03 14:28:10 -04:00
SaelixCode ff98eb3cd8 fix: standardize Blueprint empty state headings to font-heading
Replaced manual font-serif [font-style:var(--heading-style)] with the
font-heading class on the main heading and three step titles so the
Deployments empty state follows the same heading convention as the
rest of the app and respects the Calm/Signature theme toggle.
2026-07-03 14:16:52 -04:00
SaelixCode b0cb5b70d0 fix: replace Timeline/All tasks buttons with SegmentedControl
The two loose Button elements had indistinguishable selected/unselected
states (secondary vs ghost). Replaced with the SegmentedControl component
already used elsewhere on the same page, which has a clear active
highlight indicator.
2026-07-03 13:17:54 -04:00
SaelixCode 604c4a7705 fix: rename Notification Routing to Routing in settings sidebar 2026-07-03 09:13:52 -04:00
Anso 10fb93dcb1 feat(scheduler): schedule container restart, stop, and start (#1526)
* feat(scheduler): schedule container restart, stop, and start

Add container as a scheduled-task target type so operators can automate lifecycle actions against standalone containers by node and name, with matching UI pickers, validation, execution on local and remote nodes, and tests.

* fix(scheduler): stack service matching and container picker hygiene

Backfill Service on smartFallback containers so per-service stack restarts work when container_name is set. Match services by compose label and container name in stack routes and scheduled restarts. Exclude Sencho from GET /api/containers lists. Hide the Restart Stack service picker when a stack has only one service.

* test(scheduler): scope service checkbox assertion to Services block

The create dialog also has a Delete after run checkbox. Count checkboxes only inside the Services section so CI does not include unrelated form controls.

* fix(scheduler): narrow closest() result to HTMLElement in schedule test

The service-checkbox assertion passed an Element from closest() into
within(), which requires an HTMLElement, failing tsc -b in the frontend
build and Docker build stages. Use the closest<HTMLElement>() type
argument so the value type-checks without an unsafe cast.

* fix(scheduler): hide Sencho container on remote node picker lists

Remote container lists are proxied from peer Sencho instances, so id-only self filtering missed peers on older builds. Await SelfIdentity init, match ImageID, and drop official saelix/sencho images. Apply the same heuristic in the scheduled-operations UI and when the hub fetches remote containers for scheduled runs.

* test(monitor): add missing DatabaseService mocks for scan history cleanup

* test(scheduler): add missing markStaleScansAsFailed mock

SchedulerService.tick() calls db.markStaleScansAsFailed() to sweep stale
vulnerability scans. The scheduler-service test was missing this method in
its DatabaseService mock, causing TypeError failures during test initialization.

Added mockMarkStaleScansAsFailed to hoisted mocks and DatabaseService mock
object, returning safe default of 0 scans marked as failed.

* test(compose): add missing FileSystemService mocks for getStackContent/getEnvContent

* test(containers-route): mock SelfIdentityService to prevent initialize() crash

The excludeSelfContainers() helper calls SelfIdentityService.initialize(), which tries to access DockerController. Without a proper SelfIdentityService mock, the initialize() call fails silently, causing a 500 error on GET /api/containers.

Added SelfIdentityService mock with initialize(), isOwnContainer(), and isOwnImage() methods to prevent the crash.
2026-07-02 22:31:29 -04:00
Anso b65daf6845 feat: add notification suppression rules (#1525)
* feat: add notification suppression rules

* fix: restore label routing and routing test mocks for suppression

* fix: allow bell mute shortcuts for history-only notification categories

Suppression rule validation used the routable category whitelist, which rejected history-only categories such as update_started that appear in the bell during stack updates.

* feat: expand Mute Rules UX with compose-first entry points and activity badges

* fix: add missing NodeContext mocks for notification suppression tests
2026-07-02 15:26:48 -04:00
SaelixCode f9a80f30dc fix: wrap tooltip icon triggers in span for Radix compatibility
TooltipTrigger asChild requires a native element to forward props.
Lucide icon components did not reliably receive data-state and event
handlers, so tooltips on the check-failed and git-pending indicators
did not open. Wrapped each icon in a span.
2026-07-02 12:48:57 -04:00
SaelixCode ba702474bd fix: replace cursor-follow tooltip with standard Radix tooltip in sidebar rows
Replaced the Cursor/CursorFollow animate-ui primitives in StackRow
with the standard Radix Tooltip/TooltipTrigger/TooltipContent already
used throughout the app. The custom cursor dot that followed the mouse
is gone; tooltips now appear as static popovers on hover/touch.
2026-07-02 12:35:37 -04:00
SaelixCode ea02762f0a fix: improve masthead rail glow visibility
Replaced the invisible inset box-shadow glow (10px blur inside a 3px
element) with a white overlay that pulses opacity 0.15-0.55 over 4s.
Sped up glow animation from 5.5s to 4s for a more noticeable breath.
2026-07-02 12:19:07 -04:00
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
SaelixCode 715cc88362 fix: increase masthead rail shimmer visibility
Bumped shimmer highlight opacity from 25% to 50% and reduced
animation duration from 11s to 5s, matching the login page
AuthCanvas shimmer precedent (via-white/60 at 4.5s).
2026-07-02 11:12:11 -04:00
Anso c3dcf31cc8 fix: wrap auto-heal policy history in stack monitor sheet (#1538)
* fix: wrap auto-heal policy history in stack monitor sheet

Restructure PolicyRow history entries to stack vertically with break-words
so long container names and reasons stay inside the sheet width.

Fixes #1532

* fix: cap auto-heal policy history to a scrollable region

Recent activity could grow the policy row unbounded, pushing the
add-new-policy form far down the sheet when a policy accumulated many
history entries. Wrap the list in a fixed-height ScrollArea so it
scrolls internally instead.
2026-07-01 14:31:54 -04:00
dependabot[bot] 00a323252d chore(deps): bump the all-npm-frontend group (#1543)
Bumps the all-npm-frontend group in /frontend with 25 updates:

| Package | From | To |
| --- | --- | --- |
| [@radix-ui/react-alert-dialog](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/alert-dialog) | `1.1.17` | `1.1.18` |
| [@radix-ui/react-checkbox](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/checkbox) | `1.3.5` | `1.3.6` |
| [@radix-ui/react-context-menu](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/context-menu) | `2.3.1` | `2.3.2` |
| [@radix-ui/react-dialog](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/dialog) | `1.1.17` | `1.1.18` |
| [@radix-ui/react-dropdown-menu](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/dropdown-menu) | `2.1.18` | `2.1.19` |
| [@radix-ui/react-hover-card](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/hover-card) | `1.1.17` | `1.1.18` |
| [@radix-ui/react-label](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/label) | `2.1.10` | `2.1.11` |
| [@radix-ui/react-popover](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/popover) | `1.1.17` | `1.1.18` |
| [@radix-ui/react-scroll-area](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/scroll-area) | `1.2.12` | `1.2.13` |
| [@radix-ui/react-select](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/select) | `2.3.1` | `2.3.2` |
| [@radix-ui/react-separator](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/separator) | `1.1.10` | `1.1.11` |
| [@radix-ui/react-slider](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/slider) | `1.4.1` | `1.4.2` |
| [@radix-ui/react-tabs](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/tabs) | `1.1.15` | `1.1.16` |
| [@radix-ui/react-tooltip](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/tooltip) | `1.2.10` | `1.2.11` |
| [cronstrue](https://github.com/bradymholt/cRonstrue) | `3.21.0` | `3.24.0` |
| [lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react) | `1.21.0` | `1.23.0` |
| [motion](https://github.com/motiondivision/motion) | `12.41.0` | `12.42.2` |
| [radix-ui](https://github.com/radix-ui/primitives/tree/HEAD/packages/react/radix-ui) | `1.6.0` | `1.6.1` |
| [recharts](https://github.com/recharts/recharts) | `3.9.0` | `3.9.1` |
| [@tailwindcss/vite](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/@tailwindcss-vite) | `4.3.1` | `4.3.2` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.0.0` | `26.1.0` |
| [eslint](https://github.com/eslint/eslint) | `10.5.0` | `10.6.0` |
| [tailwindcss](https://github.com/tailwindlabs/tailwindcss/tree/HEAD/packages/tailwindcss) | `4.3.1` | `4.3.2` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.62.0` | `8.62.1` |
| [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.1.0` | `8.1.2` |


Updates `@radix-ui/react-alert-dialog` from 1.1.17 to 1.1.18
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/alert-dialog/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/alert-dialog)

Updates `@radix-ui/react-checkbox` from 1.3.5 to 1.3.6
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/checkbox/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/checkbox)

Updates `@radix-ui/react-context-menu` from 2.3.1 to 2.3.2
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/context-menu/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/context-menu)

Updates `@radix-ui/react-dialog` from 1.1.17 to 1.1.18
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/dialog/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/dialog)

Updates `@radix-ui/react-dropdown-menu` from 2.1.18 to 2.1.19
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/dropdown-menu/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/dropdown-menu)

Updates `@radix-ui/react-hover-card` from 1.1.17 to 1.1.18
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/hover-card/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/hover-card)

Updates `@radix-ui/react-label` from 2.1.10 to 2.1.11
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/label/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/label)

Updates `@radix-ui/react-popover` from 1.1.17 to 1.1.18
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/popover/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/popover)

Updates `@radix-ui/react-scroll-area` from 1.2.12 to 1.2.13
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/scroll-area/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/scroll-area)

Updates `@radix-ui/react-select` from 2.3.1 to 2.3.2
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/select/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/select)

Updates `@radix-ui/react-separator` from 1.1.10 to 1.1.11
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/separator/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/separator)

Updates `@radix-ui/react-slider` from 1.4.1 to 1.4.2
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/slider/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/slider)

Updates `@radix-ui/react-tabs` from 1.1.15 to 1.1.16
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/tabs/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/tabs)

Updates `@radix-ui/react-tooltip` from 1.2.10 to 1.2.11
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/tooltip/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/tooltip)

Updates `cronstrue` from 3.21.0 to 3.24.0
- [Release notes](https://github.com/bradymholt/cRonstrue/releases)
- [Changelog](https://github.com/bradymholt/cRonstrue/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bradymholt/cRonstrue/compare/v3.21.0...v3.24.0)

Updates `lucide-react` from 1.21.0 to 1.23.0
- [Release notes](https://github.com/lucide-icons/lucide/releases)
- [Commits](https://github.com/lucide-icons/lucide/commits/1.23.0/packages/lucide-react)

Updates `motion` from 12.41.0 to 12.42.2
- [Changelog](https://github.com/motiondivision/motion/blob/main/CHANGELOG.md)
- [Commits](https://github.com/motiondivision/motion/compare/v12.41.0...v12.42.2)

Updates `radix-ui` from 1.6.0 to 1.6.1
- [Changelog](https://github.com/radix-ui/primitives/blob/main/packages/react/radix-ui/CHANGELOG.md)
- [Commits](https://github.com/radix-ui/primitives/commits/HEAD/packages/react/radix-ui)

Updates `recharts` from 3.9.0 to 3.9.1
- [Release notes](https://github.com/recharts/recharts/releases)
- [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/recharts/recharts/compare/v3.9.0...v3.9.1)

Updates `@tailwindcss/vite` from 4.3.1 to 4.3.2
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.2/packages/@tailwindcss-vite)

Updates `@types/node` from 26.0.0 to 26.1.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 10.5.0 to 10.6.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v10.5.0...v10.6.0)

Updates `tailwindcss` from 4.3.1 to 4.3.2
- [Release notes](https://github.com/tailwindlabs/tailwindcss/releases)
- [Changelog](https://github.com/tailwindlabs/tailwindcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tailwindlabs/tailwindcss/commits/v4.3.2/packages/tailwindcss)

Updates `typescript-eslint` from 8.62.0 to 8.62.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.62.1/packages/typescript-eslint)

Updates `vite` from 8.1.0 to 8.1.2
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.1.2/packages/vite)

---
updated-dependencies:
- dependency-name: "@radix-ui/react-alert-dialog"
  dependency-version: 1.1.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-checkbox"
  dependency-version: 1.3.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-context-menu"
  dependency-version: 2.3.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-dialog"
  dependency-version: 1.1.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-dropdown-menu"
  dependency-version: 2.1.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-hover-card"
  dependency-version: 1.1.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-label"
  dependency-version: 2.1.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-popover"
  dependency-version: 1.1.18
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-scroll-area"
  dependency-version: 1.2.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-select"
  dependency-version: 2.3.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-separator"
  dependency-version: 1.1.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-slider"
  dependency-version: 1.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-tabs"
  dependency-version: 1.1.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@radix-ui/react-tooltip"
  dependency-version: 1.2.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: cronstrue
  dependency-version: 3.24.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-npm-frontend
- dependency-name: lucide-react
  dependency-version: 1.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-npm-frontend
- dependency-name: motion
  dependency-version: 12.42.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: all-npm-frontend
- dependency-name: radix-ui
  dependency-version: 1.6.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: recharts
  dependency-version: 3.9.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@tailwindcss/vite"
  dependency-version: 4.3.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: "@types/node"
  dependency-version: 26.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: all-npm-frontend
- dependency-name: eslint
  dependency-version: 10.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: all-npm-frontend
- dependency-name: tailwindcss
  dependency-version: 4.3.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: typescript-eslint
  dependency-version: 8.62.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
- dependency-name: vite
  dependency-version: 8.1.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: all-npm-frontend
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-01 12:48:56 -04:00
Anso d80538f254 fix(deps): patch frontend dompurify and @babel/core advisories (#1539)
Bump the frontend dependency overrides to force patched versions of two
packages flagged by security advisories:

- dompurify: monaco-editor pins 3.2.7, which the existing override raised
  only to 3.4.1. Raise the override to ^3.4.11 so the resolved version is
  3.4.11, clearing eight dompurify advisories (IN_PLACE and template
  sanitization bypasses, hook/config pollution, Trusted Types poisoning).
- @babel/core: force the transitive build-time dependency from 7.29.0 to
  ^7.29.6 (resolves to 7.29.7), clearing the sourceMappingURL arbitrary
  file read advisory. Its consumers accept ^7.0.0 / ^7.24.4.

dompurify is not imported in application code; it reaches the bundle only
through monaco-editor, so the override is the correct control point.

Lock churn is limited to the @babel/* subtree, the browserslist toolchain
data packages, and dompurify. Typecheck, production build, and the full
frontend test suite (1613 tests) pass.
2026-07-01 12:47:55 -04:00
Anso 60de0ddec2 fix(deploy-modal): hide frozen countdown label in inline feedback style (#1534)
In inline deploy feedback style, the auto-close countdown label
("closes in Xs") was visible but permanently frozen. canAutoClose
was already false in inline style (the banner owns the lifecycle),
but showCountdown was driven by !gateHoldsOpen, showing the label
even when no countdown timer could ever start.

Change showCountdown to canAutoClose so the label only appears
when the modal is actually eligible to auto-close (modal style,
succeeded, no observing gate). No gate contracts or modal-style
behavior change.

Adds regression tests: inline succeeded hides the label, modal
succeeded shows it.
2026-07-01 02:54:22 -04:00
Anso 90c69b1ea4 fix: reflect toggle state in scheduled task Enabled/Disabled label (#1533)
The New/Edit Scheduled Task modal always showed "Enabled" next to the
task toggle regardless of its on/off state. The label now tracks
formEnabled, matching the existing Enabled/Disabled label convention
used in the Stacks settings section.
2026-07-01 02:42:52 -04:00
Anso e1176fbb26 fix: make auth canvas scroll actually constrain on short viewports (#1523)
PR #1521 added max-height and overflow-y-auto but the card stayed content-
sized because flex items default to min-height:auto and justify-center
clipped overflow while html/body stay overflow:hidden. Add min-h-0 and
my-auto, use dvh, scroll the auth shell, and pin Enter Sencho outside the
preflight scroll region.
2026-06-29 21:13:32 -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 da73ee0717 fix: scroll auth canvas when preflight content overflows (#1521)
Cap the auth card height and scroll its body so setup preflight checks
remain reachable on short viewports without clipping the Enter action.
2026-06-29 20:28:51 -04:00
Anso 1b9a40f874 fix: align notification unread badge with panel visibility rules (#1520)
Stack success events were hidden from the panel but still counted unread on the bell and dashboard.

Share one visibility helper across badge, panel, and Recent Alerts.

Harden mark-all-read against partial API failures.

Fixes #1513
2026-06-29 18:19:18 -04:00
Anso 89b9341568 fix: replace Janitor wording with reclaim/prune actions in user-facing copy (#1518)
Rename "Janitor threshold" to "Reclaimable Docker data threshold" in Settings
and update the unused-Docker-data alert to point users to the Resources view
and the Prune Node Resources scheduled action, which are the real UI surfaces
for reclaiming disk space. Remove "janitor" from settings search keywords.
The internal docker_janitor_gb database key and JANITOR_* constants are
unchanged.
2026-06-29 15:23:19 -04:00
Anso 41dc339c26 fix: enforce 1:1 compose path mapping for Pilot agent mounts (#1516)
* fix: enforce 1:1 compose path mapping for Pilot agent mounts

Pilot enrollment now generates validated 1:1 bind mounts so every
agent path maps to a unique compose directory. Persisted agent paths
reconcile during startup to catch drift. Unsafe relative-bind redeploys
are blocked before container removal to prevent path escapes.

- Add composePathMapping utility with strict path validation
- Generate COMPOSE_DIR and validated mounts during Pilot enrollment
- Reconcile persisted agent paths during startup bootstrap
- Block redeploy when a relative-bind mount would escape the compose root
- Default Pilot UI path to /opt/docker/sencho
- Update multi-node and pilot-agent documentation
- Add regression tests for enrollment, bootstrap, compose-service,
  and environment-check paths

* fix: update E2E enrollment regexes for YAML-quoted token values
2026-06-29 14:35:50 -04:00
Anso 8bec32dea6 fix: stack the volume browser panels on phones so the file preview is readable (#1512)
On phone widths the volume browser kept its fixed 260px tree column beside the
preview, leaving the preview roughly 54px wide so file content wrapped to one or
two characters per line. Below the md breakpoint the two panels now stack into a
single column (tree above, preview below) with the tree capped at 40% of the
height, so the preview spans the full width. Desktop and tablet layouts are
unchanged.
2026-06-28 22:04:44 -04:00
Anso e9c2c0cf8e fix: classify degraded remote stacks as partial on the compatibility path (#1511)
When a remote node's bulk /stacks/statuses is unavailable or returns the
legacy plain-string format, the sidebar derived a stack's status from its
containers by treating "any container running" as healthy. A stack with one
running and one crashed container was shown green UP and excluded from the
Down filter.

Re-derive status from the per-stack container list in both compatibility
cases, mirroring the backend classifier: a stack with a running container and
a genuinely crashed one (dead, or exited/restarting with a non-zero code) is
now partial, while a cleanly finished one-shot container (exit 0) stays
running. Legacy plain-string bulk responses are routed through this path too,
since they have already collapsed the degraded case.
2026-06-28 22:01:38 -04:00
Anso 997a6bb79a fix: gate cross-node HTTP and stop-by-label on remote RBAC capability (#1509)
An older remote node ignores the forwarded actor-role header (running proxied
requests as admin) and ignores the stop-by-label stack allowlist (stopping
every label-matched stack). The control could neither detect nor prevent this
on a mixed-version fleet.

Instances now advertise a cross-node-rbac capability, and the control refuses
to act when a remote lacks it:

- HTTP proxy: a non-admin user's request is not forwarded to a remote that does
  not advertise the capability (fails closed when it cannot be determined).
  Admins are unaffected.
- Stop-by-label: a real stop bound to a confirmed stack set is not sent to a
  remote lacking the capability; the node is reported as needing an upgrade. As
  defense in depth, a node whose results name stacks outside the confirmed set
  is failed rather than rendered as a clean stop.

Separately, the stop's lock-contention path now reports every confirmed stack
as a contention failure (including one that lost its label), so a confirmed
stack is never silently dropped and the result is never empty.
2026-06-28 18:28:47 -04:00
Anso dd76b13d55 fix: require node:read for fleet topology reads and hide Fleet without it (#1507)
The fleet overview, configuration, dependency-map, and networking-summary reads
were authentication-only, so a role without node:read (deployer) could read node
names, host stats, and cross-node topology. They now require node:read, matching
the role model where every role except deployer holds it.

For parity, the Fleet nav entry is gated on node:read (hiding it from the top
nav, mobile menu, and command palette), the Fleet view redirects to the
dashboard when reached without it, and the dashboard fleet heartbeat falls back
to the single-node restart map for a role that cannot read fleet data.
2026-06-28 16:39:11 -04:00
Anso 1dc12f7da8 fix: bind fleet stop-by-label to the exact confirmed nodes and stacks (#1506)
A fleet stop re-matched stacks by label name at execution, so a stack that
gained the label between the operator's preview and confirmation could be
stopped even though it never appeared in the confirmation. A confirmed node
that was deleted after the preview also vanished from the results, letting the
remaining successes read as a clean stop.

The confirm flow now sends the exact node and stack list resolved in the
preview. Each node's stop is bound to that set: only stacks that are still
label-matched and confirmed are stopped, and a confirmed node missing from the
registry is reported as an explicit failure rather than dropped.
2026-06-28 16:33:01 -04:00
Anso d6ce60d280 fix: make Reduced motion gate overlays, standardize the tab band, and polish fleet/snapshots (#1504)
* fix: address review feedback on motion, fleet band, and snapshots

- Reduced motion now also skips the animate-ui overlay open/close animations
  (dialog, sheet, popover, dropdown-menu) via a shared useReducedTransition that
  zeroes the transition when reduced motion is active; MotionConfig alone only
  neutralized transform/layout, leaving the opacity/blur fade.
- Fleet tab band: flatten the list's own pill band so the tabs sit in a single
  full-width band instead of a nested second band.
- Fleet Overview: label the node-update button "Node Update"; the add-node
  button becomes a ChartNetwork icon that opens Settings > Nodes (outline style,
  matching the node-update button) instead of the add-node modal.
- Blueprint deployments empty state: drive the serif headings from the theme
  heading-style token so Calm drops the italic.
- Snapshots: move the per-stack Restore onto the stack header row (right side),
  matching the ghost action style.

* feat: standardize the tab band on Security and add a tab hover state

- Apply the Fleet full-width tab band to the Security page (single band, the
  list's pill background flattened so the tabs sit directly in it).
- Add a hover highlight to tabs so the band reads as interactive, not flat;
  the active tab is unaffected.

* fix: drive reduced-motion transitions from the app setting, not the OS query

useReducedTransition called framer-motion's useReducedMotion(), which only
reflects the OS prefers-reduced-motion media query and ignores our MotionConfig
/ appearance toggle, so dialogs kept animating with the setting on. Read the
app's useReducedMotion selector instead. Verified: with the setting on, the
dialog opacity snaps 0->1 in one frame; with it off, it ramps over the spring.

* feat: standardize stack-detail body text to text-xs and add a log expand toggle

- Bump the anatomy panel body text (rows, field values, warnings) and the
  structured log lines from 10/11/12px to text-xs (12px), leaving the uppercase
  kicker labels and the log level/source badges as-is.
- Add an expand control next to the log download button that collapses the
  Command Center so the logs pane fills the left column; toggles back to restore.
2026-06-28 08:17:34 -04:00
Anso 04e69021e0 feat: make all security features available on every tier (#1502)
Scan policies, deploy enforcement, the suppression-aware deploy-block
toggle, SARIF export, and OpenVEX export now work on Community, matching
the rest of the vulnerability-scanning surface that was already free.

Backend: drop the tier gate from the seven security routes and from the
dashboard configuration-status scan-policies row, so the Dashboard and
Fleet config cards stop hiding the Vulnerability scanning row. Reading
policies stays auth-only; mutations and exports stay admin-only.

Frontend: always show the Policies tab and panel, the SARIF and VEX
export actions, and the honor-suppressions toggle for admins.

Docs: move scan policies, SARIF, and OpenVEX to every tier across the
feature and API-reference pages; clarify that Fleet Sync's cross-node
replication remains the paid part.
2026-06-28 08:14:21 -04:00
Anso 05c483f213 fix: harden cross-node fleet label actions and guard container reads (#1503)
* fix: harden cross-node fleet label actions and guard container reads

Release-stabilization fixes for the Fleet Actions surface:

- Stop-by-label binds execution to the nodes shown in the confirmed
  preview. The real stop sends the confirmed node ids and the backend
  restricts the fan-out to them, so a node that was unreachable during
  preview and reconnects before the stop can no longer enter execution
  and have unlisted stacks stopped.
- Bulk label assign validates each remote node's result against the
  stacks it was asked to label: a body whose results are empty, partial,
  duplicated, or shaped wrong is a per-node failure instead of reading as
  a successful zero-stack assign. The card mirrors this, rejecting a
  missing or non-array results body and only reporting success when at
  least one stack was assigned.
- Bulk label assign re-reads authoritative per-node stacks and labels on
  demand via a Refresh control, and the confirmation lists the affected
  node and stack names rather than bare counts.
- The stack-specific and fleet container/stack read routes require the
  stack:read permission, matching the generic container and stack routes.
  Every shipped role already carries stack:read, so reachability is
  unchanged; the guard closes the routes that were auth-only.

Adds unit coverage for the assign-result validator, route coverage for
the stop allowlist and assign membership checks, and authorization
coverage for the newly guarded reads.

* test: assert the confirmed node allowlist in the fleet stop-card test

The stop-card component test pinned the real-stop request body to
{ labelName, dryRun } and broke once the stop began carrying the
confirmed-preview node ids. Update it to expect the nodeIds allowlist
derived from the resolved preview, so the test asserts the binding
rather than the pre-fix shape.
2026-06-28 08:13:43 -04:00
Anso b5810a9b55 feat: add Reduced motion setting and polish chrome, files, and stack-detail (#1501)
A batch of UI/UX polish:

- New independent "Reduced motion" appearance setting (separate from Reduced
  effects). Drives framer-motion via MotionConfig and clamps CSS transitions via
  data-motion on <html>; toasts are unaffected. Defaults off (OS preference
  still honored).
- Stack-detail Files tab: rename "Files & Volumes" to "Files", add a persisted
  word-wrap toggle to the file viewer (default on), and add a fullscreen toggle
  that collapses the Command Center + Logs column so the editor fills the width.
- Create Stack > From Git: remove the nested scroll clamp so the deploy toggle
  and footer are reachable.
- Fleet: full-width tab band with icon-only Refresh / Export Dossier, icon-only
  Check-for-updates / Add-node on the Overview toolbar, theme-aware empty-state
  headings (calm drops the italic), and fix the Actions card body overlapping
  the action-row divider.
- Snapshots: restyle Restore and Restore all to the ghost button design used by
  View / Preview / Download, and right-align the per-stack Restore.
- Settings sidebar: App Store gradient active style and standard font size.
- Compose Doctor: dismiss the high-risk banner (and clear the tab dot) until the
  findings change, via a shared fingerprint-keyed hook.
- Stack-detail Storage: link the "no recent fleet snapshot" warning to the Fleet
  Snapshots tab (FleetView tabs are now controlled to support the deep link).
2026-06-28 06:18:02 -04:00