The Problem

Network documentation becomes stale the moment it's created. Teams maintain manual diagrams in draw.io or rely on IaC state that misses drift from resources provisioned outside the pipeline. Scanopy solves this by running a daemon that continuously scans the network and produces fresh topological views without per-device agents.

What This Does

Scanopy runs a single daemon on a schedule that scans the network and produces four views from each scan: L2 (physical topology), L3 (logical subnet/VLAN mapping), workloads (bare metal/hypervisor/container hierarchy), and application dependencies with service groupings. The daemon uses SNMP and Docker integration for discovery and can be deployed across segments to map multi-site topologies.

The codebase is split between backend (Rust, 802 files, 714 code files) and UI (Svelte/TypeScript, 458 files, 129 code files). Entry points are backend/src/lib.rs and ui/src/main.ts. The backend connects to Neo4j for the topology model and stores data via PostgreSQL migrations (112+ migration files exist under backend/migrations/). The UI renders the topology using Svelte components under ui/src/lib/features/topology/.

Key structural patterns:

  • backend/src/server/topology/service/main.rs – topology service entry point
  • ui/src/lib/features/topology/types/base.ts – hub module; 21 other topology modules depend on it
  • ui/src/lib/features/topology/interactions.ts – oversized file (846 lines), high cognitive load from deep nesting and branching
  • ui/src/lib/features/topology/layout/engine.ts – participates in a circular import dependency

How It Is Wired

Execution flows start at the daemon entry points. The backend daemon (backend/src/daemon/mod.rs) runs discovery via backend/src/daemon/discovery/ – modules for SNMP integration (backend/src/daemon/discovery/integration/snmp/), Docker scanning (backend/src/daemon/discovery/integration/docker/), and credential handling (backend/src/daemon/discovery/credentials.rs). Scanned data flows into a Neo4j model through backend/src/server/topology/. The UI (ui/src/main.ts) consumes the model via API calls; the topology feature layer (ui/src/lib/features/topology/) handles rendering, layout (elk-layout engine), and query resolution.

The import graph has 130 modules and 113 edges, with 2 modules in circular dependencies. The most connected module is ui/src/lib/features/topology/types/base.ts (Ca=21, Ce=0, instability=0) – changes here have blast radius across a quarter of the topology feature set. Instability is high in ui/src/lib/features/topology/pipeline/build-flow-edges (Ca=0, Ce=8, instability=1) and prepare (Ca=0, Ce=8, instability=1), indicating these are pure dependency consumers with no local callers – a change in their contracts ripples outward without local compensation. The circular import involves ui/src/lib/features/topology/layout/engine.ts, which should be decomposed to break the cycle.

What this code touches outside itself: the backend writes to Neo4j (graph database), persists data via PostgreSQL migrations, and exposes an HTTP API under backend/src/server/. The UI reads the model and renders SVG/Mermaid/Confluence exports. The daemon can be distributed across network segments.

How To Use It

Setup:

git clone https://github.com/moses-y/scanopy
cd scanopy
make setup   # or: docker compose up -d

The Makefile and docker-compose.yml at root provide the primary on-ramps. Docker images are published as mayanayza/scanopy-daemon and mayanayza/scanopy-server.

Configuration: Copy .env.example and set required variables. The file is at root .env.example. Key env vars likely include database connection strings, Neo4j credentials, and SNMP community strings – the actual schema should be verified against .env.example.

Running it:

# Start the daemon
docker compose up -d daemon
# Or build and run directly:
cargo run --bin daemon --manifest-path backend/Cargo.toml

The UI starts separately: npm run dev from the ui/ directory (per ui/package.json).

Real-World Use

A platform team runs the Scanopy daemon nightly across three data-center sites. The daemon scans L2/L3 topology via SNMP, identifies Docker containers, and maps service dependencies. The resulting Neo4j model is consumed by an internal dashboard that shows which workloads depend on a given database – eliminating the need to trace APM traces or maintain static diagrams. When a new Kubernetes cluster is provisioned, the next scan picks it up automatically; the L3 view updates to show the new subnet routing, and the application view surfaces the new service's dependencies. The team exports the L2 view as SVG for change-review meetings and embeds the Mermaid workflow in Confluence for live documentation.

Code Health & Issues

  • [HIGH/cognitive_load] Oversized files x3: ui/src/lib/features/topology/interactions.ts, ui/src/lib/features/topology/queries.ts, ui/src/lib/features/topology/layout/elk-layout.ts (846 lines each, max indentation depth 9). Fix: split by responsibility, extract guard clauses.
  • [HIGH/cognitive_load] High branching density x2: same three files above, 321 branch points over 846 lines. Fix: decompose decision logic into table/dispatch.
  • [HIGH/soundness] Import cycle member: ui/src/lib/features/topology/layout/engine.ts participates in circular dependency. Fix: extract shared types, invert dependency, or defer import.
  • [MEDIUM/clarity] Hub module: ui/src/lib/features/topology/types/base.ts – 21 modules depend on it; churn is high-blast-radius. Fix: keep stable and small; move volatile logic out.
  • [MEDIUM/cognitive_load] Deep nesting x53: same three oversized files. Fix: flatten with early returns.
  • Repository hygiene: committed secrets detected (guardian flags backend/src/server/credentials/impl/types/secrets.rs and backend/src/server/license/public_key.pem). Verify and rotate if needed.

The Bottom Line

Scanopy is a functional daemon-driven system that replaces static network diagrams with a self-updating topological model. The Rust backend is well-structured for discovery and data persistence; the Svelte UI has significant cognitive-load hotspots – three oversized files, a circular import, and a hub module with high blast radius – that should be addressed before onboarding new engineers. Teams that need current, queryable network topology without per-agent deployment will find it practical; teams requiring deep linting hygiene or zero-secrets-commit guarantees will need to address the findings first.