Files
sencho/backend/src/__tests__/database-service-pilot-mesh-stacks.test.ts
T
Anso 50b89db3b8 chore(mesh): drop mesh_stacks table on pilot-mode DBs (#1085)
Per the C-3 design, mesh state lives on central. Pilots learn aliases
via the D-1 override push and hold them in `pilotAliasOverlay`. The
local `mesh_stacks` table on pilots has been dead since C-3 shipped.

This is a greenfield cleanup (Directive 20):

- `migrateMeshTables()` runs `DROP TABLE IF EXISTS mesh_stacks` when
  `SENCHO_MODE === 'pilot'` and skips the CREATE. Central-mode
  behavior is unchanged.
- The four mesh CRUD methods (`listMeshStacks`, `isMeshStackEnabled`,
  `insertMeshStack`, `deleteMeshStack`) short-circuit on the same
  check. Reads early-return empty/false; writes early-return;
  `insertMeshStack` also warns so an accidental pilot-side write is
  loud.
- New `isPilotMode()` helper mirrors the existing one in
  `bootstrap/startup.ts`. Layering rules forbid the shared import; a
  third call-site would justify extraction to `helpers/`.

Operator-visible behavior is unchanged on either side. On central, the
table and its rows are untouched. On pilots, the table is removed (it
held no rows in steady state) and any caller of the CRUD methods
continues to see empty list / false / no-op without touching SQLite.

Test plan

- `npx tsc --noEmit`: clean.
- New `database-service-pilot-mesh-stacks.test.ts`: 5/5 green (table
  absence + four short-circuit assertions).
- `mesh-service.test.ts`, `mesh-diagnostic-local.test.ts`, and
  `mesh-service-proactive-bootstrap-fanout.test.ts`: 58/58 green.
- Full backend suite: 2280/2281; the single failure is a pre-existing
  Windows EBUSY flake in `filesystem-backup.test.ts` that reproduces
  on a clean tree.
- Code reviewed; findings applied.
2026-05-17 05:25:00 -04:00

77 lines
3.2 KiB
TypeScript

/**
* Regression guard for F-A8: on pilot-mode hosts, `mesh_stacks` is dropped
* at boot and the CRUD methods short-circuit.
*
* - Per the C-3 design, mesh state lives on central. Pilots learn aliases
* via the D-1 override push and hold them in MeshService.pilotAliasOverlay.
* They never write to the local DB; the table is dead on pilots.
*
* - DatabaseService runs `DROP TABLE IF EXISTS mesh_stacks` in
* `migrateMeshTables()` when `SENCHO_MODE === 'pilot'` and skips the
* CREATE. The four CRUD methods (`listMeshStacks`, `isMeshStackEnabled`,
* `insertMeshStack`, `deleteMeshStack`) short-circuit on the same check
* so the dropped table is never queried.
*
* - Central-mode behavior is unchanged: every other mesh test in the suite
* (mesh-service.test.ts, mesh-diagnostic-local.test.ts, ...) exercises
* the table normally with `SENCHO_MODE` unset and serves as the implicit
* negative control.
*
* The test sets `SENCHO_MODE=pilot` BEFORE `setupTestDb` so the singleton's
* constructor runs `migrateMeshTables()` in pilot mode against the freshly
* copied baseline DB. The gate-function assertions then exercise the runtime
* short-circuits.
*/
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
import { setupTestDb, cleanupTestDb } from './helpers/setupTestDb';
let tmpDir: string;
let DatabaseService: typeof import('../services/DatabaseService').DatabaseService;
beforeAll(async () => {
process.env.SENCHO_MODE = 'pilot';
tmpDir = await setupTestDb();
({ DatabaseService } = await import('../services/DatabaseService'));
});
afterAll(() => {
delete process.env.SENCHO_MODE;
cleanupTestDb(tmpDir);
});
describe('DatabaseService mesh_stacks lifecycle on pilot-mode hosts (F-A8)', () => {
it('drops the mesh_stacks table during migration on pilot mode', () => {
const db = DatabaseService.getInstance();
const row = db.getDb().prepare(
"SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'mesh_stacks'"
).get();
expect(row).toBeUndefined();
});
it('listMeshStacks returns [] without querying the dropped table', () => {
const db = DatabaseService.getInstance();
expect(db.listMeshStacks()).toEqual([]);
expect(db.listMeshStacks(1)).toEqual([]);
});
it('isMeshStackEnabled returns false without querying the dropped table', () => {
const db = DatabaseService.getInstance();
expect(db.isMeshStackEnabled(1, 'any-stack')).toBe(false);
});
it('insertMeshStack is a no-op (no row written, no SQL touched)', () => {
const db = DatabaseService.getInstance();
expect(() => db.insertMeshStack(1, 'guarded-stack', 'tester')).not.toThrow();
expect(db.listMeshStacks(1)).toEqual([]);
const tableStillAbsent = db.getDb().prepare(
"SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'mesh_stacks'"
).get();
expect(tableStillAbsent).toBeUndefined();
});
it('deleteMeshStack is a no-op', () => {
const db = DatabaseService.getInstance();
expect(() => db.deleteMeshStack(1, 'any-stack')).not.toThrow();
});
});