Skip to content

issmailturann/ma-workflow-engine

Repository files navigation

ma-workflow-engine

Early-stage modular infrastructure for M&A workflows: deal pipeline, due diligence tracking, risk register, decision log and post-merger integration, built on TypeScript and PostgreSQL.

Status: early-stage / experimental — data model and domain core; API and admin panel are on the roadmap.

Overview

ma-workflow-engine is the data and domain foundation we are building at Quantum Orbit Labs for software that manages merger and acquisition processes end to end.

The repository currently contains three things: a complete PostgreSQL data model, a typed TypeScript domain core (deal stage state machine, risk scoring and due-diligence checklist calculations) and unit tests with a runnable synthetic example. There is no HTTP API, persistence layer or user interface yet. Those are on the roadmap, and we prefer to say so rather than scaffold placeholders.

This software models workflow state. It does not provide financial or legal advice.

Problem

M&A processes fragment across documents, people, decisions, financial data and tasks. Spreadsheets, mail threads and data rooms each hold a slice of the truth. Stage changes happen implicitly, diligence progress is estimated rather than measured, and decisions and their rationale are reconstructed after the fact.

We think software should turn this into a trackable system: explicit deal stages with guarded transitions, a due-diligence checklist with measurable progress, a risk register with consistent scoring, a decision log that records what was decided and why, and an append-only audit history underneath all of it.

What this project provides

  • A relational data model (db/schema.sql) covering the whole process: deals, target companies, document requests, document metadata, due-diligence checklist items, risks, decisions, ownership entries, financial metrics, integration tasks and an audit log.
  • A typed domain core in strict TypeScript:
    • src/domain/dealStages.ts — deal stage state machine with an explicit transition map and guard reasons.
    • src/domain/riskScoring.ts — likelihood times impact scoring with configurable severity bands.
    • src/domain/checklist.ts — due-diligence progress and completion calculations.
  • Unit tests for the domain core and a runnable example with synthetic data.

Not included yet: HTTP API, persistence layer, authentication, user interface. See Status and roadmap.

Architecture

Module overview

Four functional modules operate over one shared PostgreSQL model; every material change is meant to land in the append-only audit log.

The domain core is deliberately pure. Functions take rows in and return values out, with no I/O, so the same logic can later serve an API, background jobs and a user interface without change. The database stores state; the domain layer owns the rules for how state may change.

Core concepts

Deal stages

A deal moves through a fixed pipeline, one stage at a time:

sourcing -> screening -> indicative_offer -> due_diligence -> negotiation -> signing -> closing -> integration

Two special stages sit outside the pipeline:

  • on_hold — reachable from any stage before integration. The engine records the held-from stage and only allows resuming exactly there, or dropping the deal.
  • dropped — reachable from any stage before integration; terminal.

integration is also terminal. Transitions go through transition(deal, target), which returns a result object instead of throwing: either the updated deal or a machine-readable code (transition_not_allowed, resume_stage_mismatch and others) with a human-readable reason.

Risk scoring

Risks carry a likelihood and an impact, each an integer from 1 to 5. The score is their product; severity bands are defined in src/config.ts and can be overridden per call:

Severity Score range
low 1 to 4
moderate 5 to 9
high 10 to 15
critical 16 to 25

Severity is always derived, never stored, so changing the bands does not require a data migration.

Checklist progress

Due-diligence checklist items count toward completion unless marked not_applicable. Progress is completed over applicable items, and a checklist is complete when every applicable item is. An empty checklist is treated as vacuously complete, so callers should require a populated checklist before relying on that signal.

Data model

Eleven tables for PostgreSQL 14 or later, with UUID primary keys, native enum types, foreign keys and check constraints. Apply to an empty database:

createdb ma_workflow
psql ma_workflow -f db/schema.sql
Table Purpose
deals One row per acquisition process; current stage plus held-from stage
target_companies Companies under evaluation
document_requests Information request list per deal
documents Document metadata and content hash; file bodies stay in external storage
dd_checklist_items Due-diligence work items per category
risks Risk register; likelihood and impact stored, severity derived
decisions Decision log: outcome, rationale, deciding role
ownership_entries Cap table over time
financial_metrics Reported, normalized or forecast figures per company and period
integration_tasks Post-merger plan by workstream, with task dependencies
audit_log Append-only history of every material change

updated_at columns are maintained by a shared trigger. Stage transition rules are deliberately not enforced in SQL; the domain layer owns them.

Installation

Requires Node.js 22 or later. PostgreSQL 14 or later is only needed to apply the schema.

git clone https://github.com/issmailturann/ma-workflow-engine.git
cd ma-workflow-engine
npm ci
npm test

The package is not published to npm yet; consume it from source.

Usage

import { assessRisk, checklistProgress, transition } from './src/index.js';

// deal is a Deal row loaded from your store.
const result = transition(deal, 'due_diligence');
if (result.ok) {
  console.log(`now in ${result.deal.stage}`);
} else {
  console.log(`${result.code}: ${result.reason}`);
}

const { score, severity } = assessRisk(4, 4); // score 16, severity "critical"

const progress = checklistProgress(items); // ratio, counts and completion flag

A complete walk-through with synthetic data:

npx tsx examples/deal-lifecycle.ts

Security

  • The engine currently exposes no network surface: it is a schema plus pure functions.
  • audit_log is designed append-only. In managed environments, grant only INSERT and SELECT on it.
  • documents stores metadata and a SHA-256 content hash only; file bodies never enter the database.
  • Role-based access control is on the roadmap and arrives together with the API layer. Until then, database privileges are the control plane.
  • All example and test data is synthetic.
  • To report a vulnerability, see SECURITY.md.

Status and roadmap

Status: early-stage / experimental — data model and domain core; API and admin panel are on the roadmap.

The data model and domain core are implemented and tested. Interfaces may still change without notice while we validate the model against real workflows.

Planned, in rough order:

  • REST/GraphQL API over the data model
  • React admin panel
  • Role-based access control
  • Document metadata ingestion
  • AI abstraction layer for document summarization

Contributing

See CONTRIBUTING.md. Short version: open an issue first, branch from main, keep pull requests small and make npm run lint && npm test && npm run build pass.

License

MIT — see LICENSE. Copyright (c) 2026 Quantum Orbit Labs.

About

Early-stage modular infrastructure for M&A workflows — deal pipeline, due diligence tracking, risk register, decision log and post-merger integration. TypeScript and PostgreSQL.

Topics

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages