Verifier Recipe

Verify a Remote File over SSH

Confirm that an expected business file exists and is readable on a remote system.

Canonical BRS contractIndependently executableBRS-Core ready
Business question

Did the file our business process depends on actually arrive?

A reachable SSH server does not prove that an expected report, export, settlement file, or integration artifact exists. This verifier connects to the remote system and verifies the expected file directly.

Configuration

Environment: SSH_HOST, SSH_USER, REMOTE_FILE

Uses the system SSH client and your existing SSH key configuration. Node.js 24 or later is required.

Recipe structure

The top-level executable entry file sits beside a same-named directory that owns the canonical implementation and its dependency manifest. Run npm install once in that directory and retain the generated package-lock.json:

verifiers/
├── verify-remote-file-over-ssh.js
└── verify-remote-file-over-ssh/
    ├── package.json
    └── verify-remote-file-over-ssh.js

The canonical contract stays at the boundary.

The implementation exports the canonical verifier object: id, label, schedule.interval, schedule.timeout, and asynchronous verify() returning structured summary and steps. The top-level file exports that exact object unchanged, adds validated standalone execution, and is what BRS-Core discovers.

Top-level executable entry file

verifiers/verify-remote-file-over-ssh.js

#!/usr/bin/env node
'use strict';

const verifier = require('./verify-remote-file-over-ssh/verify-remote-file-over-ssh');

module.exports = verifier;

if (require.main === module) {
    void runStandalone(verifier);
}

async function runStandalone(standaloneVerifier) {
    let timeoutHandle;

    try {
        const timeout = standaloneVerifier.schedule?.timeout ?? 30;

        if (!Number.isInteger(timeout) || timeout <= 0) {
            throw new Error('schedule.timeout must be a positive integer');
        }

        const timeoutPromise = new Promise((_, reject) => {
            timeoutHandle = setTimeout(() => {
                const error = new Error(
                    `Standalone verifier execution timed out after ${timeout} seconds.`
                );
                error.code = 'BRS_TIMEOUT';
                reject(error);
            }, timeout * 1000);
        });
        const result = await Promise.race([
            Promise.resolve().then(() => standaloneVerifier.verify()),
            timeoutPromise
        ]);

        validateResult(result);
        await writeStream(
            process.stdout,
            `${JSON.stringify(result, null, 2)}\n`
        );
        process.exit(result.steps.some((step) => !step.success) ? 1 : 0);
    } catch (error) {
        const summary = error?.code === 'BRS_TIMEOUT'
            ? error.message
            : error?.code === 'BRS_INVALID_RESULT'
                ? 'Standalone verifier returned a malformed result.'
                : 'Standalone verifier execution failed unexpectedly.';

        await Promise.all([
            writeStream(
                process.stdout,
                `${JSON.stringify({ summary, steps: [] }, null, 2)}\n`
            ),
            writeStream(process.stderr, `${sanitize(error?.message)}\n`)
        ]);
        process.exit(1);
    } finally {
        clearTimeout(timeoutHandle);
    }
}

function validateResult(result) {
    const names = new Set();
    const valid = result &&
        typeof result === 'object' &&
        !Array.isArray(result) &&
        typeof result.summary === 'string' &&
        result.summary.trim() !== '' &&
        Array.isArray(result.steps) &&
        result.steps.length > 0 &&
        result.steps.every((step) => {
            const uniqueName = step &&
                /^[a-z][a-z0-9_]*$/.test(step.name) &&
                !names.has(step.name);

            if (uniqueName) names.add(step.name);

            return uniqueName &&
                typeof step.label === 'string' &&
                step.label.trim() !== '' &&
                typeof step.success === 'boolean' &&
                Number.isFinite(step.durationSeconds) &&
                step.durationSeconds >= 0 &&
                typeof step.message === 'string' &&
                step.message.trim() !== '' &&
                typeof step.checkedAt === 'string' &&
                Number.isFinite(Date.parse(step.checkedAt));
        }) &&
        (result.observations === undefined ||
            Array.isArray(result.observations));

    if (!valid) {
        const error = new Error('verifier result is malformed');
        error.code = 'BRS_INVALID_RESULT';
        throw error;
    }
}

function writeStream(stream, value) {
    return new Promise((resolve, reject) => {
        stream.write(value, (error) => error ? reject(error) : resolve());
    });
}

function sanitize(value) {
    return String(value || 'Unknown error')
        .split(/\r?\n/, 1)[0]
        .replace(/[\u0000-\u001f\u007f]/g, ' ')
        .slice(0, 500);
}

