mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-19 23:06:49 +00:00
2a29fed11703e98f39dd239b205ae8ac69888706
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bb44db0cb1 |
refactor(sidebar): rebuild footer as priority-driven Ops Pulse strip (#1178)
* refactor(sidebar): rebuild footer as priority-driven Ops Pulse strip Replace the simple notification ticker with a derived activity summary that picks one of six states (active-op, failure, automation, recent-event, quiet-live, disconnected) and routes per-state clicks to logs, schedules, or activity. The hook owns the cascade; the component is pure presentation; EditorLayout owns wiring. Failure detection covers unread errors in the last 24h; recent-event is limited to non-error stack notifications in the last hour; automation reads the next /scheduled-tasks?action=update run and a debounced state-invalidate listener; the deploy-panel composite key is used for elapsed-time tracking so close-then-immediately-reopen counts as a new session. * refactor(sidebar): apply Ops Pulse audit fixes - countEnabledAutoUpdates now defaults missing autoUpdateSettings entries to enabled, matching the backend's getStackAutoUpdateSettingsForNode contract. Previously the automation state could not render even with the documented per-row default-true. - findFailure now requires a stack_name so the sidebar does not select a system-level error whose click would no-op through navigateToNotification. System errors continue to surface via the top-bar NotificationPanel. - DeployPanelState gains a monotonic sessionId sourced from the existing internal counter, and the new usePanelSessionStartedAt hook keys the elapsed-time tracker off it so a same-stack rerun always resets even when isOpen stays true across succeeded then preparing. - buildConfig splits quiet-live out of the default and adds an exhaustiveness guard so future SidebarActivitySummary variants fail to compile. - New unit tests cover the default-true aggregation, the same-stack session reset, the non-stack failure guard, and the useNextAutoUpdateRun debounce and cleanup paths. Frontend suite: 276 / 276 pass. |
||
|
|
166ba21ff1 |
feat(sidebar): filter toggle + action button padding fix (#933)
* feat: open security basics, manual fleet ops, and basic fleet management to Community
Realign tier guards to the user-stated philosophy: Community covers
deploy/monitor at scale plus security basics, Skipper adds automation
and advanced fleet management, Admiral keeps enterprise control.
Community now includes:
- Trivy install / uninstall / update from the Settings Hub (admin role)
- CVE suppressions CRUD (admin role; replicates fleet-wide)
- Manual image scan with vuln, secret, and misconfig results
- Stack-config scan, scan comparison
- Manual fleet snapshots: create, list, view, restore, delete
- Per-node Sencho self-update (Check Updates + per-node Update)
- Fleet Overview search, sort, filters, node-card expand, auto-refresh
Stays paid:
- Scan policies with block_on_deploy enforcement (Skipper+)
- SBOM (SPDX, CycloneDX), SARIF export (Skipper+)
- Bulk Update All across the fleet (Skipper+)
- Scheduled snapshot create (now Skipper, was Admiral)
- Trivy auto-update toggle, fleet-wide policy push (Admiral)
The Settings -> Security tab is unhidden by setting the registry tier to
null. The SecuritySection no longer early-returns a PaidGate; the policy
list, Add Policy button, and policy dialogs are wrapped in {isPaid && }.
The Fleet view drops isPaid gates on the Snapshots tab, Check Updates
button, per-node update handlers, OverviewToolbar grid controls, the
NodeCard expand affordance, and the auto-refresh notice. The
NodeUpdatesSheet receives a canBulkUpdate prop and gates the Update All
button on it. useFleetUpdateStatus and useFleetPolling drop their isPaid
guards so polling runs for Community; useFleetOverview drops the isPaid
wrap on the filter and sort path.
Backend route guards are flipped per the matrix above. The scheduler
tick and requireScheduledTaskTier add 'snapshot' to the Skipper+ branch.
Backend test assertions are inverted for the now-Community endpoints
and a positive Skipper-snapshot-task test is added.
Documentation across features/, api-reference/, and operations/ is
updated to reflect the new tier mapping.
* feat: add node last-contact tracking, fleet latency, and stack-restart summary
- DatabaseService: add last_successful_contact column to nodes table via
idempotent migration; expose updateNodeLastContact() and getStackRestartSummary()
methods; include the column in NODE_COLUMNS so getNodes/getNode return it
- fleet.ts: record latency_ms and last_successful_contact on each remote
node overview fetch; pilot-agent nodes surface pilot_last_seen instead;
pass db singleton into fetchRemoteNodeOverview to avoid redundant getInstance calls
- dashboard.ts: replace /recent-activity with /stack-restarts endpoint that
groups notification_history events by stack and category (crash/autoheal/manual)
over a configurable window (default 7 days, max 30)
* refactor(dashboard): remove redundant per-route authMiddleware
All routes under /api/ are covered by the global auth gate in app.ts.
The inline authMiddleware arguments on /configuration and /stack-restarts
were redundant with that gate and inconsistent with every other route in
the file. Remove them and drop the now-unused import.
* refactor(backend): consolidate Date.now(), move SQL aggregation, normalize node row mapping
- Capture a single completedAt timestamp in fetchRemoteNodeOverview to
eliminate two separate Date.now() calls and ensure latency_ms and
last_successful_contact are derived from the same instant
- Inline the redundant contactedAt variable; use completedAt directly
- Move stack-restart aggregation from JS into SQL (GROUP BY stack_name
with CASE/SUM counts), replacing the Map loop in the route handler
- Export StackRestartSummary interface from DatabaseService and remove
the duplicate local definition in dashboard.ts; handler now returns
the query result directly
- Add last_successful_contact normalization in decryptNodeRow, mirroring
the existing pilot_last_seen pattern
- Add authGate reliance comment above dashboardRouter route handlers
* feat(dashboard): replace Recent Activity card with context-aware Fleet Heartbeat / Stack Restart Map
- Multi-node installs (≥1 remote node): shows Fleet Heartbeat — real-time
reachability, latency, and container count per registered node
- Local-only installs: shows Stack Restart Map — 7-day restart frequency
per stack grouped by crash / auto-heal / manual category
- Conditional wrapper (DashboardActivityCard) switches states automatically
when the node list changes, with no page reload required
- Deletes RecentActivity card and hook (duplicated data already in Recent Alerts)
- Extracts formatRelativeTime to frontend/src/lib/utils.ts for reuse
* fix(dashboard): add pilot_last_seen to FleetNodeOverview and use it in getLastSeenLabel
* fix(fleet): expose mode and pilot_last_seen in overview, consolidate formatRelativeTime, drop em dash
- Add `mode` and `pilot_last_seen` (in seconds) to the FleetNodeOverview
interface and to both the pilot-agent and HTTP-proxy return paths in
fetchRemoteNodeOverview so the frontend getLastSeenLabel pilot branch
can fire correctly
- Remove the private formatRelativeTime from RecentAlerts.tsx and use
the shared implementation from lib/utils, converting the millisecond
timestamp at the call site
- Replace the em dash in getLatencyLabel with 'n/a' per project rules
* feat(sidebar): add filter toggle and fix action button padding
- Add collapsible filter chip row in SidebarFilterChips with Plus/Minus
toggle button pinned to the far right of the row
- Persist expanded/collapsed state across reloads via localStorage key
sencho:sidebar:filters-visible (default expanded)
- Active filter chip stays applied while the row is hidden; hiding is
purely a visual noise reduction and does not reset the filter
- Fix flex overflow in SidebarActions by adding min-w-0 to the flex-1
wrapper around the Create Stack slot, restoring the correct 16px right
padding on the scan button
- Cap displayed counts at 99+ to bound chip render width; chips use
min-w-0 overflow-hidden instead of shrink-0 so they flex-shrink
proportionally rather than hard-clipping the last chip
* test: resolve failing CI tests and act warnings (#933)
- Fix SidebarActivityTicker to properly filter out stale activities
- Update StackGroup test to handle pinned star prefixes
- Refactor useNotifications tests to use waitFor and suppress un-awaitable act() warnings
* fix: add missing beforeAll/afterAll imports to useNotifications test
The tsc build step failed because beforeAll and afterAll were used but
not imported from vitest, unlike the other vitest functions already in
the import statement.
* fix: resolve ESLint errors in test and sidebar files
Replace any[] with unknown[] in useNotifications.test.ts console.error
mock, and add a comment to the empty catch block in StackSidebar.tsx.
|
||
|
|
f94b2ce85c |
fix(sidebar): remove 1-hour staleness filter from activity ticker (#786)
Show the most recent stack event regardless of age. The ticker now stays populated as long as any event arrived in the current session, with formatTimeAgo reflecting the true elapsed time (e.g. '2h ago'). Idle state only appears when no events have arrived yet. Also reduces the update interval from 30s to 10s so relative timestamps stay responsive. |
||
|
|
370b67d7ec |
feat(sidebar): cockpit redesign with grouped stacks and activity footer (#702)
* chore: ignore .superpowers/ brainstorm scratch dir
* feat(sidebar): add useStackMenuItems hook with grouped menu model
Pure transform hook that converts StackMenuCtx into four ordered MenuGroup
arrays (inspect, organize, lifecycle, destructive). Shared type contract in
sidebar-types.ts gives both the ContextMenu and DropdownMenu a single source
of truth so they cannot drift. Covered by 8 unit tests.
* refactor(sidebar): stabilize useStackMenuItems memoization deps
Destructure menuVisibility flags into primitive deps so inline object
literals from callers do not defeat memoization. Add a test confirming
isBusy disables all lifecycle items.
* feat(sidebar): add usePinnedStacks hook with per-node localStorage
* refactor(sidebar): stabilize usePinnedStacks eviction signal and isPinned dep
Change evictedOldest shape to { file, seq } so consumer effects re-fire on
repeated evictions. Narrow isPinned's useCallback dep to the current node's
pinned list so it only rebinds on local changes. Add test for eviction
side-effect and a second test for the seq counter.
* feat(sidebar): add useSidebarGroupCollapse hook with per-node keys
* refactor(sidebar): tighten useSidebarGroupCollapse effect ordering
Collapse the two write/read effects into a single skip-next-write ref
pattern so switching nodes no longer writes the previous node's map under
the new key before hydration. Also skip the no-op mount write. Add test
for setCollapsed.
* feat(sidebar): add row + group-header style helpers
* feat(sidebar): add SidebarBrand with mono kicker + serif hero
* feat(sidebar): add SidebarActions wrapper for create + scan
* feat(sidebar): extract SidebarSearch with kbd pill
* feat(sidebar): add StackRow with cyan-rail active state
* refactor(sidebar): dedupe tooltip markup in StackRow, widen test coverage
Extract a local RowTooltip helper so the update and git-pending branches
share the CursorProvider scaffolding. Add four behavioral tests covering
click, keyboard activation, kebab stop-propagation, and the busy loader
branch.
* feat(sidebar): unify context + kebab menus via useStackMenuItems
* feat(sidebar): add StackGroup with collapse and pinned variant
* feat(sidebar): add StackList with pinned + label groups
* feat(sidebar): add SidebarActivityTicker with idle fallback
* feat(sidebar): add StackSidebar container composing the regions
* feat(sidebar): replace sidebar block with StackSidebar composition
* docs(sidebar): add stack sidebar feature page with screenshots
* fix(sidebar): satisfy react-hooks purity and memoization rules
* fix(sidebar): restore "Sencho Logo" alt text for E2E selector
|