mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-17 14:08:19 +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:
@@ -1,4 +1,5 @@
|
||||
import { DatabaseService, NotificationHistory } from './DatabaseService';
|
||||
import { NodeRegistry } from './NodeRegistry';
|
||||
import { isDebugEnabled } from '../utils/debug';
|
||||
import { getErrorMessage } from '../utils/errors';
|
||||
|
||||
@@ -45,8 +46,11 @@ export class NotificationService {
|
||||
stackName?: string,
|
||||
containerName?: string,
|
||||
) {
|
||||
// 1. Log to history and get the full inserted record (with id)
|
||||
const notification = this.dbService.addNotificationHistory({
|
||||
// Internal writes use the middleware default so they share a row key
|
||||
// with user-initiated requests; otherwise the UI and monitors split
|
||||
// between different node_id buckets.
|
||||
const localNodeId = NodeRegistry.getInstance().getDefaultNodeId();
|
||||
const notification = this.dbService.addNotificationHistory(localNodeId, {
|
||||
level,
|
||||
message,
|
||||
timestamp: Date.now(),
|
||||
@@ -84,8 +88,8 @@ export class NotificationService {
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Fall back to global agents
|
||||
const agents = this.dbService.getEnabledAgents();
|
||||
// 4. Fall back to this instance's agents (keyed by this instance's default node id).
|
||||
const agents = this.dbService.getEnabledAgents(localNodeId);
|
||||
if (agents.length === 0) {
|
||||
if (isDebugEnabled()) console.log('[Notify:diag] No routes or agents matched; skipping external dispatch');
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user