Verifier implementation

verifiers/verify-remote-file-over-ssh/verify-remote-file-over-ssh.js

'use strict';

const { execFile } = require('node:child_process');
const { promisify } = require('node:util');
const path = require('node:path');

const execFileAsync = promisify(execFile);

module.exports = {
    id: 'remote_file_over_ssh',
    label: 'Remote File over SSH',
    schedule: {
        interval: 300,
        timeout: 30
    },

    async verify() {
        loadLocalEnvironment();

        const startedAt = Date.now();
        const host = safeTargetPart('SSH_HOST');
        const user = safeTargetPart('SSH_USER');
        const remoteFile = required('REMOTE_FILE');
        const quotedFile = quoteForPosixShell(remoteFile);
        const remoteCommand =
            `test -r ${quotedFile} && wc -c < ${quotedFile}`;
        const steps = [];

        try {
            const { stdout } = await execFileAsync('ssh', [
                '-o',
                'BatchMode=yes',
                '-o',
                'ConnectTimeout=10',
                `${user}@${host}`,
                remoteCommand
            ]);
            const bytes = Number(stdout.trim());

            if (!Number.isFinite(bytes) || bytes < 1) {
                throw new Error('Remote file is empty.');
            }

            steps.push(step(
                'verify_remote_file',
                'Verify Remote File',
                true,
                startedAt,
                'The expected remote file is present, readable, and non-empty.'
            ));
        } catch (error) {
            logFailure('verify_remote_file', error);
            steps.push(step(
                'verify_remote_file',
                'Verify Remote File',
                false,
                startedAt,
                'The expected remote file could not be verified.'
            ));
        }

        return {
            summary: steps.every((item) => item.success)
                ? 'The expected remote file was verified successfully.'
                : 'The expected remote file verification failed.',
            steps
        };
    }
};

function loadLocalEnvironment() {
    try {
        process.loadEnvFile(path.join(__dirname, '.env'));
    } catch (error) {
        if (!error || error.code !== 'ENOENT') throw error;
    }
}

function required(name) {
    const value = String(process.env[name] || '').trim();

    if (!value) throw new Error(`${name} is required`);
    return value;
}

function safeTargetPart(name) {
    const value = required(name);

    if (
        value.startsWith('-') ||
        !/^[a-zA-Z0-9._:-]+$/.test(value)
    ) {
        throw new Error(`${name} contains unsupported characters`);
    }

    return value;
}

function quoteForPosixShell(value) {
    return `'${value.replace(/'/g, `'\\''`)}'`;
}

function logFailure(name, error) {
    const detail = sanitize(error instanceof Error ? error.message : error);

    console.error(
        `verifier=remote_file_over_ssh step=${name} error="${detail}"`
    );
}

function sanitize(value) {
    return String(value || 'Unknown error')
        .split(/\r?\n/, 1)[0]
        .replace(/[\u0000-\u001f\u007f]/g, ' ')
        .replace(/\\/g, '\\\\')
        .replace(/"/g, '\\"')
        .slice(0, 500);
}

function step(name, label, success, startedAt, message) {
    return {
        name,
        label,
        success,
        durationSeconds: Number(
            ((Date.now() - startedAt) / 1000).toFixed(3)
        ),
        message,
        checkedAt: new Date().toISOString()
    };
}

Dependency manifest

verifiers/verify-remote-file-over-ssh/package.json

{
  "name": "brs-verifier-remote-file-over-ssh",
  "version": "1.0.0",
  "private": true,
  "type": "commonjs",
  "scripts": {
    "verify": "node ../verify-remote-file-over-ssh.js"
  },
  "engines": {
    "node": ">=24"
  }
}

Run it directly

cd verify-remote-file-over-ssh
npm install
npm run verify

A passing run writes validated structured JSON to standard output and exits 0. A business failure includes a failed step and exits 1. A timeout, malformed result, or unexpected execution error writes a runner-generated JSON result and exits 1.

Run it continuously with BRS-Core

This verifier does not require BRS-Core to execute. Direct execution is part of the verifier contract and makes development, troubleshooting, CI/CD use, and manual diagnostics straightforward.

BRS-Core can run this verifier alongside your other approved verifiers continuously as part of 24/7 business capability monitoring. Because every recipe presents the same canonical contract, Core can discover and schedule these verifiers together, run them independently, enforce their timeouts, record their results, and expose their signals to the monitoring environment.