mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-09-04 14:45:41 +00:00
feat: node-scoped Networking operator page (#1603)
* feat: add node-scoped Networking operator page Adds a Networking view with overview, topology, inventory, and findings. Shared aggregate reads back the page; Resources keeps prune and redirects here. Includes fail-closed network delete guards, operator docs, and /nodes/:slug/networking routing. * fix: rename unused variable n to _n to satisfy no-unused-vars lint * fix: keep top bar search clickable when nav grows * feat: complete Compose-first Networking Phase 2 operator assistant * fix: move networking action visibility helper out of component module * feat(networking): complete Compose-first Networking operator page Finish the node-scoped Networking page (Overview, Networks, Topology, Findings) with design-system parity and correct finding semantics. - Rebuild detail sheets on SystemSheet/SheetSection; align the tab band, masthead, and mobile tone with Fleet and Security. - Encode the host-mode and exposure severity matrix; fix collision counts so intentional shared externals are not flagged; add one typed drift predicate shared by inventory, topology, badges, and overview counts. - Preserve per-container attachments and IPs on topology node clicks; drawer-only click with an explicit logs action; ownership and boolean filters; bound large graphs before layout. - Aggregate cached Compose Doctor findings into the Findings tab with honest source labels, structural merge and dedupe, staleness reconciliation, and a shared exposure-context helper both engines use. - Networks tab: privacy-safe service search, precise ownership counts, schema v3 with version-2 adapters on every endpoint, pre-confirm delete reasons, and the shared sortable table with an internal scroll region. - Interop: Fleet node-card networking signal with pending-intent navigation, stack-to-node backlink, and Dossier/Drift deep links. - Enrich sanitized inspect with an allowlisted connected-container list; fetch topology once and filter client-side. - Docs and tests across every new finding kind, adapter, and flow. * fix(networking): correct drift count, exposure fail-soft, and inspect crash paths Address code-review findings on the Networking page implementation: - Fix the Overview drift count to use the shared drift-kind predicate instead of a hardcoded list that omitted external-network-missing. - Gate Compose Doctor's unclassified-exposure and reverse-proxy-undocumented rules on exposure-context availability, so a DB read failure no longer fabricates findings (mirrors the live engine's existing fail-soft behavior). - Guard the per-stack exposure-intent read in topology aggregation so a transient DB failure degrades to unknown intent instead of failing the whole response. - Harden the network detail drawer against a partial inspect payload from an older remote node, and log the real error instead of a bare catch. - Remove now-duplicated severity-rank and drift-kind helpers in favor of the shared modules; drop dead backend-only exports; widen the frontend schema version type to a plain number instead of casting past a literal type. - Add coverage for the delete-guard precedence, the full host-mode severity matrix, the schema-2 compatibility adapter, and the sanitized connected- container allowlist; tighten two tests that were not exercising the behavior they claimed to. * fix: add missing onOpenNodeNetworking prop to FleetView experimental test The added required prop on FleetViewProps broke the merge-build when the test file (on main but not on this branch) was compiled against the updated FleetView interface.
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* The connected-container section of the sanitized inspect DTO must expose only
|
||||
* the allowlisted fields and must never leak label values, MAC addresses, or
|
||||
* endpoint IDs from the raw Docker inspect payload.
|
||||
*/
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { sanitizeNetworkInspect } from '../services/network/sanitizeNetworkInspect';
|
||||
import type { DependencySnapshot } from '../services/DockerController';
|
||||
|
||||
describe('sanitizeNetworkInspect connected containers', () => {
|
||||
it('exposes only name/service/stack/ipv4 (CIDR stripped) and no raw label values or MAC/endpoint data', () => {
|
||||
const snapshot: DependencySnapshot = {
|
||||
networks: [{ id: 'net1', name: 'app_net', driver: 'bridge', scope: 'local', isSystem: false, composeProject: 'app', stack: 'app' }],
|
||||
volumes: [],
|
||||
containers: [{
|
||||
id: 'c1', name: 'app-web-1', service: 'web', composeProject: 'app', stack: 'app', state: 'running', image: 'nginx',
|
||||
networks: [{ name: 'app_net', id: 'net1', ip: '172.20.0.5/16' }], volumes: [], ports: [],
|
||||
}],
|
||||
};
|
||||
const raw = {
|
||||
Id: 'net1', Name: 'app_net', Driver: 'bridge', Scope: 'local',
|
||||
Labels: { 'com.docker.compose.project': 'app', 'secret.token': 'do-not-leak' },
|
||||
Containers: { c1: { Name: 'app-web-1', MacAddress: '02:42:ac:14:00:05', EndpointID: 'endpoint-xyz', IPv4Address: '172.20.0.5/16' } },
|
||||
};
|
||||
|
||||
const result = sanitizeNetworkInspect(raw, snapshot.networks[0], snapshot);
|
||||
|
||||
expect(result.connectedContainers).toEqual([
|
||||
{ name: 'app-web-1', service: 'web', stack: 'app', ipv4: '172.20.0.5' },
|
||||
]);
|
||||
// Label keys are exposed, values never are.
|
||||
expect(result.labelKeys).toContain('secret.token');
|
||||
const serialized = JSON.stringify(result);
|
||||
expect(serialized).not.toContain('do-not-leak');
|
||||
expect(serialized).not.toContain('02:42:ac:14:00:05');
|
||||
expect(serialized).not.toContain('endpoint-xyz');
|
||||
});
|
||||
|
||||
it('yields an empty connected list when no snapshot is provided', () => {
|
||||
const result = sanitizeNetworkInspect({ Id: 'net1', Name: 'app_net' }, undefined, undefined);
|
||||
expect(result.connectedContainers).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user