/* * Two properties of the dispatch that follows an approval, guarded by reading its source. * * ── Why source and not behaviour ─────────────────────────────────────────── * `dispatchAfterApproval` runs outside the request, touches the database and reaches an * adapter that talks to a factory. It cannot be exercised here. What can be guarded is the * shape of the two decisions that make it safe, and both are visible in the text. * * ── Why the guard lives here now (2026-09-08) ────────────────────────────── * These two assertions were in `operato-twin/test/actuation-gate-walk.test.ts`, reading * `../../headless-twin/server/…`. The applications then moved to the operato-application * repository and that relative path left this repository — three checks failed with ENOENT. * * The subject of both is a file in *this* package, so this is where they belong. The half that * guards the app's own callback (that approval, and only approval, calls dispatch) stays with * the app. A guard reads its own repository; when it has to read across one, the seam is in * the wrong place. */ import { test } from 'node:test' import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { guardFile } from './guard-roots.js' const PLACE = '../server/service/actuation/dispatch-after-approval.ts' /** The source with comments removed — a term inside a comment is not a use of it. */ function sourceOf(): string { return readFileSync(guardFile(import.meta.url, PLACE), 'utf8') } function withoutComments(src: string): string { return src.replace(/\/\*[\s\S]*?\*\//g, '').replace(/\/\/[^\n]*/g, '') } test('dispatch does not run inside the approval transaction', () => { /* * Approval happens inside the worklist's transaction. Sending a request to the factory from * inside it means a rollback cannot take the request back: the plant keeps the work order * and our ledger has the approval undone. What went out over the network was never in the * transaction's care. * * A transaction-bound store is passed the transaction — `databaseCommandStore(tx)`. An * unbound one takes no argument. So the argument list is the property. */ const src = withoutComments(sourceOf()) assert.match(src, /databaseCommandStore\(\)/, 'dispatch uses a transaction-bound store') assert.doesNotMatch(src, /databaseCommandStore\(\s*[a-zA-Z]/, 'dispatch is being handed a transaction store') }) test('a failed dispatch does not undo the approval, and does not take the process down', () => { /* * This runs outside the request, in `setImmediate`. A throw there is an unhandled rejection * and the server exits — one undelivered actuation would stop everything else. * * The approval also has to survive an adapter that is down. That is the whole reason * approving and dispatching are two steps, and it is a measured property, not a wish: * command `67f8765a` was dispatched successfully later, on the same approval. */ const src = sourceOf() assert.match(src, /catch\s*\(/, 'nothing catches a failed dispatch') assert.doesNotMatch( withoutComments(src), /\bthrow\b/, 'the dispatch path throws — outside a request that ends the process' ) }) test('this guard reads the real file, so a wrong path is red and not green', () => { /* * The two checks above fail when a pattern stops matching. They would also "pass" against an * empty string, so the path itself has to be guarded — that is exactly how these assertions * left this repository unnoticed in the first place. */ const src = sourceOf() assert.ok(src.length > 1000, `the dispatch source is ${src.length} chars — the path is wrong`) assert.match(src, /dispatchAfterApproval/, 'the file read is not the one this guard names') })