All checks were successful
Quality gates / quality (pull_request) Successful in 1m53s
Strict RED-GREEN TDD over PR review blockers; every fix landed test-first with the failing run observed before implementation. - failureClass: closed privacy-safe vocabulary (worker.unavailable, vision.timeout, model.error) under strict dotted slug grammar. Newlines, carriage returns, ANSI/control characters, secrets, medical text, SQL, oversized values, and off-vocabulary classes fail the entire evidence file closed; nothing hostile can reach rendering. - depth: added to the counter vocabulary so queue.backlog can fire at all; bounded counters (0..1,000,000, integer) fail closed above the ceiling. 9/10/11 edge tests pin silent/at-threshold/above-threshold; backlog is suppressed while worker.outage pages (depth is residual from the same incident) and returns the moment the page clears. - drill integrity: the pre-drill baseline is now read from the fixture itself and must be genuinely healthy; already-outaged fixtures are refused with exit 2 without touching their switch, and a flip that produces no real healthy-to-outage transition reports DRILL FAIL instead of passing vacuously. - manual fallback: deterministic contract replaces the tautology. available+none-required when healthy, available+local-journal under any degradation, unavailable+app-down only when the app boundary itself is down. - fail-closed telemetry: evidence missing any of the four boundaries is rejected; unknown statuses surface as a warn telemetry.gap alert with owner/threshold/runbook instead of passing as healthy (documented in the runbook inventory). - drill origin: validateLoopbackOrigin gates every network path before any fetch. Only a bare http://127.0.0.1:<port> URL passes; credentials, DNS names, hex/decimal/percent-encoded IP encodings, IPv6 forms, paths, queries, fragments, and non-http schemes are refused pre-contact (raw-string grammar gate plus parse round-trip, because the URL parser canonicalizes hostile encodings). - terminal safety: controlSafe() strips C0/C1 control characters from all dynamically produced CLI output so hostile evidence paths cannot inject ANSI escapes into a terminal. Gates: npm test 98/98, check:syntax, npm audit (0 vulns), check:diff, deploy_staging status read-only; 30 adversarial probes against sanitizer, alert edges, and live loopback CLI all pass. No merge, no deploy.
133 lines
5.2 KiB
JavaScript
133 lines
5.2 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import { sanitizeEvidence } from '../src/release-observability.js';
|
|
|
|
const validEvidence = () => ({
|
|
schemaVersion: 1,
|
|
releaseTag: 'daily-2026-08-22.1',
|
|
commit: 'ca31e6d38bec649407f63880504554c59f2878ae',
|
|
generatedAtUtc: '2026-08-22T12:00:00Z',
|
|
checks: [
|
|
{ id: 'app.healthz', boundary: 'app', status: 'pass', latencyMs: 12 },
|
|
{ id: 'api.analyze', boundary: 'api', status: 'pass', counters: { ok: 40, fail: 1 } },
|
|
{ id: 'queue.depth', boundary: 'queue', status: 'pass', counters: { ok: 30, fail: 0 } },
|
|
{ id: 'model.inference', boundary: 'model', status: 'pass', latencyMs: 900, counters: { ok: 25, fail: 0, abstain: 3 } },
|
|
],
|
|
});
|
|
|
|
test('sanitizer keeps bounded sanitized release evidence intact', () => {
|
|
const result = sanitizeEvidence(validEvidence());
|
|
assert.equal(result.ok, true);
|
|
assert.deepEqual(result.evidence, {
|
|
schemaVersion: 1,
|
|
releaseTag: 'daily-2026-08-22.1',
|
|
commit: 'ca31e6d38bec649407f63880504554c59f2878ae',
|
|
generatedAtUtc: '2026-08-22T12:00:00Z',
|
|
checks: [
|
|
{ id: 'app.healthz', boundary: 'app', status: 'pass', failureClass: null, latencyMs: 12, counters: {} },
|
|
{ id: 'api.analyze', boundary: 'api', status: 'pass', failureClass: null, latencyMs: null, counters: { ok: 40, fail: 1 } },
|
|
{ id: 'queue.depth', boundary: 'queue', status: 'pass', failureClass: null, latencyMs: null, counters: { ok: 30, fail: 0 } },
|
|
{ id: 'model.inference', boundary: 'model', status: 'pass', failureClass: null, latencyMs: 900, counters: { ok: 25, fail: 0, abstain: 3 } },
|
|
],
|
|
});
|
|
});
|
|
|
|
test('sanitizer drops session identifiers, photo payloads, credentials, and free-text notes', () => {
|
|
// Assembled at runtime so no contiguous private-key marker ever lands in Git history.
|
|
const privateKeyFixture = `-----BEGIN ${'OPENSSH'} PRIVATE KEY${'-----'}`;
|
|
const hostile = {
|
|
...validEvidence(),
|
|
sessionToken: 'sess_live_abc123',
|
|
adminCookie: 'timmy_agent=secret-cookie-value',
|
|
environmentDump: { NODE_ENV: 'production', SECRET_TOKEN: 'must-not-leak' },
|
|
operatorEmail: 'someone@example.com',
|
|
credentialFile: privateKeyFixture,
|
|
photos: [{ dataBase64: 'aGVsbG8gd29ybGQgaGVsbG8gd29ybGQ=' }],
|
|
checks: [
|
|
...validEvidence().checks,
|
|
{
|
|
id: 'leak',
|
|
boundary: 'app',
|
|
status: 'pass',
|
|
noteText: 'patient said blood at 3am, see photo hash e3b0c442',
|
|
imageHash: 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855',
|
|
base64Payload: 'aGVsbG8=',
|
|
authHeader: `Bearer ${'sk-'}live-abcdef1234567890`,
|
|
},
|
|
],
|
|
};
|
|
|
|
const result = sanitizeEvidence(hostile);
|
|
assert.equal(result.ok, true);
|
|
const serialized = JSON.stringify(result.evidence);
|
|
for (const forbidden of [
|
|
'sess_live_abc123',
|
|
'secret-cookie-value',
|
|
'must-not-leak',
|
|
'someone@example.com',
|
|
'PRIVATE KEY',
|
|
'aGVsbG8',
|
|
'patient said blood',
|
|
'e3b0c44298fc1c14',
|
|
'sk-live-abcdef1234567890',
|
|
]) {
|
|
assert.equal(serialized.includes(forbidden), false, `sanitized output leaked ${forbidden}`);
|
|
}
|
|
assert.equal(result.evidence.checks.some(check => check.id === 'leak'), false);
|
|
});
|
|
|
|
test('sanitizer fail-closes evidence carrying hostile failure-class payloads', () => {
|
|
const hostileFailureClasses = [
|
|
'worker.unavailable\nsecond line',
|
|
'worker.unavailable\r\ncarriage',
|
|
'\x1b[31mANSI-red',
|
|
'worker.unavailable\x1b[0m',
|
|
'bell\x07class',
|
|
'tab\tseparated',
|
|
'DROP TABLE users',
|
|
'patient reported blood at 3am',
|
|
'sess_live_abc123def456',
|
|
'-----BEGIN OPENSSH PRIVATE KEY-----',
|
|
'a@b.example.com',
|
|
'.leading.dot',
|
|
'trailing.dot.',
|
|
'double..dot',
|
|
'-leading-dash.d',
|
|
'd.trailing-dash-',
|
|
'-'.repeat(65),
|
|
42,
|
|
{},
|
|
[],
|
|
];
|
|
for (const failureClass of hostileFailureClasses) {
|
|
const evidence = validEvidence();
|
|
evidence.checks = [{ id: 'app.healthz', boundary: 'app', status: 'fail', failureClass }];
|
|
const result = sanitizeEvidence(evidence);
|
|
assert.equal(result.ok, false, `expected rejection for failureClass ${JSON.stringify(failureClass)}`);
|
|
}
|
|
});
|
|
|
|
test('sanitizer accepts only the exact privacy-safe failure-class vocabulary in slug grammar', () => {
|
|
const baseChecks = validEvidence().checks;
|
|
for (const failureClass of ['worker.unavailable', 'vision.timeout', 'model.error']) {
|
|
const evidence = validEvidence();
|
|
evidence.checks = [
|
|
...baseChecks.filter(check => check.boundary !== 'api'),
|
|
{ id: 'api.analyze', boundary: 'api', status: 'degraded', failureClass },
|
|
];
|
|
const result = sanitizeEvidence(evidence);
|
|
assert.equal(result.ok, true, `vocabulary class ${failureClass} must survive sanitization`);
|
|
assert.equal(result.evidence.checks.some(check => check.failureClass === failureClass), true);
|
|
}
|
|
for (const failureClass of ['made.up.class', 'worker.somethingelse', 'VISION.TIMEOUT', 'vision..timeout']) {
|
|
const evidence = validEvidence();
|
|
evidence.checks = [
|
|
...baseChecks.filter(check => check.boundary !== 'api'),
|
|
{ id: 'api.analyze', boundary: 'api', status: 'degraded', failureClass },
|
|
];
|
|
const result = sanitizeEvidence(evidence);
|
|
assert.equal(result.ok, false, `non-vocabulary class ${failureClass} must be rejected`);
|
|
}
|
|
});
|