edgeport - v1.0.3
    Preparing search index...

    Advanced Usage: Cross-Protocol Recipes

    edgeport's protocols are designed to compose. This document walks through realistic, multi-protocol workflows - the kind of "interface engine" / "edge ops" wiring that real deployments need - with a runnable code sketch for each, and points at the integration test that exercises it end-to-end against real servers under workerd.

    Every recipe below has a corresponding spec in test/integration/recipes/ that runs against the Dockerized servers in docker/compose.yml. Run them with:

    docker compose -f docker/compose.yml up -d --wait
    INTEGRATION=1 bunx vitest run test/integration/recipes
    docker compose -f docker/compose.yml down -v

    A shared helper, test/integration/recipes/_helpers.ts, provides readSyslog() (reads back what was sent to the syslog sink so logging can be asserted), artifact(n) (a deterministic binary blob for transfer tests), uniqueId(), and waitFor().

    The snippets below are application-level sketches using the public API (env vars stand in for config). The linked spec is the exact, asserted version that runs in CI.

    Every recipe reads its configuration from env (Worker secrets/vars - set with wrangler secret put NAME or in wrangler.jsonc vars). Each recipe lists the exact variables it needs under Prerequisites; this is the catalog of what they are, what the values look like, and where they come from.

    Variable Service / what it is Example value How to get it
    BOX / deviceHost SSH/SFTP host (your server, bastion, or edge device) ssh.example.com or 10.0.0.7 the hostname/IP of a box you can reach on port 22
    SSH_KEY SSH private key (PKCS#8 or OpenSSH PEM) -----BEGIN PRIVATE KEY-----\n... ssh-keygen -t ed25519; install the .pub in the box's authorized_keys
    SSH_KEY_PASSPHRASE passphrase for an encrypted private key correct horse battery staple whatever you set at ssh-keygen time
    MAIL / SMTP / SMTP_HOST SMTP (and IMAP/POP3) server host smtp.example.com or smtp.mx.cloudflare.net your mail provider, or Cloudflare Email Service (see below)
    MAIL_USER / SMTP_USER SMTP/IMAP/POP3 login postmaster@example.com (or literal api_token for CF) provider mailbox; for CF Email Service the username is the literal api_token
    MAIL_PW / SMTP_PW / CF_EMAIL_TOKEN mailbox password or API token a password, or v1.0-abc... token provider; for CF, an API token with Email Sending: Edit
    ONCALL / OPS / STAKEHOLDERS recipient email address(es) oncall@example.com your distribution list
    LDAP LDAP/LDAPS directory host ldap.example.com your directory server (389 plaintext/StartTLS, 636 LDAPS)
    SVC_DN / SVC_PW service bind DN + password cn=svc,dc=example,dc=org / a password create a bind account in your directory
    NATS NATS server host nats.example.com or connect.ngs.global self-hosted NATS, or Synadia Cloud (NGS)
    NATS_TOKEN / NATS_CREDS NATS auth token, or a .creds file's contents s3cr3t-token server config; NGS issues a .creds file
    BROKER MQTT broker host broker.example.com self-hosted Mosquitto/EMQX, or a cloud broker
    MQTT_USER / MQTT_PASS MQTT credentials (or omit for anonymous) device / a password broker config
    MQ / MQ_USER / MQ_PASS STOMP broker host + creds (ActiveMQ/RabbitMQ) mq.example.com / admin / admin broker config
    FTP / LANDING / DR FTP server host(s) files.example.com your FTP server (passive mode; ports 21 + a passive range)
    GW WebSocket gateway host (for wss://) gateway.example.com your realtime/WS endpoint
    SIEM syslog collector host (RFC 5424 over TLS) logs.example.com your SIEM/log aggregator (Datadog, Splunk, rsyslog, ...) listening on 6514
    SMSC SMPP SMSC host (carrier/aggregator or a simulator) smsc.example.com your SMS provider's SMPP endpoint (port 2775)
    SMPP_SYSTEM_ID / SMPP_PW SMPP bind credentials (ESME system id + password) esme / a password issued by your SMS provider
    SIP / SIP_DOMAIN SIP registrar/proxy host + served SIP domain sip.example.com / example.com your PBX / SIP trunk (Asterisk, FreeSWITCH, Kamailio, Twilio/Telnyx)
    SIP_USER / SIP_PW SIP account username + password (digest) alice / a password your SIP provider / PBX account

    Cloudflare Email Service (SMTP): set SMTP/MAIL to smtp.mx.cloudflare.net, tls: 'implicit' (port 465), the username to the literal string api_token, and the password to a Cloudflare API token scoped Email Sending: Edit; the from domain must be onboarded to Email Sending. See the Cloudflare Email Service SMTP docs.

    Recipe Modules What it proves
    Mail Service Stack SMTP + IMAP + POP3 + LDAP + Syslog LDAP recipient validation, cross-protocol consistency, audit
    Secure Deploy/Ops SSH + SFTP Exec, upload+resume, shell tail, clean disconnect
    CI / Observability Syslog + SMTP + IMAP Structured logs -> error alert -> verified email
    Realtime Chat WebSocket + NATS + LDAP + MQTT Auth, routing, presence, reconnect/ordering
    Resilience & Recovery NATS (JetStream) + MQTT + Syslog Durable continuity, persistent-session drain
    Device Fleet Management SSH + SFTP + MQTT + Syslog Telemetry, LWT offline, firmware push+resume
    HL7 Integration Engine FTP + SFTP + MQTT + STOMP + Syslog Parse, fan-out, ack semantics, audit
    Mainframe Nightly Batch FTP + SFTP + Syslog + SMTP Insecure-inside / secure-outside transfer
    Passive-FTP Monitoring FTP + Syslog + SMTP PASV/EPSV, port pressure, failure alerting
    Scheduled Reports SSH + SFTP + SMTP + Syslog Exec job, checksum, email attachment, failure alert
    Transactional Messaging STOMP + MQTT + NATS + Syslog STOMP commit/abort, ack modes, cross-broker bridge
    Centralized Authentication LDAP + SSH + SFTP + Syslog LDAP bind + group gate for SSH/SFTP, audit
    Notification Fan-Out NATS + WebSocket + MQTT + STOMP + Syslog One event -> three transports, ordering, slow-consumer isolation
    Credential-Protecting Gateway LDAPS + SSH + SFTP + Syslog LDAPS fail-closed, no downgrade, server-identity gate
    Certificate Lifecycle LDAPS + Syslog + SMTP Cert validation fails closed -> alert + audit
    Carrier SMS Delivery SMPP + SMS-over-email + Syslog + util Carrier SMPP delivery + receipt, email-gateway fallback, audit
    SIP Messaging & Alerting SIP + Syslog Register (RFC 5626), digest MESSAGE routing send+receive, audit

    Modules: SMTP + IMAP + POP3 + LDAP + Syslog: mail.spec.ts

    • Mail server MAIL + MAIL_USER/MAIL_PW: a host speaking SMTP+IMAP+POP3 (a mailbox provider, or smtp.mx.cloudflare.net via the Cloudflare Email Service).
    • Directory LDAP + SVC_DN/SVC_PW: for recipient validation (e.g. cn=svc,dc=example,dc=org).
    • Syslog collector SIEM: for the audit trail.

    See Environment & Services for value formats and how to obtain each.

    A complete mail server: recipients are validated against LDAP before send, mail is submitted via SMTP and read back via both IMAP (multi-device) and POP3 (download), cross-protocol mailbox consistency holds (a POP3 read without delete leaves the IMAP view intact), and every transaction is audited to Syslog. An unknown recipient is rejected at the directory gate.

    import { send } from 'edgeport/smtp';
    import { connect as imapConnect } from 'edgeport/imap';
    import { search as ldapSearch, eq } from 'edgeport/ldap';
    import { connect as syslogConnect } from 'edgeport/syslog';

    const auth = { username: env.MAIL_USER, password: env.MAIL_PW };
    await using audit = await syslogConnect({
    hostname: env.SIEM,
    port: 6514,
    tls: 'implicit',
    appName: 'mta'
    });

    // 1. validate the recipient against the directory (reject unknown addresses).
    // eq() carries the address literally, so an untrusted recipient can't inject filter syntax
    const found = await ldapSearch({
    hostname: env.LDAP,
    bindDN: env.SVC_DN,
    password: env.SVC_PW,
    base: 'ou=people,dc=example,dc=org',
    filter: eq('mail', recipient)
    });
    if (found.length === 0) {
    await audit.warn(`rejected unknown recipient ${recipient}`);
    throw new Error('unknown recipient');
    }

    // 2. submit (tls:'off' for a trusted internal relay; or 587/STARTTLS, 465/implicit)
    await send({
    hostname: env.MAIL,
    tls: 'off',
    auth,
    from: 'bot@example.org',
    to: recipient,
    subject: 'Hi',
    text: 'body'
    });
    await audit.info(`delivered to ${recipient}`);

    // 3. the same message is visible via IMAP and POP3; a POP3 read (no DELE) doesn't disturb IMAP
    await using imap = await imapConnect({ hostname: env.MAIL, tls: 'off', auth });
    await imap.select('INBOX');
    const uids = await imap.search({ subject: 'Hi' });
    const messages = await imap.fetch(uids, { body: true });

    Use case: a full mail-handling service with directory-validated recipients and a compliance audit trail.

    Modules: SSH + SFTP, secure.spec.ts

    • SSH host BOX + private key SSH_KEY; a box reachable on port 22 with your public key in authorized_keys.

    See Environment & Services for value formats and how to obtain each.

    A deploy/ops loop over one connection: read free space with the df('/') helper (parsed rows, no text munging), upload a build artifact over an SFTP session reused from the SSH connection, resume an interrupted upload with writeFile(path, data, { offset }), chmod() + restart, tail logs over an interactive shell() channel, and verify a clean await using disconnect.

    import { connect as sshConnect } from 'edgeport/ssh';
    import { connect as sftpConnect } from 'edgeport/sftp';

    await using ssh = await sshConnect({
    hostname: env.BOX,
    username: 'deploy',
    privateKey: { pem: env.SSH_KEY }
    });

    // check disk before shipping (df() returns parsed rows, no text munging)
    const [root] = await ssh.df('/'); // { filesystem, sizeKb, usedKb, availKb, usePercent, mountedOn }

    // upload over a REUSED session, resuming if the first attempt was cut short
    await using sftp = await sftpConnect({ session: ssh });
    try {
    await sftp.writeFile('/srv/app.tar', artifact);
    } catch {
    const { size } = await sftp.stat('/srv/app.tar'); // resume from the partial size
    await sftp.writeFile('/srv/app.tar', artifact.subarray(size), { offset: size });
    }

    // apply + restart, then tail the log over an interactive shell
    await ssh.chmod('/srv/app.tar', 0o600);
    await ssh.exec('systemctl restart app');
    await using shell = await ssh.shell();
    await shell.write(new TextEncoder().encode('tail -n 20 /var/log/app.log\n'));
    for await (const chunk of shell.stdout) {
    console.log(new TextDecoder().decode(chunk));
    break;
    }
    // the `await using` scope closes both channels cleanly on exit

    Use case: CI/CD deploy steps, remote maintenance, log inspection from a Worker.

    Modules: Syslog + SMTP + IMAP, ci.spec.ts

    • Syslog collector SIEM: ingests the RFC 5424 logs (TLS on 6514).
    • SMTP + IMAP SMTP + SMTP_USER/SMTP_PW, alerting to ONCALL: sends and verifies the alert email.

    See Environment & Services for value formats and how to obtain each.

    A service emits high-volume RFC 5424 structured-data logs over Syslog; ingestion and the structured-data wire format are verified; an error-severity event triggers an alert email over SMTP, confirmed to land via IMAP. Ingestion + parsing + downstream notification together.

    import { connect as syslogConnect, Severity } from 'edgeport/syslog';
    import { send } from 'edgeport/smtp';

    await using log = await syslogConnect({
    hostname: env.SIEM,
    port: 6514,
    tls: 'implicit',
    appName: 'api'
    });

    for (const event of requestLog) {
    await log.log({
    severity: event.level,
    message: event.msg,
    structuredData: [{ id: 'req@1', params: { ms: String(event.ms), path: event.path } }]
    });

    // an error escalates to an alert email
    if (event.level === Severity.error) {
    await send({
    hostname: env.SMTP,
    port: 587,
    auth: { username: env.SMTP_USER, password: env.SMTP_PW },
    from: 'alerts@example.com',
    to: env.ONCALL,
    subject: `ALERT ${event.msg}`,
    text: event.detail
    });
    }
    }
    // an IMAP poll later confirms the alert was delivered (see the spec)

    Use case: shipping Worker logs to a SIEM/collector and alerting on errors.

    Modules: WebSocket + NATS + LDAP + MQTT, chat.spec.ts

    • Directory LDAP (+ a user DN/password at runtime); the login gate.
    • NATS NATS + NATS_TOKEN; message routing with queue groups.
    • MQTT broker BROKER; presence via Last Will.
    • WebSocket gateway GW; the client transport (wss://).

    See Environment & Services for value formats and how to obtain each.

    A realtime chat app with presence: authenticate with an LDAP bind, open a WebSocket carrying a session token, route messages through NATS pub/sub with queue groups for multi-server fan-out, and track presence with an MQTT Last Will that fires on an ungraceful disconnect.

    import { connect as ldapConnect } from 'edgeport/ldaps';
    import { escapeDN } from 'edgeport/ldap';
    import { connect as wsConnect } from 'edgeport/ws';
    import { connect as natsConnect } from 'edgeport/nats';
    import { connect as mqttConnect } from 'edgeport/mqtt';

    // 1. authenticate the user (LDAP bind is the login gate; escapeDN guards the RDN value)
    await using dir = await ldapConnect({
    hostname: env.LDAP,
    bindDN: `uid=${escapeDN(user)},ou=people,dc=example,dc=org`,
    password
    });

    // 2. presence via an MQTT last-will: if this client drops, the broker announces 'offline'
    await using presence = await mqttConnect({
    hostname: env.BROKER,
    clientId: user,
    will: { topic: `presence/${user}`, payload: 'offline', qos: 1, retain: true }
    });
    await presence.publish(`presence/${user}`, 'online', { retain: true });

    // 3. fan messages out across chat servers with a queue group (one server handles each)
    await using nc = await natsConnect({ hostname: env.NATS, token: env.NATS_TOKEN });
    const room = nc.subscribe('room.general', { queue: 'chat-servers' });

    // 4. bridge the client's WebSocket into the bus
    const ws = await wsConnect(`wss://${env.GW}/chat?token=${sessionToken}`);
    for await (const frame of ws) {
    if (frame.type === 'text') await nc.publish('room.general', frame.data);
    }

    Use case: authenticated realtime messaging with horizontal fan-out and presence.

    Modules: NATS (JetStream) + MQTT + Syslog, recovery.spec.ts

    • NATS with JetStream NATS + NATS_TOKEN; the server must be started with -js.
    • MQTT broker BROKER; with persistence enabled for cleanSession: false drains.

    See Environment & Services for value formats and how to obtain each.

    Resilience across the stack: NATS JetStream durable streams + consumers verify message continuity (no loss / no duplication) across a client reconnect, and MQTT persistent sessions (cleanSession: false + a fixed clientId) reconnect and drain QoS-1 messages queued while the subscriber was offline.

    import { connect as mqttConnect } from 'edgeport/mqtt';
    import { connect as natsConnect } from 'edgeport/nats';

    // MQTT persistent session: messages published while we were gone are waiting on reconnect
    await using sub = await mqttConnect({
    hostname: env.BROKER,
    clientId: 'ingest-1',
    cleanSession: false
    });
    for await (const m of sub.subscribe('ingest/#', { qos: 1 })) {
    // process m here; QoS-1 delivery survives a disconnect/reconnect
    }

    // NATS JetStream durable continuity is driven over core request-reply to $JS.API.*:
    await using nc = await natsConnect({ hostname: env.NATS, token: env.NATS_TOKEN });
    const enc = new TextEncoder();
    await nc.request(
    '$JS.API.STREAM.CREATE.EVENTS',
    enc.encode(JSON.stringify({ name: 'EVENTS', subjects: ['events.>'] }))
    );
    await nc.publishJson('events.created', { id: 1 }); // acked + persisted by the stream
    // a durable consumer replays un-acked messages after a reconnect - see the spec for the full dance

    Tests run under workerd and cannot restart Docker, so "failover" is modeled as a client reconnect rather than a server-node kill - the message-continuity guarantees are what matter and are fully asserted.

    Use case: at-least-once pipelines that must survive disconnects without losing messages.

    Modules: SSH + SFTP + MQTT + Syslog, recovery-agent.spec.ts

    • MQTT broker BROKER; device telemetry + Last Will.
    • SSH/SFTP host deviceHost + private key SSH_KEY; the device the operator reaches.

    See Environment & Services for value formats and how to obtain each.

    The IoT/edge ops loop: devices report telemetry over MQTT (QoS 1) with a Last Will for offline detection; an operator SSHes in and pushes a firmware blob over SFTP with a SHA-256 checksum verified on the device and resume-on-drop via { offset }; SSH exec applies and restarts; the device's Syslog confirms.

    import { connect as mqttConnect } from 'edgeport/mqtt';
    import { connect as sshConnect } from 'edgeport/ssh';
    import { connect as sftpConnect } from 'edgeport/sftp';

    // device side: telemetry + last-will so the fleet sees it drop
    await using device = await mqttConnect({
    hostname: env.BROKER,
    clientId: deviceId,
    will: { topic: `devices/${deviceId}/status`, payload: 'offline', qos: 1 }
    });
    await device.publishJson(`devices/${deviceId}/telemetry`, { cpu: 0.31 }, { qos: 1 });

    // operator side: push firmware, verify the checksum on the box, apply, restart
    await using ssh = await sshConnect({
    hostname: deviceHost,
    username: 'ops',
    privateKey: { pem: env.SSH_KEY }
    });
    await using sftp = await sftpConnect({ session: ssh });
    await sftp.writeFile('/tmp/fw.bin', firmware);

    const digest = [...new Uint8Array(await crypto.subtle.digest('SHA-256', firmware))]
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('');
    const { stdout } = await ssh.exec('sha256sum /tmp/fw.bin');
    if (!stdout.includes(digest)) throw new Error('firmware checksum mismatch');
    await ssh.exec('fwupdate /tmp/fw.bin && reboot');

    Use case: remote device/firmware management and health monitoring.

    Modules: FTP + SFTP + MQTT + STOMP + Syslog, healthcare.spec.ts

    • FTP server FTP (+ username/password at runtime); the lab drop zone.
    • MQTT broker BROKER and STOMP broker MQ + MQ_USER/MQ_PASS; the two downstream consumers.
    • Syslog collector SIEM; the audit trail.

    See Environment & Services for value formats and how to obtain each.

    A healthcare interface engine (Mirth/Rhapsody-class): a lab drops an HL7 batch over FTP, the engine parses it into messages/segments (MSH/PID) and republishes events to two downstream consumers - MQTT and STOMP. The STOMP (EHR) subscriber uses ack: 'client'; an acked message is not redelivered. Every stage writes an audited Syslog trail.

    import { getFile } from 'edgeport/ftp';
    import { connect as mqttConnect } from 'edgeport/mqtt';
    import { connect as stompConnect } from 'edgeport/stomp';
    import { connect as syslogConnect } from 'edgeport/syslog';

    // pick up the batch the lab dropped (plain FTP; FTPS is not supported - see note)
    const batch = new TextDecoder().decode(
    await getFile({ hostname: env.FTP, username, password, path: '/in/lab.hl7' })
    );
    const messages = batch.split('\r\r'); // one HL7 message per block

    await using mqtt = await mqttConnect({ hostname: env.BROKER, clientId: 'hl7-engine' });
    await using mq = await stompConnect({ hostname: env.MQ, login: env.MQ_USER, passcode: env.MQ_PW });
    await using audit = await syslogConnect({
    hostname: env.SIEM,
    port: 6514,
    tls: 'implicit',
    appName: 'hl7'
    });

    for (const hl7 of messages) {
    const pid = hl7.split('\r').find((s) => s.startsWith('PID'));
    await mqtt.publish('hl7/adt', hl7, { qos: 1 }); // downstream consumer A
    await mq.send('/queue/hl7.ehr', hl7); // downstream consumer B (acks delivery)
    await audit.info(`routed ${pid}`);
    }

    // the EHR side acks what it has durably stored:
    const ehr = mq.subscribe('/queue/hl7.ehr', { ack: 'client' });
    for await (const m of ehr) {
    // persist m.body (the EHR write) here
    await m.ack?.();
    }

    The recipe calls for FTPS; edgeport doesn't provide FTPS (Workers startTls can't reuse the control channel's TLS session), so plain edgeport/ftp is used - noted in the spec.

    Use case: transactional message routing with delivery acks and a full audit trail.

    Modules: FTP + SFTP + Syslog + SMTP, mainframe.spec.ts

    • Landing FTP LANDING and secure SFTP DR (+ username/password at runtime); the insecure-in / secure-out legs.
    • Syslog collector SIEM and SMTP SMTP + SMTP_USER/SMTP_PW to OPS; per-leg audit + the job-summary email.

    See Environment & Services for value formats and how to obtain each.

    The classic "insecure-inside, secure-outside" hybrid: a legacy system pushes fixed-width, CRLF-terminated records over plain FTP into a landing zone; a transfer agent re-sends them securely over SFTP (with resume-on-interruption); each leg emits Syslog; a job-summary email goes out over SMTP at the end.

    import { connect as ftpConnect } from 'edgeport/ftp';
    import { connect as sftpConnect } from 'edgeport/sftp';
    import { connect as syslogConnect } from 'edgeport/syslog';
    import { send } from 'edgeport/smtp';

    await using audit = await syslogConnect({
    hostname: env.SIEM,
    port: 6514,
    tls: 'implicit',
    appName: 'erp-batch'
    });

    // 1. pull the fixed-width file the mainframe dropped over plain FTP
    await using ftp = await ftpConnect({ hostname: env.LANDING, username, password });
    const file = await ftp.get('NIGHTLY.DAT');
    await audit.info('landed NIGHTLY.DAT');

    // 2. forward it securely over SFTP (byte-exact; resumes if interrupted)
    await using sftp = await sftpConnect({ hostname: env.DR, username, password });
    await sftp.writeFile('/incoming/nightly.dat', file);
    await audit.info('forwarded NIGHTLY.DAT');

    // 3. job-summary email
    await send({
    hostname: env.SMTP,
    port: 587,
    auth: { username: env.SMTP_USER, password: env.SMTP_PW },
    from: 'batch@example.com',
    to: env.OPS,
    subject: 'nightly batch complete',
    text: `${file.length} bytes transferred`
    });

    The recipe calls for active-mode FTP; edgeport FTP is passive-only (Workers can't accept inbound connections), so passive mode is used. The CRLF-terminated fixed-width records are forwarded in BINARY mode and asserted byte-exact end to end - preserving them verbatim is a binary-transfer property, since a spec-compliant FTP server normalizes CRLF in ASCII (TYPE A) mode.

    Use case: legacy ERP/mainframe file exchange bridged to modern secure transfer.

    Modules: FTP + Syslog + SMTP, monitoring.spec.ts

    • FTP server FTP (+ username/password at runtime); passive mode, ports 21 + a passive range.
    • Syslog collector SIEM and SMTP SMTP + SMTP_USER/SMTP_PW to ONCALL; failure audit + alert.

    See Environment & Services for value formats and how to obtain each.

    The parts of passive FTP that actually break in production: EPSV-first/PASV-fallback negotiation, passive-port-range pressure (sequential transfers forcing port reuse), control-connection survival during a large transfer, and failure handling - a failed transfer is caught, logged to Syslog, and alerted over SMTP.

    import { connect as ftpConnect } from 'edgeport/ftp';
    import { connect as syslogConnect, Severity } from 'edgeport/syslog';
    import { send } from 'edgeport/smtp';

    await using audit = await syslogConnect({
    hostname: env.SIEM,
    port: 6514,
    tls: 'implicit',
    appName: 'ftp-mon'
    });
    await using ftp = await ftpConnect({ hostname: env.FTP, username, password }); // EPSV-first, PASV fallback

    try {
    const data = await ftp.get('exports/large.csv');
    await audit.info(`transfer ok ${data.length}b`);
    await ftp.list('exports'); // control connection still healthy after a large data transfer
    } catch (err) {
    // the data channel stalled/failed - log it and page on-call
    await audit.log({ severity: Severity.alert, message: `FTP transfer failed: ${err}` });
    await send({
    hostname: env.SMTP,
    port: 587,
    auth: { username: env.SMTP_USER, password: env.SMTP_PW },
    from: 'mon@example.com',
    to: env.ONCALL,
    subject: 'FTP transfer failed',
    text: String(err)
    });
    }

    Resume uses real RFC 959 REST offset resume - put(path, rest, { append: true }) to continue an upload and get(path, { offset }) to fetch just the tail.

    Use case: monitoring and alerting for passive-FTP-behind-NAT deployments.

    Modules: SSH + SFTP + SMTP + Syslog, report.spec.ts

    • SSH/SFTP host BOX + private key SSH_KEY; runs and serves the report.
    • SMTP SMTP to ONCALL/STAKEHOLDERS; distributes the report (attachment) and failure alerts.

    See Environment & Services for value formats and how to obtain each.

    The classic reporting cron: a scheduler SSHes into a host to run a report job, pulls the output over SFTP with a SHA-256 integrity check, emails it to stakeholders as a MIME attachment, logs the run to Syslog, and alerts on failure.

    import { connect as sshConnect } from 'edgeport/ssh';
    import { connect as sftpConnect } from 'edgeport/sftp';
    import { send } from 'edgeport/smtp';

    await using ssh = await sshConnect({
    hostname: env.BOX,
    username: 'reports',
    privateKey: { pem: env.SSH_KEY }
    });
    const { code } = await ssh.exec('generate-daily-report > /var/reports/today.csv');
    if (code !== 0) {
    await send({
    hostname: env.SMTP,
    tls: 'off',
    from: 'cron@x',
    to: env.ONCALL,
    subject: 'report FAILED',
    text: 'job exited nonzero'
    });
    throw new Error('report job failed');
    }

    // pull + verify integrity
    await using sftp = await sftpConnect({ session: ssh });
    const csv = await sftp.readFile('/var/reports/today.csv');
    const digest = [...new Uint8Array(await crypto.subtle.digest('SHA-256', csv))]
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('');
    if (!(await ssh.exec('sha256sum /var/reports/today.csv')).stdout.includes(digest))
    throw new Error('checksum mismatch');

    // distribute as an attachment
    await send({
    hostname: env.SMTP,
    tls: 'off',
    from: 'cron@x',
    to: env.STAKEHOLDERS,
    subject: 'Daily report',
    text: 'Attached.',
    attachments: [{ filename: 'today.csv', content: csv, contentType: 'text/csv' }]
    });

    Use case: ops/reporting cron jobs that generate, fetch, and distribute artifacts.

    Modules: STOMP + MQTT + NATS + Syslog, messaging.spec.ts

    • STOMP broker MQ + MQ_USER/MQ_PASS; the transactional producer/consumer (ActiveMQ/RabbitMQ).
    • MQTT broker BROKER and NATS NATS + NATS_TOKEN; the bridged downstream consumers.

    See Environment & Services for value formats and how to obtain each.

    Transactional produce with multiple consumers: a producer stages sends in a STOMP transaction (a rolled-back transaction never reaches subscribers), ack modes (client vs client-individual) behave correctly, and committed messages are bridged - at the application level, since the brokers are separate - to MQTT and NATS subscribers byte-for-byte.

    import { connect as stompConnect } from 'edgeport/stomp';
    import { connect as mqttConnect } from 'edgeport/mqtt';
    import { connect as natsConnect } from 'edgeport/nats';

    await using mq = await stompConnect({ hostname: env.MQ, login: env.MQ_USER, passcode: env.MQ_PW });
    await using mqtt = await mqttConnect({ hostname: env.BROKER, clientId: 'bridge' });
    await using nc = await natsConnect({ hostname: env.NATS, token: env.NATS_TOKEN });

    // stage two sends; commit releases both atomically (abort would deliver neither)
    const tx = await mq.begin();
    await tx.send('/queue/orders', payload);
    await tx.send('/queue/audit', entry);
    await tx.commit();

    // a subscriber consumes the committed message and the worker bridges it to other transports
    for await (const m of mq.subscribe('/queue/orders', { ack: 'client' })) {
    await mqtt.publish('orders', m.body, { qos: 1 });
    await nc.publish('orders', m.body);
    await m.ack();
    break;
    }

    Use case: transactional pipelines whose events must reach heterogeneous consumers.

    Modules: LDAP + SSH + SFTP + Syslog, auth.spec.ts

    • Directory LDAP + SVC_DN/SVC_PW; identity + group membership (with ou=people / ou=groups).
    • SSH/SFTP host BOX + private key SSH_KEY; the gated action target.

    See Environment & Services for value formats and how to obtain each.

    LDAP as the single identity source for a fleet: a bind verifies the password, a group lookup authorizes the action, locked accounts are denied, and only then does the SSH/SFTP action run - every decision and command audited to Syslog.

    import { authenticate, search as ldapSearch, eq } from 'edgeport/ldap';
    import { connect as sshConnect } from 'edgeport/ssh';

    async function authorize(uid: string, password: string): Promise<boolean> {
    // 1. authenticate via bind-search-bind in one call; eq() keeps an untrusted uid from
    // injecting filter syntax. returns the located entry, or null on bad password / no match
    const entry = await authenticate({
    hostname: env.LDAP,
    bindDN: env.SVC_DN,
    bindPassword: env.SVC_PW,
    base: 'ou=people,dc=example,dc=org',
    userFilter: eq('uid', uid),
    password
    });
    if (!entry) return false;
    // 2. authorize: not locked, and a member of cn=admins
    if (entry.attributes.employeeType?.includes('locked')) return false;
    const admins = await ldapSearch({
    hostname: env.LDAP,
    bindDN: env.SVC_DN,
    password: env.SVC_PW,
    base: 'cn=admins,ou=groups,dc=example,dc=org',
    filter: '(objectClass=*)'
    });
    return admins[0]?.attributes.member?.some((m) => m.startsWith(`uid=${uid},`)) ?? false;
    }

    if (await authorize(uid, password)) {
    await using ssh = await sshConnect({
    hostname: env.BOX,
    username: 'svc',
    privateKey: { pem: env.SSH_KEY }
    });
    await ssh.exec('systemctl restart app'); // gated action
    }

    The SSH box authenticates its own service account; the LDAP bind + group check is the application authorization gate in front of it (the standard "LDAP-backed fleet" pattern). The edgeport LDAP module is bind+search, so access changes are shown via seeded membership.

    Use case: centralized, audited authorization for a fleet of hosts.

    Modules: NATS + WebSocket + MQTT + STOMP + Syslog, notifications.spec.ts

    • NATS NATS + NATS_TOKEN; the notification core.
    • WebSocket gateway GW, MQTT broker BROKER, STOMP broker MQ + MQ_USER/MQ_PASS; the three fan-out transports.

    See Environment & Services for value formats and how to obtain each.

    One event, many transports: a notification core on NATS fans each event out to browsers (WS), mobile/IoT (MQTT QoS 1), and JVM/legacy consumers (STOMP client-ack) - bridged at the application level. Ordering is preserved per transport, per-protocol ack/QoS is respected, and a slow consumer on one transport does not stall the others.

    import { connect as natsConnect } from 'edgeport/nats';
    import { connect as wsConnect } from 'edgeport/ws';
    import { connect as mqttConnect } from 'edgeport/mqtt';
    import { connect as stompConnect } from 'edgeport/stomp';

    await using nc = await natsConnect({ hostname: env.NATS, token: env.NATS_TOKEN });
    await using mqtt = await mqttConnect({ hostname: env.BROKER, clientId: 'notify' });
    await using mq = await stompConnect({ hostname: env.MQ, login: env.MQ_USER, passcode: env.MQ_PW });
    const ws = await wsConnect(`wss://${env.GW}/notify`);

    // the core publishes once on NATS; the worker is the fan-out bridge to every transport
    for await (const event of nc.subscribe('notifications.>')) {
    ws.send(event.data); // browsers
    await mqtt.publish('notifications', event.data, { qos: 1 }); // mobile / IoT
    await mq.send('/topic/notifications', event.data); // JVM / legacy
    }

    Use case: product notification hubs delivering one event to heterogeneous clients.

    Modules: LDAPS + SSH + SFTP + Syslog, credentials.spec.ts

    • LDAPS directory LDAP + SVC_DN/SVC_PW; connect via edgeport/ldaps (TLS on 636); the server cert must chain to a CA the runtime trusts.
    • SSH/SFTP host BOX + private key SSH_KEY; the gated action target.

    See Environment & Services for value formats and how to obtain each.

    An auth gateway binds over LDAPS so the simple-bind password never crosses the wire in cleartext. The security guarantees live in the TLS layer: an untrusted/self-signed/expired or hostname-mismatched server certificate makes the bind fail closed before any credential is sent, the client never silently downgrades to plaintext LDAP, and expectedServerHostname pins the server identity. Only after the directory check passes does the gated SSH/SFTP action run, with every decision audited to Syslog.

    import { connect as ldapsConnect } from 'edgeport/ldaps';
    import { connect as sshConnect } from 'edgeport/ssh';
    import { ConnectionError } from 'edgeport';

    // fail closed: an untrusted directory cert is rejected before the bind, so no password leaks
    try {
    await using dir = await ldapsConnect({
    hostname: env.LDAP,
    expectedServerHostname: env.LDAP, // the cert must match this identity
    bindDN: env.SVC_DN,
    password: env.SVC_PW
    });
    // ... bind succeeded over a verified TLS channel; gate the action here
    await using ssh = await sshConnect({
    hostname: env.BOX,
    username: 'svc',
    privateKey: { pem: env.SSH_KEY }
    });
    await ssh.exec('systemctl restart app');
    } catch (err) {
    if (err instanceof ConnectionError) {
    // TLS/cert validation failed - do NOT fall back to plaintext LDAP; deny the action
    }
    }

    Workers runtime limits (documented in the spec): workerd validates the server cert but cannot be made to trust a private CA, so a trusted-CA happy-path bind and on-wire packet capture are not testable locally - the recipe asserts the fail-closed gate and no-downgrade behavior.

    Use case: an identity gateway where credentials must never traverse an unverified channel.

    Modules: LDAPS + Syslog + SMTP, certificates.spec.ts

    • LDAPS directory LDAP + SVC_DN/SVC_PW; edgeport/ldaps on 636; the monitored server certificate.
    • Syslog collector SIEM and SMTP SMTP to ONCALL; cert-failure audit + alert.

    See Environment & Services for value formats and how to obtain each.

    The operational failure mode that breaks LDAPS in production: the directory server's certificate is untrusted (expired / self-signed / wrong hostname), so binds start failing closed. The deployment detects it, audits the failure to Syslog, and alerts on-call over SMTP - and keeps failing closed on retry until the cert is fixed.

    import { connect as ldapsConnect } from 'edgeport/ldaps';
    import { connect as syslogConnect } from 'edgeport/syslog';
    import { send } from 'edgeport/smtp';
    import { ConnectionError } from 'edgeport';

    await using audit = await syslogConnect({
    hostname: env.SIEM,
    port: 6514,
    tls: 'implicit',
    appName: 'ldaps-mon'
    });

    try {
    await using dir = await ldapsConnect({
    hostname: env.LDAP,
    bindDN: env.SVC_DN,
    password: env.SVC_PW
    });
    // ... bind ok
    } catch (err) {
    if (err instanceof ConnectionError) {
    await audit.error('ldaps cert validation failed');
    await send({
    hostname: env.SMTP,
    tls: 'off',
    from: 'ldaps-mon@example.org',
    to: env.ONCALL,
    subject: 'CERT: directory TLS validation failing',
    text: String(err)
    });
    }
    }

    Workers surfaces one opaque error for all cert problems (it does not distinguish expired vs hostname-mismatch vs self-signed vs broken-chain), and a successful post-renewal bind can't be shown locally (no trusted cert validates) - the recipe asserts one representative fail-closed -> alert + audit path.

    Use case: detecting and alerting on directory-certificate expiry/rotation failures.

    Modules: SMPP + SMS-over-email (SMTP) + Syslog + util, sms.spec.ts

    • SMSC SMSC + SMPP_SYSTEM_ID/SMPP_PW: an SMPP v3.4 SMSC (a carrier/aggregator, or a simulator) reachable on 2775.
    • SMTP SMTP + SMTP_USER/SMTP_PW: the email-to-SMS fallback path.
    • Syslog collector SIEM: the audit trail.

    See Environment & Services for value formats and how to obtain each.

    A two-tier SMS sender: the primary path binds to a carrier SMSC over SMPP and submits with a requested delivery receipt (carrier-grade delivery, confirmed by the returned deliver_sm); if the SMPP link is unreachable the fallback addresses the recipient's carrier email-to-SMS gateway and sends it over SMTP. The flaky connect is wrapped in util.retry (which retries only transient transport errors, never an auth/protocol rejection), and every step is audited to Syslog.

    import { connect as smppConnect } from 'edgeport/smpp';
    import { sendSms } from 'edgeport/smtp';
    import { connect as syslogConnect } from 'edgeport/syslog';
    import { retry } from 'edgeport/util';

    await using audit = await syslogConnect({
    hostname: env.SIEM,
    port: 6514,
    tls: 'implicit',
    appName: 'sms'
    });

    try {
    // 1. primary: submit over SMPP (retry only transient connect failures)
    await using smpp = await retry(() =>
    smppConnect({
    hostname: env.SMSC,
    systemId: env.SMPP_SYSTEM_ID,
    password: env.SMPP_PW,
    bindMode: 'transceiver'
    })
    );
    const id = await smpp.submit({
    source: 'EDGEPORT',
    destination: number,
    message,
    registeredDelivery: true
    });
    await audit.info(`submitted ${id}`);

    // confirm delivery from the SMSC receipt that arrives on the same session
    for await (const inbound of smpp.messages()) {
    const r = inbound.receipt();
    if (inbound.isDeliveryReceipt && r.id === id) {
    await audit.info(`delivered ${id} ${r.stat}`); // e.g. 'DELIVRD'
    break;
    }
    }
    } catch (err) {
    // 2. fallback: the recipient's carrier email-to-SMS gateway over SMTP
    await audit.warn(`smpp failed, using the email gateway: ${err}`);
    const result = await sendSms({
    hostname: env.SMTP,
    auth: { username: env.SMTP_USER, password: env.SMTP_PW },
    from: 'alerts@example.com',
    to: { number, carrier }, // e.g. { number: '12065550100', carrier: 'att' }
    text: message
    });
    await audit.info(`email-sms to ${result.accepted[0]}`);
    }

    The spec runs the SMPP leg against the ukarim/smscsim SMSC simulator (submit + a confirmed DELIVRD receipt over one session, retry-wrapped) and the email-to-SMS leg against GreenMail (the computed number@gateway address is accepted and echoed back in the send result), auditing every step to the syslog readback sink.

    Use case: a resilient SMS sender that prefers a carrier SMPP link and falls back to the email-to-SMS gateway, with delivery confirmation and a full audit trail.

    Modules: SIP + Syslog, sip.spec.ts

    • SIP server SIP + SIP_USER/SIP_PW: a SIP registrar/proxy on 5060 (Asterisk, FreeSWITCH, Kamailio, OpenSIPS, or a cloud SIP trunk) that routes MESSAGE between registered users.
    • Syslog collector SIEM: the audit trail.

    See Environment & Services for value formats and how to obtain each.

    Deliver an alert to an on-call endpoint over SIP: both sides register with RFC 5626 outbound (so a listen-less Worker receives inbound requests on its own connection), the sender delivers a pager-mode MESSAGE (RFC 3428, digest-authenticated and routed by the proxy), the on-call side receives it on its registered flow, and every step is audited to Syslog. SIP + MSRP are the chat protocols RCS rides on, so this is the RCS-family messaging path against open SIP infrastructure - it does not reach carrier RCS handsets.

    import { connect as sipConnect } from 'edgeport/sip';
    import { connect as syslogConnect } from 'edgeport/syslog';

    await using audit = await syslogConnect({
    hostname: env.SIEM,
    port: 6514,
    tls: 'implicit',
    appName: 'sip-alerts'
    });

    // the on-call endpoint registers and listens for inbound MESSAGEs on its flow
    await using oncall = await sipConnect({
    hostname: env.SIP,
    domain: env.SIP_DOMAIN,
    username: 'oncall',
    password: env.SIP_PW
    });
    await oncall.register();

    // the sender registers and delivers the alert (the proxy challenges + routes it)
    await using sender = await sipConnect({
    hostname: env.SIP,
    domain: env.SIP_DOMAIN,
    username: 'alerts',
    password: env.SIP_PW
    });
    await sender.register();
    await sender.message('oncall', 'ALERT disk almost full');
    await audit.info('sip alert sent');

    for await (const m of oncall.messages()) {
    await audit.info(`sip alert received from ${m.from}`);
    break; // handle m.text() here
    }

    The spec registers two endpoints against the Dockerized Kamailio (docker/sip, realm edgeport.test), routes a digest-authenticated MESSAGE between them, confirms the on-call side receives it on its outbound flow, and asserts the ordered register -> send -> receive trail on the syslog readback sink. A long-lived registration belongs in a Durable Object (an open socket keeps a DO alive ~15 min; the session refreshes REGISTER, and you reconnect on a DO alarm).

    Use case: routing alerts/notifications and two-way messaging over SIP to PBXs, softphones, and SIP trunks from a Worker.


    • Syslog readback: the Dockerized syslog service ingests on :5514 and serves the captured log back on :5515, so tests can assert exactly what was logged (readSyslog()).
    • Plaintext transports: GreenMail's plaintext mail ports are used with tls: 'off' (workerd rejects GreenMail's self-signed cert on the implicit-TLS ports).
    • Port forwarding: SSH forwardOut (direct-tcpip) is verified against Dropbear, which permits TCP forwarding (linuxserver/openssh disables it by default).
    • JetStream: the NATS server runs with -js enabled for the recovery recipe.
    • SMPP: the ukarim/smscsim SMSC simulator accepts any bind, returns a message_id on submit_sm, and emits a delivery-receipt deliver_sm (stat:DELIVRD) a couple of seconds after a submit_sm that set registered_delivery; mobile-originated messages can be injected via its HTTP form on :12775.
    • SIP: a Kamailio 5.6 registrar/proxy (docker/sip, built at runtime on a digest-pinned Debian base) challenges digest in realm edgeport.test (creds tester/testpass, a realm-static password so any username binds), accepts RFC 5626 outbound registrations, and routes MESSAGE between registered AORs over TCP 5060. Its MSRP relay listens on 2855. MSRP session-mode chat is unit-tested at the codec level; end-to-end MSRP through the relay needs the relay's AUTH handshake (a documented follow-up), so the integration suite covers the SIP signaling + pager-mode MESSAGE path.