mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-22 08:06:42 +00:00
79914fe750
* fix: recognize clean one-shot completions in health gate and drift Treat exit 0 with restart policy no/absent as successful completion so init and migration jobs no longer fail post-update observation or show as service-missing, while long-running restart policies still fail closed. * fix: ignore residual health on clean one-shots and honor deploy.restart_policy Completed exit-0 jobs with no-restart intent no longer fail the health gate on leftover starting/unhealthy state, and Drift treats deploy.restart_policy with Compose precedence so any/on-failure services are not mistaken for one-shots. * fix: require explicit Compose restart no for one-shot recognition Docker inspect reports restart no for both intentional jobs and bare services that omit restart, so Health Gate and Drift now require declared restart:""no"" (or deploy.restart_policy condition none) and load Compose intent once per gate.
44 lines
2.1 KiB
TypeScript
44 lines
2.1 KiB
TypeScript
/**
|
|
* 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', exitCode: null, 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([]);
|
|
});
|
|
});
|