dextmorgn e3014553a5 fix(frontend): type the graph subsystem's react-force-graph boundary
The single biggest source of `any` in this codebase: react-force-graph
is a loosely-typed library by design (NodeObject/LinkObject both carry
`[others: string]: any` index signatures), and every hook/component
touching the graph ref, node/edge callbacks, or force settings had
absorbed that looseness as `any` instead of narrowing it once at the
boundary. Fixed the boundary, not each site individually — most of
this diff is mechanical once the shared types existed.

New shared types (types/graph.ts):
- GraphViewerRef = ForceGraphMethods<NodeObject<GraphNode>,
  LinkObject<GraphNode, GraphEdge>> | undefined — the one ref type
  every graphRef across 8 files now uses instead of re-guessing
  `React.RefObject<any>` at each site.
- GraphNode gained fx?/fy? — react-force-graph's own NodeObject type
  declares these (pin coordinates set after drag-end and after
  layout), and every consumer that touched them was already doing so
  through `any`; the app's own type just never caught up.

Root-cause fix in index.tsx: explicitly parametrizing
`<ForceGraph2D<GraphNode, GraphEdge>>` (it was rendered with no
generics, defaulting every prop's NodeType/LinkType to `{}`) made
onNodeClick/onNodeRightClick/onLinkClick/onLinkRightClick/
nodeCanvasObject/linkCanvasObject all correctly typed against the
app's real node/edge shapes for free — four `any` params across two
files resolved by one annotation, not four separate patches.

Found and fixed a real TS gotcha this surfaced: GraphEdge declares
source/target as plain required strings, which collides with
LinkObject's own optional `source?: string | number | NodeObject`
when GraphEdge is used as the LinkType generic — the intersection of
a required string and that optional union collapses to `never` once
narrowed with `typeof x === 'object'`, silently breaking any code that
reads `.x`/`.y` off a link's resolved endpoint. Verified in isolation
before touching the real files (see the two `LinkObject<GraphNode,
Omit<GraphEdge, 'source'|'target'>>` sites and their comments). Every
earlier place in this codebase handling this exact duality with hand-
rolled `typeof === 'object' ? x.id : x` guards was working around this
same underlying incompatibility without naming it.

Found and removed real dead code exposed by typing, not introduced by
it: link-renderer.ts's LinkRenderParams declared theme/highlightNodes/
selectedEdges and both call sites dutifully threaded them through, but
renderLink's body never reads any of the three — their information was
already baked into `rc` (RenderContext) before the call. Confirmed by
literal absence from the destructure, not inferred; removed from the
interface and both call sites.

Documented, not silently patched: use-graph-initialization.ts's
getViewportCenter called `graphRef.current.getBoundingClientRect?.()`
— a DOM method ForceGraphMethods doesn't have, so the optional call
was always undefined and the function always returned the {x:0,y:0}
fallback. Feeds "center new item in viewport" (add-item-dialog.tsx),
which has therefore always placed new items at graph-origin, never the
actual visible center. Left the behavior unchanged with the bug
explained inline — fixing it needs the container's DOM rect, which
this hook isn't given, and guessing at a fix here without a way to
verify it against the running app risked a worse, unverifiable
regression.

Also typed through the two hooks/use-layout.ts and
hooks/use-graph-layout.ts (nodes/graphData/forceSettings/
saveAllNodePositions, matching the same real types), and the worker
message boundary in use-layout.ts (a minimal `{id, x?, y?}` type for
what crosses postMessage's structured-clone, since that's genuinely
all that's read off it).

Verified: eslint no-explicit-any 257 -> 202 in one pass, tsc 89
(unchanged from the running baseline — every step diffed against it,
not just "count went down"; two remaining findings are the
established table/data-table.tsx dead code), vitest 15/15, yarn build
clean. Also fixed two no-extra-semi findings in nodes-view.tsx/
relationships-view.tsx that kept reappearing: deleting the leading `;`
alone doesn't stick because prettier's own ASI-safety rule re-inserts
it on every format pass when a statement starts with `(` — restructured
to a local `const` instead of leaving something prettier would keep
fighting.
2026-08-25 09:33:35 +02:00
2026-04-11 13:17:14 +02:00
2025-10-29 08:31:41 +01:00
2025-10-29 08:31:41 +01:00
2025-10-23 11:50:18 +02:00
2026-01-25 11:11:58 +01:00

Flowsint

License Ethical Software Buy Me A Coffee Ko-fi Discord

Flowsint is an open-source OSINT graph exploration tool designed for ethical investigation, transparency, and verification.

Ethics: Please read ETHICS.md for responsible use guidelines.

hero-dark

https://github.com/user-attachments/assets/eaabfa81-d7b3-414d-8cf7-f69b4e37bab6

https://github.com/user-attachments/assets/7457d94a-cf1d-4a97-949f-f9b1d8d92644

https://github.com/user-attachments/assets/65c3f26e-7132-4853-be45-21b8933688bd

Contributing

Flowsint is still in early development and definetly needs the help of the community! Feel free to raise issues, propose features, etc.

Get started

Don't want to read ? Got it. Here's your install instructions:

Linux / macOS

1. Install pre-requisites

  • Docker
  • Make

2. Run install command

git clone https://github.com/reconurge/flowsint.git
cd flowsint
make prod

Windows

No Make needed. Works in both Command Prompt (cmd) and PowerShell.

1. Install pre-requisites

2. Clone and set up environment files

git clone https://github.com/reconurge/flowsint.git
cd flowsint

copy .env.example .env
copy .env.example flowsint-api\.env
copy .env.example flowsint-core\.env
copy .env.example flowsint-app\.env

3. Start

docker compose -f docker-compose.prod.yml up -d

This pulls the pre-built images from GitHub Container Registry — no local build needed.

First login

Then go to http://localhost:5173/register and create an account. There are no credentials or account by default.

✅ OSINT investigations need a high level of privacy. Everything is stored on your machine.

Deploy on a network (team / server)

The same setup works out of the box on a server: the frontend serves the UI and proxies all API calls internally, so no extra configuration is needed for clients.

git clone https://github.com/reconurge/flowsint.git
cd flowsint
cp .env.example .env
# Edit .env — see "Before exposing to a network" below
docker compose -f docker-compose.prod.yml up -d

Anyone on the network can then access Flowsint at http://<server-ip>:5173.

Before exposing to a network, change the default secrets in .env:

  • AUTH_SECRET — signs authentication tokens. Generate one: openssl rand -hex 32
  • MASTER_VAULT_KEY_V1 — encrypts stored API keys. Generate one: python3 -c "import os, base64; print('base64:' + base64.b64encode(os.urandom(32)).decode())"
  • NEO4J_PASSWORD — Neo4j database password.

Also add your server hostname/IP to the Host-header allowlist in flowsint-app/nginx.conf (look for map $http_host $is_flowsint_host). The default allowlist accepts only localhost / 127.0.0.1 / [::1], which defends single-user installs against DNS rebinding; LAN and public deploys must opt-in their own hostname. Two commented-out template lines in the same map block show the format.

Only port 5173 is exposed to the network. PostgreSQL, Redis, Neo4j and the API are bound to 127.0.0.1 on the server and reachable only through the frontend proxy.

To pin a specific version instead of latest, set FLOWSINT_VERSION in .env (e.g. FLOWSINT_VERSION=1.2.10).

HTTPS (recommended beyond a trusted LAN): put any reverse proxy in front of port 5173. Example with Caddy:

flowsint.example.com {
    reverse_proxy 127.0.0.1:5173
}

When fronting with a reverse proxy, also bind the app port to localhost in docker-compose.prod.yml ("127.0.0.1:5173:8080") so clients can only go through HTTPS.

What is it?

Flowsint is a graph-based investigation tool focused on reconnaissance and OSINT (Open Source Intelligence). It allows you to explore relationships between entities through a visual graph interface and automated enrichers.

Available Enrichers

Domain Enrichers

  • Reverse DNS Resolution - Find domains pointing to an IP
  • DNS Resolution - Resolve domain to IP addresses
  • Subdomain Discovery - Enumerate subdomains
  • WHOIS Lookup - Get domain registration information
  • Domain to Website - Convert domain to website entity
  • Domain to Root Domain - Extract root domain
  • Domain to ASN - Find ASN associated with domain
  • Domain History - Retrieve historical domain data

IP Enrichers

  • IP Information - Get geolocation and network details
  • IP to ASN - Find ASN for IP address

ASN Enrichers

  • ASN to CIDRs - Get IP ranges for an ASN

CIDR Enrichers

  • CIDR to IPs - Enumerate IPs in a range

Social Media Enrichers

  • Maigret - Username search across social platforms

Organization Enrichers

  • Organization to ASN - Find ASNs owned by organization
  • Organization Information - Get company details
  • Organization to Domains - Find domains owned by organization

Cryptocurrency Enrichers

  • Wallet to Transactions - Get transaction history
  • Wallet to NFTs - Find NFTs owned by wallet

Website Enrichers

  • Website Crawler - Crawl and map website structure
  • Website to Links - Extract all links
  • Website to Domain - Extract domain from URL
  • Website to Webtrackers - Identify tracking scripts
  • Website to Text - Extract text content

Email Enrichers

  • Email to Gravatar - Find Gravatar profile
  • Email to Breaches - Check data breach databases
  • Email to Domains - Find associated domains

Phone Enrichers

  • Phone to Breaches - Check phone number in breaches

Individual Enrichers

  • Individual to Organization - Find organizational affiliations
  • Individual to Domains - Find domains associated with person

Integration Enrichers

  • N8n Connector - Connect to N8n workflows

Project structure

The project is organized into autonomous modules:

Core modules

  • flowsint-core: Core utilities, orchestrator, vault, celery tasks, and base classes
  • flowsint-types: Pydantic models and type definitions
  • flowsint-enrichers: Enricher modules, scanning logic, and tools
  • flowsint-api: FastAPI server, API routes, and schemas only
  • flowsint-app: Frontend application

Module dependencies

flowsint-app (frontend)
    ↓
flowsint-api (API server)
    ↓
flowsint-core (orchestrator, tasks, vault)
    ↓
flowsint-enrichers (enrichers & tools)
    ↓
flowsint-types (types)

Development setup

Prerequisites

  • Docker

Run

Linux / macOS (requires Make):

make dev

Windows (cmd or PowerShell, no Make — create the .env files first, see Get started):

docker compose -f docker-compose.dev.yml up -d --build
docker compose -f docker-compose.dev.yml logs -f

Development

The app is accessible at http://localhost:5173.

Module details

flowsint-core

Core utilities and base classes used by all other modules:

  • Database connections (PostgreSQL, Neo4j)
  • Authentication and authorization
  • Logging and event handling
  • Configuration management
  • Base classes for enrichers and tools
  • Utility functions

flowsint-types

Pydantic models for all data types:

  • Domain, IP, ASN, CIDR
  • Individual, Organization, Email, Phone
  • Website, Social profiles, Credentials
  • Crypto wallets, Transactions, NFTs
  • And many more...

flowsint-enrichers

Enricher modules that process data:

  • Domain enrichers (subdomains, WHOIS, resolution)
  • IP enrichers (geolocation, ASN lookup)
  • Social media enrichers (Maigret, Sherlock)
  • Email enrichers (breaches, Gravatar)
  • Crypto enrichers (transactions, NFTs)
  • And many more...

flowsint-api

FastAPI server providing:

  • REST API endpoints
  • Authentication and user management
  • Graph database integration
  • Real-time event streaming

flowsint-app

Frontend application.

  • Modern and UI friendly interface
  • Built for performance (no lag even on thousands of nodes)

Development workflow

  1. Adding new types: Add to flowsint-types module
  2. Adding new enrichers: Add to flowsint-enrichers module
  3. Adding new API endpoints: Add to flowsint-api module
  4. Adding new utilities: Add to flowsint-core module

Testing

Each module has its own (incomplete) test suite:

# Test core module
cd flowsint-core
uv run pytest

# Test types module
cd ../flowsint-types
uv run pytest

# Test enrichers module
cd ../flowsint-enrichers
uv run pytest

# Test API module
cd ../flowsint-api
uv run pytest

Contributing

  1. Follow the modular structure
  2. Use Poetry for dependency management
  3. Write tests for new functionality
  4. Update documentation as needed

Ethics: Please read ETHICS.md for responsible use guidelines.

Flowsint is designed strictly for lawful, ethical investigation and research purposes.

It was created to assist:

  • Cybersecurity researchers and analysts
  • Journalists and OSINT investigators
  • Law enforcement or fraud investigation teams
  • Organizations conducting internal threat intelligence or digital risk analysis

Flowsint must not be used for:

  • Unauthorized intrusion, surveillance, or data collection
  • Harassment, doxxing, or targeting of individuals
  • Political manipulation, misinformation, or violation of privacy laws

Any misuse of this software is strictly prohibited and goes against the ethical principles defined in ETHICS.md.

❤️ Support

Buy Me A Coffee Ko-fi

S
Description
No description provided
Readme Apache-2.0
67 MiB
Latest
2026-08-26 02:25:31 -05:00
Languages
TypeScript 52.8%
Python 44.8%
CSS 1.2%
JavaScript 0.5%
Makefile 0.3%
Other 0.3%