Skip to content

Repository files navigation

FlowProof

Deterministic testing for n8n workflows.
Lint them, auto-generate branch-coverage tests, run them safely, and get a scorecard of exactly what's untested.

CI License: MIT Node >= 20">https://img.shields.io/badge/node-%E2%89%A5%2020-3fb950.svg"> TypeScript PRs welcome good first issues Stars

Install · Quick start · Why · Roadmap · Contributing

flowproof lint output — flagging an unhandled impure node, a hardcoded secret, leftover pinData, and an orphan node

If FlowProof looks useful, a ⭐ helps others find it — and tells me to keep building the next phases.


Status: v0.1 shipped the linter; execution has since landed on main. Available today: static analysis (flowproof lint), plus flowproof compile and flowproof run — a workflow's impure nodes are compiled out and it is executed for real, reporting which nodes ran and which never did. Branch-coverage scorecards, scenario generation, and record-and-replay are next (see the roadmap).

Why FlowProof

People build large n8n workflows (20–40+ nodes) and "test" them with a single happy-path run in the editor. That says almost nothing about production behavior. Real failures cluster where a smoke test never looks:

  • Data-contract mismatches — a field is null and a downstream expression crashes.
  • External services misbehaving — timeouts, 500s, 429s, malformed responses.
  • Untested branches — an IF/Switch path that has never once executed.
  • Non-idempotent side effects — a retry creates duplicate records or emails.
  • Loop/pagination bugs — non-termination, mishandled empty batches.

n8n's own Evaluations feature targets AI workflows (scoring probabilistic LLM output). FlowProof fills the other gap: deterministic testing of ordinary business workflows — structural, data-contract, branch-coverage, and failure-injection testing. It's complementary, not competitive.

Install

Published on npm under the @malharlakdawala/flowproof-* scope. The CLI package installs a command named flowproof:

# Global CLI
npm install -g @malharlakdawala/flowproof-cli
flowproof lint ./workflows/onboarding.json

# Or add the libraries to a project
npm install -D @malharlakdawala/flowproof-lint @malharlakdawala/flowproof-connect

Hitting EACCES on npm i -g? That's a global-npm-prefix permission issue on macOS/Linux, not a FlowProof problem — either fix the npm prefix or use pnpm add -g @malharlakdawala/flowproof-cli, which installs into your home directory.

Or build from source

Requirements: Node ≥ 20 and pnpm.

git clone https://github.com/malharlakdawala/flowproof.git
cd flowproof && pnpm install && pnpm build
pnpm flowproof lint examples/workflows/buggy.json

Quick start

# Lint an exported workflow JSON
flowproof lint ./workflows/onboarding.json

# Emit JUnit for CI
flowproof lint ./workflows/onboarding.json --format junit --out flowproof-results.xml

# Lint a workflow straight from a live n8n instance (Cloud or self-hosted)
export N8N_URL=https://your-tenant.app.n8n.cloud   # or http://localhost:5678
export N8N_API_KEY=…                                # never printed to logs
flowproof lint --instance --workflow-id abc123

# Scaffold a config
flowproof init

Run a workflow safely — every impure node is compiled out first, so no external service is contacted:

# First run writes a fixture template next to the workflow and stops
flowproof run ./workflows/onboarding.json
#   → wrote onboarding.fixtures.json — fields the workflow actually reads are
#     pre-filled as "TODO:<field>". Replace them and re-run.

flowproof run ./workflows/onboarding.json
#   Onboarding — success
#     ✓ Fetch Customer    [0]:1     1 item(s)
#     ✓ Check Plan Type   [0]:1 [1]:0
#     ✓ Send Welcome      [0]:1     1 item(s)
#
#     Never executed on this path
#       Notify Sales

# Inspect exactly what will run, without running it
flowproof compile ./workflows/onboarding.json

run needs an n8n available (npm i -g n8n, or --n8n <path>). It never contacts a real service: impure nodes are replaced with fixture emitters before execution, and compilation fails loudly if any of them is unmocked.

Programmatic use:

import { connect } from '@malharlakdawala/flowproof-connect';
import { lintWorkflow, formatReport } from '@malharlakdawala/flowproof-lint';

const model = await connect.file('./onboarding.json');
const report = lintWorkflow(model);
console.log(formatReport(report, 'pretty'));
process.exit(report.errorCount > 0 ? 1 : 0);

What the linter catches

no-unhandled-io, dangling-error-output, hardcoded-secret, leftover-pindata (errors by default) · unsafe-expression, hardcoded-url, no-retry-on-flaky-io, loop-no-termination-guard, orphan-node, deprecated-node-version (warnings) · and more — all configurable and pluggable. See @malharlakdawala/flowproof-lint.

Packages

FlowProof is a pnpm monorepo. Each package is independently versioned and testable.

Package Status Purpose
@malharlakdawala/flowproof-core ✅ v0.1 Normalized WorkflowModel, graph + fork analysis, expression extraction, node-behavior registry
@malharlakdawala/flowproof-connect ✅ v0.1 Load workflows from a JSON file or a live n8n instance
@malharlakdawala/flowproof-lint ✅ v0.1 Static analysis engine + built-in rules
@malharlakdawala/flowproof-cli ✅ v0.1 The CLI (installs the flowproof command)
@malharlakdawala/flowproof-scenarios 🚧 Phase 2 Branch-coverage scenario generation + stress menu
@malharlakdawala/flowproof-mock ✅ partial Compiles impure nodes into fixture emitters; fixture scaffolding
@malharlakdawala/flowproof-runner ✅ partial LocalRunner + result parsing; Docker runner and egress guard pending
@malharlakdawala/flowproof-assert 🚧 Phase 3 Matchers + coverage scorecard
@malharlakdawala/flowproof-report 🚧 Phase 4 Terminal / HTML / JUnit reporters
@malharlakdawala/flowproof-sdk 🚧 Phase 4 describe/it-style authoring API
@malharlakdawala/flowproof-record 🚧 Phase 5 Record real executions → replayable tests

Roadmap

Built in phases; each phase is independently shippable.

  • Phase 0 — Scaffolding. ✅ Monorepo, tooling, CI, example workflows.
  • Phase 1 — core + connect + lint.v0.1: a workflow linter.you are here
  • Phase 2 — fork discovery + structural scenario generation. flowproof generate.
  • Phase 3 — runner + mock + determinism + assert + scorecard. v0.2: generate + run + score.

Build order note: Phase 3 (execution) is being built before Phase 2 (generation). Generating scenarios before anything can run them means designing the Scenario type blind — the runner's real requirements should define it. Tracked in #17. Phase numbers are kept as-is so existing issue labels stay meaningful.

  • Phase 4 — stress-scenario library + reporters + GitHub Action + SDK. v0.3: full core product.
  • Phase 5 — record & replay + CloudRunner. v0.4: the flagship differentiators.
  • Phase 6 — extensibility hardening, docs site, community node-behavior registry. v1.0.

Development

pnpm install
pnpm build         # build all packages
pnpm test          # run the full test suite (Vitest)
pnpm typecheck     # project-wide type check
pnpm format        # prettier

Node ≥ 20 and pnpm are required.

Contributing

FlowProof is designed for community extension — new lint rules, matchers, runners, and especially node behaviors (n8n ships new nodes constantly). See CONTRIBUTING.md.

License

MIT © FlowProof contributors.

About

Deterministic testing for n8n workflows — lint, auto-generate branch-coverage tests, run them safely, and score exactly what's untested.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages