mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-11 03:06:54 +00:00
feat(settings): surface security, notifications, and app store on remote nodes (#716)
Flip Security (Trivy), Notifications (agents + history), and App Store from global-and-hidden-on-remote to node-scoped so operators can manage them when a remote node is selected in the node picker. The primary instance proxies the calls to each remote, which resolves the correct per-instance binary state, agent config, and template registry. Backend: key `agents` and `notification_history` by `node_id` with idempotent column-add migrations and a `(node_id, type)` unique index on agents, matching the Labels pattern. Thread `req.nodeId` through the /api/agents and /api/notifications routes. Internal NotificationService and ImageUpdateService writes resolve the middleware default via `NodeRegistry.getDefaultNodeId()` so monitor-emitted rows share a bucket with user-facing ones (avoids split-brain where the UI sees test notifications but not internal alerts). Frontend: split Security on remote to render only the scanner card and hide scan policies and CVE suppressions (those remain control-plane-only). Drop the misleading "Always Local" badge on Developer since retention windows govern backend jobs, not UI state. Flip the App Store registry to node-scoped. Docs: add a "What Settings apply per node" table to multi-node, clarify remote alert setup in alerts-notifications, and note Trivy's per-host install in vulnerability-scanning.
This commit is contained in:
@@ -3,10 +3,8 @@ import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { TogglePill } from '@/components/ui/toggle-pill';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { useLicense } from '@/context/LicenseContext';
|
||||
import { RefreshCw, Database, Info } from 'lucide-react';
|
||||
import { RefreshCw, Database } from 'lucide-react';
|
||||
import type { PatchableSettings } from './types';
|
||||
|
||||
interface DeveloperSectionProps {
|
||||
@@ -15,7 +13,6 @@ interface DeveloperSectionProps {
|
||||
onSave: () => Promise<void>;
|
||||
isSaving: boolean;
|
||||
isLoading: boolean;
|
||||
isRemote: boolean;
|
||||
}
|
||||
|
||||
function SettingsSkeleton() {
|
||||
@@ -32,29 +29,11 @@ function SettingsSkeleton() {
|
||||
);
|
||||
}
|
||||
|
||||
export function DeveloperSection({ settings, onSettingChange, onSave, isSaving, isLoading, isRemote }: DeveloperSectionProps) {
|
||||
export function DeveloperSection({ settings, onSettingChange, onSave, isSaving, isLoading }: DeveloperSectionProps) {
|
||||
const { isPaid, license } = useLicense();
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{isRemote && (
|
||||
<div className="flex justify-end">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Badge variant="secondary" className="text-xs cursor-help">
|
||||
<Info className="w-3 h-3 mr-1" />
|
||||
Always Local
|
||||
</Badge>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom" className="max-w-[220px] text-center">
|
||||
These settings control this Sencho instance's UI behaviour and are never synced to remote nodes.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isLoading ? <SettingsSkeleton /> : (
|
||||
<>
|
||||
<div className="space-y-6 bg-glass border border-glass-border p-4 rounded-lg">
|
||||
|
||||
Reference in New Issue
Block a user