Protect private bank configuration from drift reconciliation (Refs #152)

This commit is contained in:
2026-10-12 23:32:20 -04:00
parent 4e3df81786
commit d9fa15cdf6
23 changed files with 597 additions and 28 deletions
+49
View File
@@ -122,6 +122,55 @@ async function sustainedFailure() {
}
describe('Watchdog detection and ownership', () => {
it.each([false, true])(
'rescans legacy bank drift and preserves real differences (mixed=%s)',
async (mixed) => {
const { mkdir } = await import('node:fs/promises');
const { destOfKind } = await import('../../src/lib/server/config.js');
const { setMaintenancePolicy, pauseMaintenance } =
await import('../../src/lib/server/maintenance/policies.js');
setMaintenancePolicy('drift', false);
pauseMaintenance(true);
const dest = destOfKind(server, 'config');
await mkdir(dest, { recursive: true });
const secret = 'set tws_bank_token "ec_bank_watchdog_private"';
await writeFile(join(dest, 'electric_cherry_bank.cfg'), secret);
if (mixed) await writeFile(join(dest, 'stray.cfg'), 'real drift');
database
.db()
.prepare(
`INSERT INTO watchdog_incidents
(id,server,kind,state,summary,details,first_seen_at,last_seen_at,failures)
VALUES('legacy-bank',?,'drift','open','Old drift',?,?,?,1)`
)
.run(
server,
JSON.stringify({
files: [{ kind: 'config', relPath: 'electric_cherry_bank.cfg' }]
}),
new Date().toISOString(),
new Date().toISOString()
);
await watchdog.watchdogTick(true);
const row = database
.db()
.prepare('SELECT state,details FROM watchdog_incidents WHERE id=?')
.get('legacy-bank') as { state: string; details: string };
expect(row.state).toBe(mixed ? 'open' : 'resolved');
expect(
JSON.parse(row.details).files.map((file: { relPath: string }) => file.relPath)
).toEqual(mixed ? ['stray.cfg'] : []);
expect(operations()).toEqual([]);
expect(
database
.db()
.prepare('SELECT 1 FROM file_blobs WHERE instr(content,?)>0')
.all(Buffer.from(secret))
).toEqual([]);
expect(await readFile(join(dest, 'electric_cherry_bank.cfg'), 'utf8')).toBe(secret);
}
);
it('waits for status-monitor evidence without issuing its own routine probes', async () => {
down();
for (let minute = 0; minute < 4; minute++) {