This document describes the architecture of the monocle project: a BGP information toolkit that can be used as both a Rust library, a command-line application, and an HTTP/SSE server.
- Library-first: the core capability lives in the library; the CLI is a thin wrapper.
- Clear separation of concerns:
- persistence and caching in
database/ - domain operations in
lens/ - presentation and UX concerns in the CLI (
bin/)
- persistence and caching in
- Extensible: new functionality should be added as new lenses (and optionally wired into the CLI).
- Composability: lenses should be usable programmatically and in batch/automation contexts.
The codebase follows strict layering rules to maintain separation of concerns:
Repositories are data access only:
- CRUD operations (Create, Read, Update, Delete)
- Query methods that return raw data
- No business logic or policy decisions
- No output formatting
Lenses contain business logic and policy:
- Interpretation of data (e.g., RPKI validation logic)
- Coordination between multiple repositories
- Output formatting
- Cache refresh decisions
CLI commands are thin wrappers:
- Argument parsing
- Output format selection
- Progress display
- Error presentation
Monocle is organized into three primary layers:
- CLI layer (
src/bin/):- parses flags/arguments
- loads configuration
- selects output format
- calls into lenses
- Lens layer (
src/lens/):- provides "use-case" APIs (e.g., search, parse, RPKI lookups)
- controls output shaping via a unified
OutputFormat - uses
database/and external libraries as needed
- Database layer (
src/database/):- manages storage (SQLite), schema initialization, and caching primitives
- contains repositories for specific datasets
src/
βββ lib.rs # Library entry point / exports
βββ config.rs # Configuration and shared status helpers
β
βββ database/ # Persistence + caching
β βββ mod.rs
β βββ README.md
β β
β βββ core/ # Connection + schema
β β βββ mod.rs
β β βββ connection.rs
β β βββ schema.rs
β β
β βββ session/ # Ephemeral / per-run databases
β β βββ mod.rs
β β βββ msg_store.rs
β β
β βββ monocle/ # Main persistent monocle database
β βββ mod.rs
β βββ asinfo.rs # Unified AS information (from bgpkit-commons)
β βββ as2rel.rs # AS relationships
β βββ rpki.rs # ROAs/ASPAs cache (SQLite with blob prefixes)
β βββ pfx2as.rs # Prefix-to-ASN mappings (SQLite with blob prefixes)
β
βββ lens/ # Business logic ("use-cases")
β βββ mod.rs
β βββ README.md
β βββ utils.rs # OutputFormat, formatting helpers
β βββ country.rs # Country code/name lookup
β β
β βββ as2rel/ # AS relationship lens
β β βββ mod.rs
β β βββ args.rs
β β βββ types.rs
β β
β βββ inspect/ # Unified AS/prefix inspection
β β βββ mod.rs # InspectLens implementation
β β βββ types.rs # Result types, section selection
β β
β βββ ip/ # IP information lookup
β β βββ mod.rs
β β
β βββ parse/ # MRT file parsing
β β βββ mod.rs
β β
β βββ pfx2as/ # Prefix-to-ASN mapping types
β β βββ mod.rs # Types only; repository handles lookups
β β
β βββ rpki/ # RPKI validation and data
β β βββ mod.rs # RpkiLens with validation logic
β β βββ commons.rs # bgpkit-commons integration
β β
β βββ search/ # BGP message search
β β βββ mod.rs
β β βββ query_builder.rs
β β
β βββ time/ # Time parsing and formatting
β βββ mod.rs
β
βββ server/ # HTTP/SSE server (requires `server` feature)
β βββ mod.rs # Server state, startup, /health, auth wiring
β βββ http.rs # REST router, API error types, system/info
β βββ search.rs # SSE search streaming handler
β βββ auth.rs # Token auth middleware
β βββ rest/ # REST endpoint handlers
β βββ mod.rs
β βββ time.rs # time/parse
β βββ country.rs # country/lookup
β βββ ip.rs # ip/lookup, ip/public
β βββ rpki.rs # rpki/roa/lookup, rpki/aspa/lookup, rpki/roa/validate
β βββ pfx2as.rs # pfx2as/lookup
β βββ as2rel.rs # as2rel/search, as2rel/relationship, as2rel/refresh
β βββ inspect.rs # inspect/query
β βββ database.rs # database/status, database/refresh, inspect/refresh
β
βββ bin/
βββ monocle.rs # CLI entry point
βββ commands/ # Command handlers (thin wrappers around lenses)
βββ as2rel.rs
βββ config.rs # Config display + update, backup, sources
βββ country.rs
βββ inspect.rs # Unified inspect command (replaces whois, pfx2as)
βββ ip.rs
βββ parse.rs
βββ rpki.rs
βββ search.rs
βββ time.rs
The inspect command and lens consolidate multiple data sources into a single query interface:
- ASInfo: Core AS data from bgpkit-commons (replaces as2org)
- Connectivity: AS2Rel-based upstream/peer/downstream relationships
- RPKI: ROAs and ASPA records
- Pfx2as: Prefix-to-ASN mappings
Features:
- Auto-detects query type (ASN, prefix, IP address, or name)
- Section selection (
--show basic/prefixes/connectivity/rpki/all) - Display limits with
--full,--full-roas,--full-prefixes,--full-connectivity - Auto-refresh of stale data
- Multiple output formats
The RPKI lens (RpkiLens) provides:
- Validation logic (RFC 6811): Valid/Invalid/NotFound states
- Cache management: Uses
RpkiRepositoryfor current data (SQLite with blob prefixes) - Historical queries: Uses bgpkit-commons for date-specific lookups
Layering:
RpkiRepository(database): Raw data access only (CRUD, prefix range queries)RpkiLens(lens): Validation logic, cache refresh, formatting
The Pfx2as repository (Pfx2asRepository) provides:
- Lookup modes: Exact, longest prefix match, covering (supernets), covered (subnets)
- ASN queries: Get all prefixes for an ASN
- SQLite storage: IP prefixes stored as 16-byte start/end address pairs
- Cache management: 24-hour TTL with automatic refresh
Note: The file-based cache has been removed; all pfx2as data now uses SQLite.
The HTTP/SSE server (monocle server) provides programmatic access to monocle functionality:
- Protocol: HTTP REST with JSON request/response bodies
- Streaming: SSE (
text/event-stream) for search with progress, element batches, and terminal events - Cancellation: Client closes HTTP connection; server detects drop via
Arc<AtomicBool> - Backpressure: Bounded mpsc channel (capacity 32); element batches never dropped
- Terminal invariant: Exactly one terminal event (
completed,cancelled, orerror) - Auth: Optional token-based middleware (
Authorization: Bearer <token>) - DB access: Per-request
MonocleDatabaseinspawn_blocking(connection is!Send)
Available endpoint groups:
/health: Health check (always open)/api/v1/system/*: Server introspection/api/v1/search/*: SSE streaming BGP search/api/v1/time/*,/api/v1/ip/*,/api/v1/country/*: Utility lookups/api/v1/rpki/*: RPKI ROA/ASPA lookup and validation/api/v1/as2rel/*: AS relationship queries/api/v1/pfx2as/*: Prefix-to-ASN mapping/api/v1/inspect/*: Unified AS/prefix inspection/api/v1/database/*: Database status and refresh
Responsibilities:
- compute default paths and load config file overrides
- provide shared helpers used by
configCLI command to display:- SQLite database info (size, table counts, last update time)
- cache settings and cache directory info
- database management (refresh, backup, sources)
This module is intentionally "infra-ish": it should not implement domain logic.
The database module handles local persistence and caches shared across commands.
Responsibilities:
- create/configure SQLite connections
- define and initialize schema
- expose schema/version checks (used on open)
Notes:
- schema management is owned here; higher-level modules should not issue
CREATE TABLEetc.
Responsibilities:
- main persistent monocle dataset store (SQLite DB under the monocle data directory)
- repositories for datasets:
- ASInfo (unified AS information from bgpkit-commons)
- AS2Rel (AS-level relationships)
- RPKI (ROAs/ASPAs with blob-based prefix storage)
- Pfx2as (prefix-to-ASN mappings with blob-based prefix storage)
- file cache helpers for auxiliary file-based caching
Key idea:
MonocleDatabaseis the entry point for accessing the persistent DB/repositories.
Responsibilities:
- short-lived, per-operation SQLite storage (e.g., search results)
- optimized for write-heavy temporary usage and easy export
Lenses are the primary public-facing API surface for functionality. A lens:
- takes a
&MonocleDatabasereference for data access - defines argument types (often serde-serializable; optionally clap-derivable under
cli) - defines result types (serde-serializable)
- performs the operation (may call into Broker, Parser, SQLite repositories, file caches, etc.)
- emits output using the unified
OutputFormat
lens/utils.rs contains the global OutputFormat used across the CLI to keep formatting consistent and predictable.
Certain lenses support progress callbacks (e.g., parse/search). Progress types are designed to be:
- thread-safe (
Send + Sync) - serializable (for GUI or other frontends)
The CLI layer wires together:
- clap argument parsing
- config loading
- output selection (
--format,--json) - invocation of lens operations
- printing human-readable messages to stderr and data output to stdout (to support piping)
The CLI should not duplicate core logic. It should:
- validate/normalize CLI inputs
- call library APIs
- format/print results
- User runs
monocle <command> ... - CLI parses args and loads
MonocleConfig - CLI determines
OutputFormat - CLI opens
MonocleDatabaseand constructs the lens - Lens executes operation:
- uses repository for data access
- applies business logic
- returns typed results (and optionally progress events via callback)
- CLI prints results via
OutputFormat
- Application creates (or opens) the
MonocleDatabase - Application constructs lens with database reference
- Application calls lens methods
- Application consumes typed results directly, or uses
OutputFormatto format for display
- Client sends HTTP request (POST with JSON body, or GET)
- Axum router dispatches to handler
- Handler opens
MonocleDatabaseinspawn_blocking(for DB-backed endpoints) - Handler calls lens methods, formats result as JSON response
- For search: handler returns
Ssestream; worker sends events via bounded channel - Client disconnect cancels the search worker via
Arc<AtomicBool>
Monocle supports conditional compilation via Cargo features with a simplified three-tier structure:
cli (default)
βββ server
β βββ lib
βββ lib
Quick Guide:
- Need the CLI binary? Use
cli(includes everything) - Need HTTP/SSE server without CLI? Use
server(includes lib) - Need only library/data access? Use
lib(database + all lenses + display)
| Feature | Description | Key Dependencies |
|---|---|---|
lib |
Complete library: database + all lenses + display | rusqlite, bgpkit-parser, bgpkit-broker, tabled, etc. |
server |
HTTP/SSE server (implies lib) |
axum, tokio, serde_json |
cli |
Full CLI binary with progress bars (implies lib and server) |
clap, indicatif |
Features: lib
Use when building applications that need:
- Database operations (SQLite, data loading)
- All lenses (TimeLens, ParseLens, SearchLens, RPKI, Country, InspectLens, etc.)
- Table formatting with tabled
monocle = { version = "1.1", default-features = false, features = ["lib"] }use monocle::database::MonocleDatabase;
use monocle::lens::inspect::{InspectLens, InspectQueryOptions};
let db = MonocleDatabase::open_in_dir("~/.local/share/monocle")?;
let lens = InspectLens::new(&db);
let result = lens.query("AS13335", &InspectQueryOptions::default())?;Features: server
Use when building applications that need:
- Everything in
lib - HTTP/SSE server for remote API access
monocle = { version = "1.1", default-features = false, features = ["server"] }use monocle::config::MonocleConfig;
use monocle::server::start_server;
let config = MonocleConfig::new(&None)?;
// Start HTTP/SSE server on default port
start_server(config).await?;Features: cli (default)
The full CLI binary with all features, HTTP/SSE server, and terminal UI:
monocle = "1.1"Or explicitly:
monocle = { version = "1.1", features = ["cli"] }All of these combinations compile successfully:
| Combination | Use Case |
|---|---|
| (none) | Config types only, no functionality |
lib |
Full library functionality |
server |
Library + HTTP/SSE server |
cli |
Full CLI (includes everything) |
When you enable a higher-tier feature, lower-tier features are automatically included:
serverβ automatically enableslibcliβ automatically enableslibandserver
README.mdβ user-facing CLI and library overviewCHANGELOG.mdβ version history and breaking changesDEVELOPMENT.mdβ contributor guide for adding lenses and fixing bugssrc/server/README.mdβ HTTP/SSE API specificationsrc/database/README.mdβ database module notessrc/lens/README.mdβ lens module patterns and conventionsexamples/README.mdβ example code organized by feature tier