MS MarlinSpike Passive OT/ICS Topology Workbench
Repo family

One suite repo, several focused component repos, and a clean artifact boundary.

MarlinSpike is moving from a single mixed repository toward a repo family where the suite repo vendors a known-good combination of workbench, engine, plugins, and Rust engines.

Suite repo

The top-level marlinspike repo is the integration surface for teams that want one clone.

Authoritative components

Engine, workbench, plugins, and Rust engines are each intended to become authoritative in their own repos.

Subtree model

The suite repo uses git subtree, not submodules, to vendor component repos.

Repo model

Repository Role
marlinspike The suite repo, integration home, and one-clone option.
marlinspike-msengine The core analysis engine repo. Internal package and CLI name: msengine.
marlinspike-workbench The web UI and collaboration surface that reads report artifacts and can optionally invoke the engine.
marlinspike-plugins The Python plugin monorepo for report-consuming extensions.
marlinspike-engines The Rust engine workspace for packet-facing and event-heavy components.

One clone for everything

The suite repo vendors component repos via git subtree. The docs frame that as a practical middle ground:

  • Users still get normal git clone behavior.
  • Teams avoid a git-submodule setup burden.
  • Component repos can keep their own release cycles.
  • The suite repo can pin a known-good combination for operators who want the whole stack together.

Contract boundary

The portable report artifact is the handoff between components:

  1. msengine produces a report artifact from captured traffic.
  2. marlinspike-workbench consumes that artifact for review, triage, and collaboration.
  3. Python plugins consume the same finished report and emit sidecar artifacts.
  4. Rust engines may produce upstream artifacts or event streams that feed the engine or other components.

The workbench is intentionally usable even when the report was generated elsewhere and no local engine binary is present.

Current transition state

The docs are honest that the current repository still contains both engine and workbench code while the split is being prepared.

  • The root marlinspike repo still carries operational engine and Flask UI code today.
  • The first bootstrap subtree prefix is msengine/.
  • Until cutover is complete, root _ms_engine.py remains the operational engine source.
  • The helper script scripts/sync-msengine-bootstrap.sh mirrors the operational engine into the subtree copy.

Ownership boundaries for contributors

The contribution docs already encourage developers to think in future component boundaries even before the extraction finishes:

  • Packet-facing parsing, observables, and engine CLI work belong to the msengine boundary.
  • Flask routes, templates, auth, projects, and report-review UX belong to the workbench boundary.
  • ATT&CK, IEC 62443, PERA, and other report-consuming overlays belong to the future plugins boundary.
  • Packet-heavy Rust parsers belong to the future engines boundary.

Need the concrete extension contracts behind that split?

The extensibility docs define how Rust engines, Python plugins, and YAML rule packs are supposed to interact with the report artifact and each other.