mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-12 19:57:37 +00:00
fix: update Configuration Status card labels and add new rows
Notifications section: renamed Notification agents to Channels, Notification routing to Routing, added Mute Rules row linking to notification-suppression settings. Security section: added Trivy installed Yes/No row, renamed Vulnerability scanning to Scan policies. Backend: added trivyInstalled and suppressionRules fields to the /dashboard/configuration payload.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Router, type Request, type Response } from 'express';
|
||||
import { DatabaseService, type StackRestartSummary } from '../services/DatabaseService';
|
||||
import { CloudBackupService } from '../services/CloudBackupService';
|
||||
import TrivyService from '../services/TrivyService';
|
||||
import { effectiveTier } from '../middleware/tierGates';
|
||||
import { isDebugEnabled } from '../utils/debug';
|
||||
import type { LicenseTier } from '../services/license-types';
|
||||
@@ -18,6 +19,7 @@ export interface ConfigurationStatus {
|
||||
agents: { discord: AgentStatus; slack: AgentStatus; webhook: AgentStatus };
|
||||
alertRules: number;
|
||||
routingRules: { count: number; enabledCount: number; locked: boolean };
|
||||
suppressionRules: { total: number; enabledCount: number };
|
||||
};
|
||||
automation: {
|
||||
autoHeal: { total: number; enabled: number };
|
||||
@@ -29,6 +31,7 @@ export interface ConfigurationStatus {
|
||||
mfaEnabled: boolean | null;
|
||||
ssoEnabled: boolean;
|
||||
ssoProvider: string | null;
|
||||
trivyInstalled: boolean;
|
||||
scanPolicies: { total: number; enabled: number; locked: boolean };
|
||||
};
|
||||
thresholds: {
|
||||
@@ -101,6 +104,10 @@ export function buildLocalConfigurationStatus(
|
||||
enabledCount: notifRoutes.filter(r => r.enabled).length,
|
||||
locked: false,
|
||||
},
|
||||
suppressionRules: (() => {
|
||||
const rules = db.getNotificationSuppressionRules();
|
||||
return { total: rules.length, enabledCount: rules.filter(r => r.enabled).length };
|
||||
})(),
|
||||
},
|
||||
automation: {
|
||||
autoHeal: {
|
||||
@@ -128,6 +135,7 @@ export function buildLocalConfigurationStatus(
|
||||
mfaEnabled: mfaRow ? mfaRow.enabled === 1 : null,
|
||||
ssoEnabled: !!enabledSso,
|
||||
ssoProvider: enabledSso?.provider ?? null,
|
||||
trivyInstalled: TrivyService.getInstance().getSource() !== 'none',
|
||||
// Scan policies are available on every tier.
|
||||
scanPolicies: {
|
||||
total: scanPolicies.length,
|
||||
|
||||
@@ -141,7 +141,7 @@ export function ConfigurationStatus({ onOpenSection }: ConfigurationStatusProps
|
||||
<CardContent className="pt-0">
|
||||
<div className="space-y-0">
|
||||
<SectionHeader icon={Bell} label="Notifications" />
|
||||
<Row label="Notification agents" value={agentSummary} onClick={open('notifications')} />
|
||||
<Row label="Channels" value={agentSummary} onClick={open('notifications')} />
|
||||
<Row
|
||||
label="Alert rules"
|
||||
value={formatCount(notifications.alertRules, 'rule')}
|
||||
@@ -149,11 +149,16 @@ export function ConfigurationStatus({ onOpenSection }: ConfigurationStatusProps
|
||||
/>
|
||||
{!notifications.routingRules.locked && (
|
||||
<Row
|
||||
label="Notification routing"
|
||||
label="Routing"
|
||||
value={formatCount(notifications.routingRules.enabledCount, 'route')}
|
||||
onClick={open('notification-routing')}
|
||||
/>
|
||||
)}
|
||||
<Row
|
||||
label="Mute Rules"
|
||||
value={formatCount(notifications.suppressionRules.enabledCount, 'rule')}
|
||||
onClick={open('notification-suppression')}
|
||||
/>
|
||||
|
||||
<SectionHeader icon={Zap} label="Automation" />
|
||||
<Row
|
||||
@@ -188,9 +193,13 @@ export function ConfigurationStatus({ onOpenSection }: ConfigurationStatusProps
|
||||
onClick={open('account')}
|
||||
/>
|
||||
<Row label="SSO" value={ssoLabel} onClick={open('sso')} />
|
||||
<Row
|
||||
label="Trivy installed"
|
||||
value={security.trivyInstalled ? 'Yes' : 'No'}
|
||||
/>
|
||||
{!security.scanPolicies.locked && (
|
||||
<Row
|
||||
label="Vulnerability scanning"
|
||||
label="Scan policies"
|
||||
value={formatCount(security.scanPolicies.enabled, 'policy')}
|
||||
onClick={() => window.dispatchEvent(
|
||||
new CustomEvent<SenchoNavigateDetail>(SENCHO_NAVIGATE_EVENT, { detail: { view: 'security', tab: 'policies' } }),
|
||||
|
||||
@@ -20,6 +20,7 @@ function makePayload(overrides: Partial<ConfigurationStatusPayload> = {}): Confi
|
||||
},
|
||||
alertRules: 0,
|
||||
routingRules: { count: 0, enabledCount: 0, locked: true },
|
||||
suppressionRules: { total: 0, enabledCount: 0 },
|
||||
},
|
||||
automation: {
|
||||
autoHeal: { total: 0, enabled: 0 },
|
||||
@@ -31,6 +32,7 @@ function makePayload(overrides: Partial<ConfigurationStatusPayload> = {}): Confi
|
||||
mfaEnabled: null,
|
||||
ssoEnabled: false,
|
||||
ssoProvider: null,
|
||||
trivyInstalled: false,
|
||||
scanPolicies: { total: 0, enabled: 0, locked: false },
|
||||
},
|
||||
thresholds: { cpuLimit: 90, ramLimit: 90, diskLimit: 90, dockerJanitorGb: 5, globalCrash: false, hostAlertsEnabled: true },
|
||||
@@ -68,11 +70,11 @@ describe('ConfigurationStatus row visibility', () => {
|
||||
expect(screen.getByText('Auto-heal policies')).toBeDefined();
|
||||
expect(screen.getByText('Auto-update schedules')).toBeDefined();
|
||||
// Rows whose payload reports locked stay hidden.
|
||||
expect(screen.queryByText('Notification routing')).toBeNull();
|
||||
expect(screen.queryByText('Routing')).toBeNull();
|
||||
expect(screen.queryByText('Webhooks')).toBeNull();
|
||||
expect(screen.queryByText('Scheduled tasks')).toBeNull();
|
||||
// Scan policies are free, so the Vulnerability scanning row renders.
|
||||
expect(screen.getByText('Vulnerability scanning')).toBeDefined();
|
||||
// Scan policies are free, so the row renders.
|
||||
expect(screen.getByText('Scan policies')).toBeDefined();
|
||||
// Cloud Backup row is universal (Custom S3 is open to every tier).
|
||||
expect(screen.getByText('Cloud Backup')).toBeDefined();
|
||||
});
|
||||
@@ -89,6 +91,7 @@ describe('ConfigurationStatus row visibility', () => {
|
||||
},
|
||||
alertRules: 2,
|
||||
routingRules: { count: 1, enabledCount: 1, locked: false },
|
||||
suppressionRules: { total: 0, enabledCount: 0 },
|
||||
},
|
||||
automation: {
|
||||
autoHeal: { total: 3, enabled: 2 },
|
||||
@@ -100,6 +103,7 @@ describe('ConfigurationStatus row visibility', () => {
|
||||
mfaEnabled: true,
|
||||
ssoEnabled: true,
|
||||
ssoProvider: 'oidc_google',
|
||||
trivyInstalled: true,
|
||||
scanPolicies: { total: 2, enabled: 2, locked: false },
|
||||
},
|
||||
}),
|
||||
@@ -110,10 +114,10 @@ describe('ConfigurationStatus row visibility', () => {
|
||||
expect(screen.getByText('Automation')).toBeDefined();
|
||||
expect(screen.getByText('Auto-heal policies')).toBeDefined();
|
||||
expect(screen.getByText('Auto-update schedules')).toBeDefined();
|
||||
expect(screen.getByText('Notification routing')).toBeDefined();
|
||||
expect(screen.getByText('Routing')).toBeDefined();
|
||||
expect(screen.getByText('Webhooks')).toBeDefined();
|
||||
expect(screen.getByText('Scheduled tasks')).toBeDefined();
|
||||
expect(screen.getByText('Vulnerability scanning')).toBeDefined();
|
||||
expect(screen.getByText('Scan policies')).toBeDefined();
|
||||
expect(screen.getByText('Cloud Backup')).toBeDefined();
|
||||
// SSO label maps the provider to a friendly name.
|
||||
expect(screen.getByText('Google')).toBeDefined();
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface ConfigurationStatus {
|
||||
agents: { discord: AgentStatus; slack: AgentStatus; webhook: AgentStatus };
|
||||
alertRules: number;
|
||||
routingRules: { count: number; enabledCount: number; locked: boolean };
|
||||
suppressionRules: { total: number; enabledCount: number };
|
||||
};
|
||||
automation: {
|
||||
autoHeal: { total: number; enabled: number };
|
||||
@@ -29,6 +30,7 @@ export interface ConfigurationStatus {
|
||||
mfaEnabled: boolean | null;
|
||||
ssoEnabled: boolean;
|
||||
ssoProvider: string | null;
|
||||
trivyInstalled: boolean;
|
||||
scanPolicies: { total: number; enabled: number; locked: boolean };
|
||||
};
|
||||
thresholds: {
|
||||
|
||||
Reference in New Issue
Block a user