Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

μNet Documentation

Welcome to μNet - A modern network configuration management system for documenting topology, monitoring compliance, and automating operations.


🚀 New to μNet?

→ Quick Start Guide - Get μNet running in 10 minutes

→ What is μNet? - Learn about features and use cases


📖 User Guides

Choose your path based on how you'll use μNet:

For Network Operators

For Developers & Integrators

For Project Planning

  • Roadmap - Current features and future plans

🎯 Common Tasks

Just getting started?Quick Start GuideCLI Reference

Setting up compliance monitoring?Policy GuideTroubleshooting

Building integrations?API ReferenceArchitecture

Having issues?TroubleshootingCLI Reference


📋 Examples & Resources


💬 Getting Help

Found a bug or need a feature?
Open an issue on GitHub

Questions about usage?
Check Troubleshooting or browse the complete documentation

Want to contribute?
See the Architecture Guide and GitHub repository


μNet v0.1.0 - Built with ❤️ in Rust

📖 Full documentation: https://unet.bedecarroll.com

Introduction to μNet

μNet (pronounced "micro-net") is a network configuration management system that helps you document, monitor, and automate your network infrastructure.


What Problems Does μNet Solve?

📋 Network Documentation Chaos

  • Problem: Network topology scattered across spreadsheets, diagrams, and tribal knowledge
  • Solution: Centralized device inventory with relationships, locations, and lifecycle tracking

🔍 Configuration Drift

  • Problem: Devices gradually drift from standards without detection
  • Solution: Declarative policies that continuously check compliance

🔧 Manual Operations

  • Problem: Repetitive configuration tasks prone to human error
  • Solution: Automated actions triggered by policy rules

📊 Lack of Visibility

  • Problem: Limited insight into device status and performance
  • Solution: Real-time SNMP monitoring with historical tracking

Core Concepts

Devices & Topology

μNet models your network as Nodes (devices), Links (connections), and Locations (physical sites):

Campus
├── Building A
│   ├── Floor 1
│   │   └── Rack 1
│   │       ├── core-01 (Core Router)
│   │       └── dist-01 (Distribution Switch)
│   └── Floor 2
└── Building B

Policy-Driven Compliance

Define network standards as declarative rules:

# Ensure production devices are monitored
WHEN node.lifecycle == "Production" 
THEN SET custom_data.monitoring_enabled TO true

# Cisco devices should use SNMPv3
WHEN node.vendor == "Cisco"
THEN ASSERT custom_data.snmp_version == "v3"

Real-Time Monitoring

μNet polls your devices via SNMP to collect:

  • System information (uptime, description, contact)
  • Interface status and statistics
  • Performance metrics (CPU, memory, temperature)
  • Custom vendor-specific data

Key Features

What μNet Does Today (v0.1.0)

  • Complete Device Management: Add, update, and organize network devices
  • Topology Mapping: Document connections and physical locations
  • Policy Engine: Write and evaluate compliance rules
  • SNMP Monitoring: Real-time device status collection
  • REST API: Full HTTP API for automation
  • Rich CLI: Command-line interface with multiple output formats
  • Data Import/Export: Bulk operations for network data

🚧 In Development

  • Background SNMP Integration: Automatic device polling and database updates
  • API Completeness: Full implementation of location/link endpoints
  • Derived State Tracking: Historical device status and metrics

🔮 Future Planned Features

  • Configuration Templates: Generate device configs from templates (NOT STARTED)
  • Historical Analytics: Time-series data and trend analysis (NOT STARTED)
  • Configuration Push: Deploy generated configs to devices (NOT STARTED)
  • Advanced Alerting: Notifications for policy violations (NOT STARTED)

Architecture Overview

μNet consists of three main components:

┌─────────────┐    HTTP/JSON    ┌─────────────┐
│  unet-cli   │ ◄──────────────► │ unet-server │
│             │                 │             │
│ • Commands  │                 │ • REST API  │
│ • Local DB  │                 │ • SNMP Poll │
│ • Policies  │                 │ • Policies  │
└─────────────┘                 └─────────────┘
       │                               │
       ▼                               ▼
┌─────────────────────────────────────────────┐
│              SQLite Database                │
│ • Devices  • Links  • Locations • Status   │
└─────────────────────────────────────────────┘

Design Principles:

  • Single Binary: No external dependencies, easy deployment
  • SQLite Backend: Zero-ops database for up to 10K+ devices
  • API-First: Everything available via HTTP API
  • Incremental Adoption: Start small, grow capabilities over time

Use Cases

Network Documentation

  • Device Inventory: Comprehensive database of all network equipment
  • Topology Mapping: Visual representation of network connections
  • Lifecycle Tracking: Manage devices from planning to decommission
  • Change Auditing: Track modifications and policy compliance

Compliance Monitoring

  • Security Standards: Ensure devices meet security baselines
  • Configuration Validation: Check for required settings and features
  • Vendor Consistency: Enforce consistent configurations by vendor
  • Lifecycle Policies: Different rules for production vs. staging

Operational Automation

  • Bulk Updates: Apply changes across multiple devices
  • Automated Validation: Continuous compliance checking
  • Integration Workflows: Connect with existing automation tools
  • Reporting: Generate compliance and inventory reports

Getting Started

Ready to try μNet?

  1. Quick Start Guide - Get running in 10 minutes
  2. CLI Reference - Learn the commands
  3. Policy Guide - Write your first compliance rules

Questions? Check the Troubleshooting Guide or open an issue.


Why Choose μNet?

Built for Network Engineers

  • Domain-specific: Designed for network operations, not generic IT
  • Practical: Solves real daily challenges network teams face
  • Flexible: Adapt to your existing processes and tools

Modern Technology

  • Rust Performance: Fast, memory-safe, reliable
  • Simple Deployment: Single binary, SQLite database
  • API-First: Easy integration with existing tools

Open Source

  • MIT/Apache License: Use freely in commercial environments
  • Active Development: Regular releases with new features
  • Community Driven: Contributions and feedback welcome

Next: Quick Start Guide

Quick Start Guide – Getting Started with μNet

Goal: Get μNet running and managing your first network devices in 10 minutes


Installation

Build from Source

Note: μNet is currently in active development. Pre-built releases are not yet available. You must build from source.

git clone https://github.com/bedecarroll/unet.git
cd unet
cargo build --release
cp target/release/unet-cli ./unet
cp target/release/unet-server ./unet-server

Quick Setup

1. Initialize Database

μNet will automatically create a SQLite database on first use:

./unet nodes list
# Creates unet.db in current directory

Managing Vendors

Common vendors are seeded automatically. Manage them using the CLI:

# List vendors
unet vendors list

# Add a vendor
unet vendors add CustomVendor

# Remove a vendor
unet vendors delete CustomVendor

2. Create Sample Data

Note: Pre-built example files are not yet available. You can create sample data manually:

# Create a location
./unet locations create --name "Datacenter" --type "datacenter" --description "Main datacenter"

# Create a node
./unet nodes create --name "core-01" --type "Router" --vendor "Cisco" --model "ISR4321" --location "Datacenter"

# List your data
./unet nodes list
./unet locations list

Basic Operations

Managing Nodes

# Add a new device
./unet nodes add \
  --name core-sw-01 \
  --domain corp.example.com \
  --vendor cisco \
  --model catalyst9300 \
  --role access \
  --lifecycle production \
  --management-ip 192.168.1.10

# List all devices
./unet nodes list

# Show device details
./unet nodes show core-sw-01

# Update device
./unet nodes update core-sw-01 --lifecycle production

# Delete device
./unet nodes delete core-sw-01

Managing Locations

# Add a location
./unet locations add \
  --name "Building A" \
  --location-type building \
  --address "123 Main Street"

# List locations
./unet locations list

# Show location details
./unet locations show "Building A"
# Create a point-to-point link
./unet links add \
  --node-a core-sw-01 \
  --interface-a GigE0/0/1 \
  --node-z dist-sw-01 \
  --interface-z GigE1/0/24 \
  --bandwidth 1000000000

# Create an internet circuit
./unet links add \
  --node-a edge-rtr-01 \
  --interface-a GigE0/0/0 \
  --circuit-id "ISP-CIRCUIT-12345"

# List links
./unet links list

Working with Policies

1. Create Your First Policy

Create a file called network-standards.rules:

# Ensure all production devices are monitored
WHEN node.lifecycle == "Production" 
THEN SET custom_data.monitoring_enabled TO true

# Cisco devices should use SNMPv3
WHEN node.vendor == "Cisco"
THEN SET custom_data.snmp_version TO "v3"

# Core devices need redundancy
WHEN node.role == "Core"
THEN ASSERT custom_data.redundancy_configured IS true

2. Validate and Run Policies

# Check syntax
./unet policy validate network-standards.rules

# Evaluate against all nodes
./unet policy eval network-standards.rules

# Show only failures
./unet policy eval network-standards.rules --failures-only

Using the HTTP Server

1. Start the Server

# Start server on default port (8080)
./unet-server

# Or specify custom settings
./unet-server --host 0.0.0.0 --port 8080 --database-url sqlite://network.db

2. Use CLI with Remote Server

# Set server URL
export UNET_SERVER=http://localhost:8080

# Now CLI commands use the server
./unet nodes list
./unet policy eval network-standards.rules

3. Use the API Directly

# List nodes via API
curl http://localhost:8080/api/v1/nodes

# Create a node via API
curl -X POST http://localhost:8080/api/v1/nodes \
  -H "Content-Type: application/json" \
  -d '{
    "name": "new-device",
    "vendor": "Cisco",
    "model": "ISR4331",
    "role": "Edge",
    "lifecycle": "Staging"
  }'

# Evaluate policies via API
curl -X POST http://localhost:8080/api/v1/policies/evaluate

Output Formats

μNet supports multiple output formats for different use cases:

# Human-readable table (default for terminal)
./unet nodes list

# JSON for automation
./unet nodes list --output json

# YAML for readability
./unet nodes list --output yaml

# Pipe to other tools
./unet nodes list --output json | jq '.data.data[].name'

Common Workflows

Network Discovery Documentation

# 1. Document your physical sites
./unet locations add --name "HQ Campus" --location-type campus
./unet locations add --name "Main Building" --location-type building --parent-id <campus-id>

# 2. Add your network devices
./unet nodes add --name core-01 --vendor cisco --model asr9000 --role core
./unet nodes add --name dist-01 --vendor cisco --model catalyst9400 --role distribution

# 3. Document connections
./unet links add --node-a core-01 --interface-a TenGigE0/0/0/1 \
                 --node-z dist-01 --interface-z TenGigE1/0/1

# 4. Export for backup
./unet export --output-dir backup/

Compliance Monitoring

# 1. Create compliance policies
cat > compliance.rules << 'EOF'
WHEN node.lifecycle == "Production" THEN ASSERT custom_data.backup_configured IS true
WHEN node.role == "Core" THEN ASSERT custom_data.redundancy_level >= 2
WHEN node.vendor == "Cisco" THEN ASSERT custom_data.snmp_version == "v3"
EOF

# 2. Run compliance check
./unet policy eval compliance.rules --failures-only

# 3. Generate compliance report
./unet policy eval compliance.rules --output json > compliance-report.json

Data Migration

# Export from existing system
./unet export --output-dir migration/

# Edit exported files as needed
# ...

# Import to new environment
./unet import migration/ --dry-run  # Test first
./unet import migration/              # Actually import

Configuration

Environment Variables

# Database location
export UNET_DATABASE_URL="sqlite:///path/to/unet.db"

# Server URL for remote operations
export UNET_SERVER="http://unet-server:8080"

# Default output format
export UNET_OUTPUT_FORMAT="json"

Configuration File

Create ~/.config/unet/config.toml:

[defaults]
database_url = "sqlite:///home/user/network/unet.db"
server_url = "http://unet-server:8080"
output_format = "table"

[logging]
level = "info"

Next Steps

Now that you have μNet running:

  1. Read the CLI Reference for complete command documentation
  2. Study the Policy Guide for advanced policy authoring
  3. Explore the API Reference for automation integration
  4. Review the Architecture Overview to understand the system design

Common Next Actions

  • Scale Up: Import your real network topology
  • Automate: Integrate with your CI/CD pipeline
  • Monitor: Set up continuous policy evaluation
  • Extend: Use the API to build custom integrations

Getting Help

Welcome to μNet! 🎉

Troubleshooting Guide – Common Issues and Solutions

Audience: Users experiencing problems with μNet
Status: Covers current implementation (v0.1.0)


Common CLI Issues

Command Not Found

Problem: unet: command not found

Solutions:

# 1. Check if binary exists and is executable
ls -la unet
chmod +x unet

# 2. Use full path
./unet nodes list

# 3. Add to PATH
export PATH=$PATH:$(pwd)
# Or move to system path
sudo mv unet /usr/local/bin/

Database Connection Errors

Problem: Failed to connect to database or Database locked

Solutions:

# 1. Check database file permissions
ls -la unet.db
chmod 644 unet.db

# 2. Ensure directory is writable
ls -la .
# Directory should be writable by current user

# 3. Try different database location
unet --database-url sqlite:///tmp/test.db nodes list

# 4. Check for zombie processes
ps aux | grep unet
# Kill any stuck processes: kill <pid>

Validation Errors

Problem: Invalid input or Validation failed

Solutions:

# 1. Check required fields
unet nodes add --help

# 2. Verify enum values
# Vendor: Cisco, Juniper, Arista, HPE, Dell, etc.
# Role: Core, Distribution, Access, Edge, etc.
# Lifecycle: Planning, Staging, Production, etc.

# 3. Check IP address format
unet nodes add --name test --vendor cisco --model test \
  --role access --lifecycle staging \
  --management-ip 192.168.1.1  # Valid IP format

# 4. Validate UUID format for location-id
unet locations list  # Get valid UUID

Server Issues

Server Won't Start

Problem: Server fails to start or crashes immediately

Solutions:

# 1. Check port availability
netstat -an | grep 8080
# Or try different port
unet-server --port 8081

# 2. Check database access
ls -la unet.db
# Ensure server has read/write access

# 3. Verbose logging
unet-server --log-level debug

# 4. Check disk space
df -h .
# Ensure adequate space for database

Server Connection Refused

Problem: Connection refused when accessing API

Solutions:

# 1. Verify server is running
ps aux | grep unet-server

# 2. Check server logs
unet-server --log-level info

# 3. Test local connection
curl http://localhost:8080/health

# 4. Check firewall rules
# For systemd/firewalld:
sudo firewall-cmd --add-port=8080/tcp

# 5. Bind to all interfaces if needed
unet-server --host 0.0.0.0 --port 8080

API Errors

Problem: HTTP 500 errors or unexpected API responses

Solutions:

# 1. Check server logs
unet-server --log-level debug

# 2. Validate request format
curl -X POST http://localhost:8080/api/v1/nodes \
  -H "Content-Type: application/json" \
  -d '{"name":"test","vendor":"Cisco","model":"test","role":"Access","lifecycle":"Staging"}'

# 3. Check database state
sqlite3 unet.db ".tables"
sqlite3 unet.db "SELECT COUNT(*) FROM nodes;"

# 4. Restart server
pkill unet-server
unet-server

Policy Issues

Policy Syntax Errors

Problem: Policy validation failed or Parse error

Solutions:

# 1. Check basic syntax
cat > test.rules << 'EOF'
WHEN node.vendor == "Cisco" THEN SET custom_data.test TO true
EOF

unet policy validate test.rules

# 2. Common syntax fixes:
# - Use quotes around strings: "Cisco" not Cisco
# - Include THEN keyword: WHEN ... THEN ...
# - Check field names: node.vendor not node.brand

# 3. Use verbose validation
unet policy validate policies/ --verbose

# 4. Test with simple policy first
echo 'WHEN true THEN SET custom_data.test TO true' > simple.rules
unet policy validate simple.rules

Policy Evaluation Failures

Problem: Policies don't trigger or produce unexpected results

Solutions:

# 1. Check if nodes exist
unet nodes list

# 2. Verify field values
unet nodes show node-name --output json | jq '.data.vendor'

# 3. Test with verbose output
unet policy eval policies/ --verbose

# 4. Test specific node
unet policy eval policies/ --node specific-node-name

# 5. Check custom_data structure
unet nodes show node-name --output json | jq '.data.custom_data'

Policy Results Not Stored

Problem: Policy evaluation runs but results aren't saved

Solutions:

# 1. Check API endpoint
curl -X POST http://localhost:8080/api/v1/policies/evaluate \
  -H "Content-Type: application/json" \
  -d '{"store_results": true, "policies": [...]}'

# 2. Verify database tables
sqlite3 unet.db ".schema policy_results"

# 3. Check server permissions
ls -la unet.db
# Server needs write access

Data Issues

Import Failures

Problem: Import failed or partial imports

Solutions:

# 1. Validate JSON format
cat nodes.json | jq .
# Should show pretty-printed JSON without errors

# 2. Check required fields
cat > minimal-node.json << 'EOF'
{
  "name": "test-node",
  "vendor": "Cisco", 
  "model": "test",
  "role": "Access",
  "lifecycle": "Staging"
}
EOF

unet import minimal-node.json

# 3. Use dry-run to check
unet import data/ --dry-run

# 4. Continue on errors
unet import data/ --continue-on-error

# 5. Import in dependency order
unet import locations.json
unet import nodes.json  
unet import links.json

Export Issues

Problem: Export produces empty files or fails

Solutions:

# 1. Check data exists
unet nodes list
unet locations list

# 2. Ensure output directory exists
mkdir -p exports/
unet export --output-dir exports/

# 3. Check permissions
ls -la exports/
# Directory should be writable

# 4. Try different format
unet export --output-dir exports/ --format yaml

# 5. Export specific types
unet export --output-dir exports/ --only nodes

Performance Issues

Slow CLI Commands

Problem: Commands take a long time to execute

Solutions:

# 1. Check database size
ls -lh unet.db

# 2. Use pagination for large datasets  
unet nodes list --page 1 --per-page 20

# 3. Add indexes (for large datasets)
sqlite3 unet.db "CREATE INDEX idx_nodes_vendor ON nodes(vendor);"

# 4. Manually create vendor records
unet vendors add ExampleCorp
unet vendors delete ExampleCorp

# 5. Use specific filters
unet nodes list --vendor cisco --role core

# 6. Consider using server mode
unet-server &
export UNET_SERVER=http://localhost:8080
unet nodes list  # Now uses HTTP API

Memory Usage Issues

Problem: High memory usage or out-of-memory errors

Solutions:

# 1. Monitor memory usage
ps aux | grep unet | awk '{print $6}' # RSS memory in KB

# 2. Use pagination
unet nodes list --per-page 50

# 3. Limit data returned
unet nodes list --output json | jq '.data.data | length'

# 4. Process in batches
for page in {1..10}; do
  unet nodes list --page $page --per-page 100 --output json
done

Network/SNMP Issues

SNMP Polling Failures

Problem: Node status shows as unreachable or no SNMP data

Solutions:

# 1. Check node has management IP
unet nodes show node-name | grep management_ip

# 2. Test SNMP connectivity manually
snmpget -v2c -c public 192.168.1.1 1.3.6.1.2.1.1.1.0

# 3. Check server logs for SNMP errors
unet-server --log-level debug | grep -i snmp

# 4. Verify SNMP configuration on device
# Ensure device has SNMP enabled with proper community/credentials

# 5. Check network connectivity
ping 192.168.1.1
telnet 192.168.1.1 161  # SNMP port

Missing Derived State

Problem: Node status or interface data is empty

Solutions:

# 1. Check if SNMP polling is enabled
curl http://localhost:8080/api/v1/nodes/node-id/status

# 2. Verify management IP is set
unet nodes update node-name --management-ip 192.168.1.1

# 3. Check SNMP credentials (when implemented)
# Currently uses default community "public"

# 4. Monitor polling in server logs
unet-server --log-level debug | grep -i "snmp\|polling"

# 5. Check device SNMP configuration
# Ensure device responds to SNMP queries

Development Issues

Build Failures

Problem: cargo build fails

Solutions:

# 1. Update Rust toolchain
rustup update
rustc --version  # Should be 1.85+

# 2. Clean build cache
cargo clean
cargo build --release

# 3. Check dependencies
cargo check --workspace

# 4. Update dependencies
cargo update

# 5. Check specific feature flags
cargo build --no-default-features

Test Failures

Problem: cargo test fails

Solutions:

# 1. Run specific test
cargo test test_name

# 2. Run with output
cargo test -- --nocapture

# 3. Test specific package
cargo test -p unet-core

# 4. Clean test databases
rm -f test_*.db

# 5. Check for port conflicts
# Tests may use random ports, conflicts are rare

Configuration Issues

Environment Variables Not Working

Problem: Environment variables ignored

Solutions:

# 1. Check variable names
echo $UNET_DATABASE_URL
echo $UNET_SERVER

# 2. Export variables properly
export UNET_DATABASE_URL="sqlite:///path/to/db"

# 3. Use command line flags instead
unet --database-url sqlite:///path/to/db nodes list

# 4. Check precedence order
# CLI flags > Environment variables > Config file > Defaults

Config File Issues

Problem: Configuration file not loaded

Solutions:

# 1. Check file location
ls -la ~/.config/unet/config.toml
ls -la ./config.toml

# 2. Validate TOML syntax
cat config.toml | toml verify  # If you have toml CLI tool

# 3. Use explicit config path
unet --config /path/to/config.toml nodes list

# 4. Check file permissions
chmod 644 config.toml

Log Analysis

Enable Debug Logging

# CLI
unet --verbose nodes list

# Server
unet-server --log-level debug

# Via environment
export UNET_LOG_LEVEL=debug

Common Log Patterns

# Database issues
grep -i "database\|sqlite\|sea_orm" unet.log

# SNMP issues  
grep -i "snmp\|poll" unet.log

# Policy issues
grep -i "policy\|eval" unet.log

# HTTP issues
grep -i "http\|api\|request" unet.log

Getting More Help

Diagnostic Information

When reporting issues, include:

# 1. Version information
unet --version
unet-server --version

# 2. System information
uname -a
rustc --version

# 3. Database information
ls -la unet.db
sqlite3 unet.db ".schema" | head -20

# 4. Sample data
unet nodes list --output json | head -50

# 5. Error logs
unet --verbose nodes list 2>&1 | tail -50

Minimal Reproduction

Create minimal test case:

# 1. Fresh database
rm -f test.db
unet --database-url sqlite://test.db nodes list

# 2. Minimal data
echo '{"name":"test","vendor":"Cisco","model":"test","role":"Access","lifecycle":"Staging"}' > test-node.json
unet --database-url sqlite://test.db import test-node.json

# 3. Reproduce issue
unet --database-url sqlite://test.db nodes show test

Community Support

Self-Help Resources

  1. CLI Help: unet --help, unet nodes --help
  2. API Documentation: API Reference
  3. Policy Guide: Policy Guide
  4. Architecture: Architecture Overview

CLI Reference – μNet Command Line Tool

Audience: Users and operators working with μNet daily
Status: Documents implemented commands only (v0.1.0)


Overview

μNet provides a comprehensive command-line interface for network configuration management. The CLI supports local SQLite and remote (HTTP API) operation modes.

Binary Name: unet
Current Version: 0.1.0
Source: crates/unet-cli/

Quick Start

# Local SQLite mode (default)
unet nodes list

# Remote server mode
unet --server http://localhost:8080 nodes list

# Import sample data (create your own JSON files)
unet import your-locations.json
unet import your-nodes.json
unet import your-links.json

Global Options

OptionEnvironment VariableDefaultDescription
-c, --config <FILE>UNET_CONFIG-Configuration file path
-d, --database-url <URL>UNET_DATABASE_URLsqlite://unet.dbDatabase connection URL
-s, --server <URL>UNET_SERVER-Server URL for remote operations
-t, --token <TOKEN>UNET_TOKEN-Authentication token
-f, --output <FORMAT>-tableOutput format: table, json, yaml
-v, --verbose--Enable verbose logging

Commands

Node Management

unet nodes add

Create a new network device.

unet nodes add --name router-01 --domain example.com --vendor cisco --model ISR4431 --role router --lifecycle live

Required Options:

  • --name <NAME> - Device hostname
  • --domain <DOMAIN> - DNS domain
  • --vendor <VENDOR> - Device vendor (cisco, juniper, arista, fortinet, paloalto, checkpoint, other)
  • --model <MODEL> - Device model
  • --role <ROLE> - Device role (router, switch, firewall, load-balancer, wireless-controller, other)
  • --lifecycle <STATE> - Lifecycle state (planned, implementing, live, decommissioned)

Optional Options:

  • --management-ip <IP> - Management IP address
  • --location-id <UUID> - Location UUID
  • --custom-data <JSON> - Additional data as JSON string

unet nodes list

List all nodes with optional filtering.

unet nodes list
unet nodes list --vendor cisco --role router
unet nodes list --lifecycle live --page 1 --per-page 20

Options:

  • --vendor <VENDOR> - Filter by vendor
  • --role <ROLE> - Filter by role
  • --lifecycle <STATE> - Filter by lifecycle
  • --page <NUM> - Page number (default: 1)
  • --per-page <NUM> - Items per page (default: 50)

unet nodes show

Display detailed information about a specific node.

unet nodes show router-01
unet nodes show --include-status --show-interfaces router-01

Arguments:

  • <NODE_ID> - Node name or UUID

Options:

  • --include-status - Include node status from SNMP polling
  • --show-interfaces - Show interface status
  • --show-system-info - Show system information

unet nodes update

Update node properties.

unet nodes update router-01 --model ISR4451 --lifecycle live
unet nodes update router-01 --management-ip 192.168.1.1

Arguments:

  • <NODE_ID> - Node name or UUID

Options:

  • --name <NAME> - Update hostname
  • --domain <DOMAIN> - Update domain
  • --vendor <VENDOR> - Update vendor
  • --model <MODEL> - Update model
  • --role <ROLE> - Update role
  • --lifecycle <STATE> - Update lifecycle
  • --management-ip <IP> - Update management IP
  • --location-id <UUID> - Update location
  • --custom-data <JSON> - Update custom data

unet nodes delete

Remove a node from the system.

unet nodes delete router-01
unet nodes delete router-01 --yes  # Skip confirmation

Arguments:

  • <NODE_ID> - Node name or UUID

Options:

  • --yes - Skip confirmation prompt

unet nodes status

Show current status information for a node.

unet nodes status router-01
unet nodes status router-01 --show-interfaces --show-system-info

Arguments:

  • <NODE_ID> - Node name or UUID

Options:

  • --show-interfaces - Include interface status
  • --show-system-info - Include system information

unet nodes metrics

Display current metrics for a node.

unet nodes metrics router-01

Arguments:

  • <NODE_ID> - Node name or UUID

Note: Historical metrics are not yet implemented.


Location Management

unet locations add

Create a new location.

unet locations add --name "Building A" --location-type building --address "123 Main St"

Required Options:

  • --name <NAME> - Location name
  • --location-type <TYPE> - Type: campus, building, floor, room, rack

Optional Options:

  • --parent-id <UUID> - Parent location UUID
  • --address <ADDRESS> - Physical address
  • --custom-data <JSON> - Additional data as JSON

unet locations list

List all locations.

unet locations list
unet locations list --location-type building

Options:

  • --location-type <TYPE> - Filter by location type
  • --page <NUM> - Page number
  • --per-page <NUM> - Items per page

unet locations show

Display detailed location information.

unet locations show "Building A"

Arguments:

  • <LOCATION_ID> - Location name or UUID

unet locations update

Update location properties.

unet locations update "Building A" --address "456 New St"

Arguments:

  • <LOCATION_ID> - Location name or UUID

Options:

  • --name <NAME> - Update name
  • --location-type <TYPE> - Update type
  • --parent-id <UUID> - Update parent
  • --address <ADDRESS> - Update address
  • --custom-data <JSON> - Update custom data

unet locations delete

Remove a location.

unet locations delete "Building A"

Arguments:

  • <LOCATION_ID> - Location name or UUID

Options:

  • --yes - Skip confirmation prompt

Create a connection between nodes.

# Point-to-point link
unet links add --node-a router-01 --interface-a GigE0/0/0 --node-z switch-01 --interface-z GigE1/0/1

# Internet circuit (no node-z)
unet links add --node-a router-01 --interface-a GigE0/0/1 --circuit-id "ISP-12345"

Required Options:

  • --node-a <NODE> - First node name/UUID
  • --interface-a <INTERFACE> - Interface on first node

For Point-to-Point Links:

  • --node-z <NODE> - Second node name/UUID
  • --interface-z <INTERFACE> - Interface on second node

For Internet Circuits:

  • --circuit-id <ID> - Circuit identifier

Optional Options:

  • --bandwidth <BPS> - Link bandwidth in bits per second
  • --custom-data <JSON> - Additional data as JSON

List all links.

unet links list
unet links list --node-a router-01

Options:

  • --node-a <NODE> - Filter by first node
  • --node-z <NODE> - Filter by second node
  • --page <NUM> - Page number
  • --per-page <NUM> - Items per page

Display detailed link information.

unet links show <LINK_UUID>

Arguments:

  • <LINK_ID> - Link UUID

Update link properties.

unet links update <LINK_UUID> --bandwidth 10000000000

Arguments:

  • <LINK_ID> - Link UUID

Options:

  • --bandwidth <BPS> - Update bandwidth
  • --custom-data <JSON> - Update custom data

Remove a link.

unet links delete <LINK_UUID>

Arguments:

  • <LINK_ID> - Link UUID

Options:

  • --yes - Skip confirmation prompt

Policy Management

unet policy validate

Validate policy file syntax.

unet policy validate policies/compliance.rules
unet policy validate policies/ --verbose

Arguments:

  • <PATH> - Policy file or directory path

Options:

  • --verbose - Show detailed rule information

unet policy eval

Evaluate policies against nodes.

unet policy eval policies/compliance.rules
unet policy eval policies/ --verbose --failures-only

Arguments:

  • <PATH> - Policy file or directory path

Options:

  • --verbose - Show detailed evaluation results
  • --failures-only - Only show policy failures
  • --node <NODE> - Evaluate against specific node

unet policy list

List available policy files.

unet policy list policies/

Arguments:

  • <DIRECTORY> - Policy directory path

unet policy show

Display policy file contents and parsed rules.

unet policy show policies/compliance.rules
unet policy show policies/compliance.rules --ast

Arguments:

  • <FILE> - Policy file path

Options:

  • --ast - Show parsed abstract syntax tree

Data Import/Export

unet import

Import data from JSON files.

unet import your-nodes.json
unet import your-data-directory/ --dry-run
unet import your-data-directory/ --continue-on-error

Arguments:

  • <PATH> - JSON file or directory path

Options:

  • --dry-run - Show what would be imported without making changes
  • --continue-on-error - Continue importing even if some items fail

unet export

Export data to JSON/YAML files.

unet export --output-dir exports/
unet export --output-dir exports/ --format yaml --only nodes

Options:

  • --output-dir <DIR> - Output directory (required)
  • --format <FORMAT> - Export format: json, yaml (default: json)
  • --only <TYPE> - Export only specific type: nodes, links, locations
  • --force - Overwrite existing files

Output Formats

Table Format (Default)

Human-readable tabular output with colors when outputting to terminal.

unet nodes list

JSON Format

Machine-readable JSON output.

unet nodes list --output json

YAML Format

Human-readable YAML output.

unet nodes list --output yaml

Configuration

Configuration File

μNet can load settings from a configuration file:

unet --config /path/to/config.toml nodes list

Environment Variables

Set environment variables to avoid repeating common options:

export UNET_DATABASE_URL="sqlite:///path/to/unet.db"
export UNET_SERVER="http://localhost:8080"
export UNET_TOKEN="your-auth-token"

Error Codes

Exit CodeMeaning
0Success
1General error
2Configuration error
3Network/connection error
4Authentication error
5Data validation error

Examples

Basic Network Setup

# Create locations
unet locations add --name "HQ Campus" --location-type campus --address "123 Business Park"
unet locations add --name "Main Building" --location-type building --parent-id <campus-uuid>

# Create nodes
unet nodes add --name core-01 --domain corp.example.com --vendor cisco --model ASR9000 \
    --role router --lifecycle live --management-ip 10.1.1.1

unet nodes add --name dist-01 --domain corp.example.com --vendor cisco --model Catalyst9400 \
    --role switch --lifecycle live --management-ip 10.1.1.2

# Create link
unet links add --node-a core-01 --interface-a TenGigE0/0/0/1 \
    --node-z dist-01 --interface-z TenGigE1/0/1 --bandwidth 10000000000

# View the topology
unet nodes list
unet links list

Policy Validation

# Validate policy syntax
unet policy validate policies/security.rules

# Check compliance
unet policy eval policies/ --failures-only

# Evaluate specific node
unet policy eval policies/compliance.rules --node core-01

Data Management

# Export current configuration
unet export --output-dir backup/ --format yaml

# Import from backup
unet import backup/nodes.yaml --dry-run
unet import backup/

Limitations (Current Version)

  • Template engine: Not yet implemented (planned for v0.2.0)
  • SNMP polling controls: Background polling runs automatically, but CLI controls are not implemented
  • Node comparison and history: Planned for future versions
  • Table output formatting: Currently defaults to JSON format
  • Advanced filtering: jq-style filters not yet implemented

For planned features, see the Roadmap.

Policy Guide – Network Compliance and Automation

Audience: Network engineers and operators writing policy rules
Status: Documents implemented policy engine (v0.1.0)


Overview

μNet's policy engine enables declarative network compliance checking and automated data management through a simple Domain Specific Language (DSL). Policies help ensure your network configuration meets organizational standards and automatically apply corrective actions.

Key Benefits:

  • Declarative Rules: Write what you want, not how to achieve it
  • Real-time Compliance: Continuous evaluation of network state
  • Automated Actions: Reduce manual configuration tasks
  • Audit Trail: Track policy execution and compliance status

Quick Start

Your First Policy

Create a file called basic-compliance.rules:

WHEN node.vendor == "Cisco" THEN ASSERT custom_data.snmp_configured IS true

Test it:

unet policy validate basic-compliance.rules
unet policy eval basic-compliance.rules

This policy ensures all Cisco devices have SNMP configured.


Policy Language Syntax

Basic Structure

Every policy rule follows this pattern:

WHEN <condition> THEN <action>
  • WHEN: Introduces the condition that triggers the action
  • Condition: Boolean expression evaluated against node data
  • THEN: Separates condition from action
  • Action: Operation to perform when condition is true

Example Policy Rule

WHEN node.vendor == "Cisco" AND node.lifecycle == "Production" 
THEN SET custom_data.backup_enabled TO true

Conditions

Field References

Access node properties using dot notation:

Field PathData TypeExample
node.idUUID550e8400-e29b-41d4-a716-446655440000
node.nameString"core-switch-01"
node.vendorString"Cisco", "Juniper", "Arista"
node.modelString"ASR9000", "EX4300"
node.roleString"Core", "Access", "Edge"
node.lifecycleString"Production", "Staging"
node.management_ipString"192.168.1.1"
custom_data.fieldAnyJSON field access

Comparison Operators

OperatorDescriptionExample
==Equal tonode.vendor == "Cisco"
!=Not equal tonode.lifecycle != "Decommissioned"
>Greater thancustom_data.port_count > 48
<Less thancustom_data.cpu_percent < 80
>=Greater than or equalcustom_data.uptime >= 86400
<=Less than or equalcustom_data.memory_usage <= 90
CONTAINSString containsnode.model CONTAINS "4000"
MATCHESRegex matchnode.name MATCHES "^core-"

Logical Operators

OperatorDescriptionExample
ANDBoth conditions truenode.vendor == "Cisco" AND node.role == "Core"
OREither condition truenode.lifecycle == "Production" OR node.lifecycle == "Staging"
NOTNegate conditionNOT (node.lifecycle == "Decommissioned")

Parentheses for Grouping

WHEN (node.vendor == "Cisco" OR node.vendor == "Juniper") 
     AND node.lifecycle == "Production"
THEN ASSERT custom_data.monitoring_enabled IS true

Actions

ASSERT Action

Validate that a condition is true. Used for compliance checking.

Syntax:

ASSERT <field> IS <expected_value>
ASSERT <condition>

Examples:

# Check field value
WHEN node.vendor == "Cisco" 
THEN ASSERT custom_data.snmp_enabled IS true

# Check complex condition  
WHEN node.role == "Core"
THEN ASSERT custom_data.redundancy_level >= 2

# Simple assertion with message
WHEN node.lifecycle == "Production"
THEN ASSERT "Device is properly configured for production"

SET Action

Modify node data by setting field values.

Syntax:

SET <field> TO <value>

Examples:

# Set simple value
WHEN node.vendor == "Cisco" 
THEN SET custom_data.backup_method TO "TFTP"

# Set complex data
WHEN node.role == "Access"
THEN SET custom_data.vlan_config TO {"default": 100, "voice": 200}

# Set based on condition
WHEN node.lifecycle == "Production"
THEN SET custom_data.monitoring_interval TO 300

Custom Data Access

Access nested JSON data in the custom_data field:

# Simple field access
custom_data.location_code

# Nested field access  
custom_data.network.vlan_id
custom_data.hardware.memory_gb
custom_data.monitoring.alert_threshold

# Array access (planned feature)
custom_data.interfaces[0].name

Data Types and Values

String Values

"Cisco"
"ASR9000" 
"192.168.1.1"

Numeric Values

100        # Integer
3.14       # Float
48         # Port count
80.5       # Percentage

Boolean Values

true
false

Null Values

null

Common Policy Patterns

Vendor-Specific Compliance

# Cisco devices should have specific SNMP settings
WHEN node.vendor == "Cisco" 
THEN SET custom_data.snmp_version TO "v3"

# Juniper devices need different backup method
WHEN node.vendor == "Juniper"
THEN SET custom_data.backup_protocol TO "SCP"

Role-Based Configuration

# Core devices need redundancy
WHEN node.role == "Core"
THEN ASSERT custom_data.redundancy_enabled IS true

# Access switches have port security
WHEN node.role == "Access" 
THEN SET custom_data.port_security_enabled TO true

# Edge devices need firewall rules
WHEN node.role == "Edge"
THEN ASSERT custom_data.firewall_configured IS true

Lifecycle Management

# Production devices must be monitored
WHEN node.lifecycle == "Production"
THEN SET custom_data.monitoring_enabled TO true

# Decommissioned devices should be isolated
WHEN node.lifecycle == "Decommissioned"  
THEN SET custom_data.network_access TO false

# Staging devices need test configuration
WHEN node.lifecycle == "Staging"
THEN SET custom_data.test_mode TO true

Location-Based Policies

# Data center devices need specific settings
WHEN custom_data.location_type == "datacenter"
THEN SET custom_data.power_monitoring TO true

# Remote sites have different backup schedules
WHEN custom_data.location_type == "remote_office"
THEN SET custom_data.backup_schedule TO "weekly"

Conditional Data Management

# Set VLAN based on device role
WHEN node.role == "Access"
THEN SET custom_data.default_vlan TO 100

WHEN node.role == "Core" 
THEN SET custom_data.default_vlan TO 1

# Configure monitoring intervals by importance
WHEN node.role == "Core" OR node.role == "Edge"
THEN SET custom_data.monitoring_interval TO 60

WHEN node.role == "Access"
THEN SET custom_data.monitoring_interval TO 300

Policy File Organization

Single Policy File

# File: network-compliance.rules

# Vendor compliance
WHEN node.vendor == "Cisco" THEN SET custom_data.snmp_version TO "v3"
WHEN node.vendor == "Juniper" THEN SET custom_data.backup_method TO "SCP"

# Role-based settings  
WHEN node.role == "Core" THEN ASSERT custom_data.redundancy IS true
WHEN node.role == "Access" THEN SET custom_data.port_security TO true

Multiple Policy Files

policies/
├── vendor-compliance.rules      # Vendor-specific rules
├── role-configuration.rules     # Role-based configuration  
├── lifecycle-management.rules   # Lifecycle policies
└── security-baseline.rules     # Security requirements

Policy File Comments

# This policy ensures core devices have redundancy
WHEN node.role == "Core" 
THEN ASSERT custom_data.redundancy_level >= 2

# TODO: Add environmental monitoring for data center devices
# WHEN custom_data.location == "datacenter"
# THEN ASSERT custom_data.temperature_monitoring IS true

Working with Policies

Validating Policy Syntax

# Validate single file
unet policy validate network-compliance.rules

# Validate directory of policies
unet policy validate policies/

# Validate with detailed output
unet policy validate policies/ --verbose

Evaluating Policies

# Evaluate policies against all nodes
unet policy eval network-compliance.rules

# Evaluate against specific node
unet policy eval policies/ --node core-switch-01

# Show only failures
unet policy eval policies/ --failures-only

# Detailed evaluation output
unet policy eval policies/ --verbose

Viewing Policy Results

# List policy files and their rules
unet policy list policies/

# Show policy file contents
unet policy show network-compliance.rules

# Show parsed rules (AST)
unet policy show network-compliance.rules --ast

API Integration

Evaluate Policies via API

curl -X POST http://localhost:8080/api/v1/policies/evaluate \
  -H "Content-Type: application/json" \
  -d '{
    "policies": [
      {
        "id": "cisco-compliance",
        "condition": "node.vendor == \"Cisco\"",
        "action": "assert(\"SNMP configured\")"
      }
    ]
  }'

Get Policy Results

curl http://localhost:8080/api/v1/policies/results?node_id=550e8400-e29b-41d4-a716-446655440000

Best Practices

Policy Design

  1. Start Simple: Begin with basic compliance checks before complex logic
  2. Use Descriptive Names: Make policy intent clear from the rule
  3. Group Related Rules: Organize policies by vendor, role, or function
  4. Test Incrementally: Validate syntax before adding to production

Rule Organization

# Good: Clear, specific rule
WHEN node.vendor == "Cisco" AND node.role == "Core"
THEN ASSERT custom_data.hsrp_configured IS true

# Avoid: Complex nested conditions
WHEN (node.vendor == "Cisco" OR node.vendor == "Juniper") 
     AND (node.role == "Core" OR node.role == "Distribution")
     AND (custom_data.location == "datacenter" OR custom_data.location == "colo")
THEN SET custom_data.complex_setting TO true

Error Handling

  1. Use ASSERT for Compliance: Check requirements with clear messages
  2. Handle Missing Data: Consider what happens with null/undefined values
  3. Test Edge Cases: Verify policies work with minimal data sets

Version Control

# Store policies in Git
git add policies/
git commit -m "Add network compliance policies"

# Review policy changes
git diff policies/network-compliance.rules

Troubleshooting

Common Syntax Errors

# Error: Missing quotes around string
WHEN node.vendor == Cisco  # ❌ Wrong
WHEN node.vendor == "Cisco"  # ✅ Correct

# Error: Invalid field reference  
WHEN node.invalid_field == "value"  # ❌ Wrong
WHEN custom_data.valid_field == "value"  # ✅ Correct

# Error: Missing THEN keyword
WHEN node.vendor == "Cisco" SET custom_data.x TO true  # ❌ Wrong  
WHEN node.vendor == "Cisco" THEN SET custom_data.x TO true  # ✅ Correct

Debugging Policy Evaluation

# Check if policies parse correctly
unet policy validate policies/ --verbose

# Test against specific node  
unet policy eval policies/ --node test-device-01 --verbose

# Examine policy AST
unet policy show policies/debug.rules --ast

Common Issues

  1. Policy Not Triggering: Check condition syntax and field names
  2. SET Action Failing: Verify field path and value type
  3. ASSERT Always Failing: Check for null/undefined values

Performance Considerations

Efficient Policy Design

  • Use Specific Conditions: Avoid overly broad conditions that match many nodes
  • Limit Custom Data Access: Deep JSON traversal can be slow
  • Batch Similar Rules: Group related checks in single policies

Evaluation Performance

  • Node Count: Policies evaluate against all matching nodes
  • Rule Complexity: Complex conditions take more time to evaluate
  • Custom Data Size: Large JSON objects slow down field access

Limitations (Current Version)

  • Array Access: Custom data array indexing not yet supported
  • Function Calls: No built-in functions (length, contains, etc.)
  • Cross-Node References: Cannot reference other nodes in conditions
  • Template Integration: APPLY action is infrastructure-ready but templates not implemented

Examples

Network Security Baseline

# File: security-baseline.rules

# All production devices must have SNMP v3
WHEN node.lifecycle == "Production"
THEN ASSERT custom_data.snmp_version == "v3"

# Core devices need access control
WHEN node.role == "Core"  
THEN ASSERT custom_data.acl_configured IS true

# Edge devices require firewall
WHEN node.role == "Edge"
THEN ASSERT custom_data.firewall_enabled IS true

# Management interfaces should be secured
WHEN node.management_ip != null
THEN SET custom_data.mgmt_security_enabled TO true

Device Lifecycle Management

# File: lifecycle-management.rules

# New devices start in staging
WHEN custom_data.deployment_status == "new"
THEN SET node.lifecycle TO "Staging"

# Production readiness checks
WHEN node.lifecycle == "Staging" AND custom_data.testing_complete IS true
THEN SET node.lifecycle TO "Production"

# Decommissioning workflow
WHEN custom_data.scheduled_replacement != null
THEN SET custom_data.decommission_planned TO true

# Remove access for decommissioned devices
WHEN node.lifecycle == "Decommissioned"
THEN SET custom_data.network_access TO false

Vendor-Specific Configuration

# File: vendor-configuration.rules

# Cisco device standards
WHEN node.vendor == "Cisco"
THEN SET custom_data.config_backup_method TO "TFTP"

WHEN node.vendor == "Cisco" AND node.role == "Core"  
THEN SET custom_data.routing_protocol TO "OSPF"

# Juniper device standards
WHEN node.vendor == "Juniper"
THEN SET custom_data.config_backup_method TO "SCP"

WHEN node.vendor == "Juniper" AND node.role == "Edge"
THEN SET custom_data.security_zones TO ["DMZ", "INTERNAL"]

# Arista device standards  
WHEN node.vendor == "Arista"
THEN SET custom_data.management_protocol TO "eAPI"

For more advanced examples and integration patterns, see the API Reference and CLI Reference.

API Reference – μNet HTTP Server

Audience: Developers integrating with μNet via HTTP API
Status: Documents implemented endpoints only (v0.1.0)


Overview

μNet provides a RESTful HTTP API for all network configuration management operations. The API is built with Axum (Rust) and supports JSON request/response formats.

Base URL: http://localhost:8080 (default)
API Version: v1
Authentication: None (planned for future versions)

Standard Response Format

All API responses follow a consistent format:

Success Response

{
  "data": "<response_data>",
  "success": true,
  "message": null
}

Error Response

{
  "error": "Human-readable error message",
  "code": "ERROR_CODE",
  "success": false
}

HTTP Status Codes

  • 200 - Success
  • 400 - Bad Request (validation errors)
  • 404 - Resource not found
  • 409 - Conflict (constraint violations)
  • 500 - Internal server error
  • 503 - Service unavailable

Health Check

GET /health

System health and status check.

Response

{
  "status": "healthy",
  "service": "μNet",
  "version": "0.1.0",
  "timestamp": "2024-01-15T10:30:00Z",
  "components": {
    "datastore": {
      "status": "healthy",
      "type": "sqlite"
    }
  }
}

Node Management

GET /api/v1/nodes

List all nodes with filtering and pagination.

Query Parameters

  • page (int) - Page number (default: 1)
  • per_page (int) - Items per page (default: 20)
  • lifecycle (string) - Filter by lifecycle state
  • role (string) - Filter by device role
  • vendor (string) - Filter by vendor
  • include_status (bool) - Include SNMP-derived status data

Example Request

GET /api/v1/nodes?vendor=cisco&role=router&page=1&per_page=10

Response

{
  "data": {
    "data": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "core-01",
        "domain": "example.com",
        "fqdn": "core-01.example.com",
        "vendor": "Cisco",
        "model": "ASR9000",
        "role": "Core",
        "lifecycle": "Production",
        "management_ip": "10.1.1.1",
        "location_id": "550e8400-e29b-41d4-a716-446655440001",
        "platform": null,
        "version": null,
        "serial_number": null,
        "asset_tag": null,
        "purchase_date": null,
        "warranty_expires": null,
        "custom_data": {},
        "status": null
      }
    ],
    "total": 50,
    "page": 1,
    "per_page": 10,
    "total_pages": 5,
    "has_next": true,
    "has_prev": false
  },
  "success": true,
  "message": null
}

GET /api/v1/nodes/{id}

Get a specific node by UUID.

Path Parameters

  • id (UUID) - Node identifier

Response

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "core-01",
    "domain": "example.com",
    "fqdn": "core-01.example.com",
    "vendor": "Cisco",
    "model": "ASR9000",
    "role": "Core",
    "lifecycle": "Production",
    "management_ip": "10.1.1.1",
    "location_id": "550e8400-e29b-41d4-a716-446655440001",
    "custom_data": {
      "rack_position": "R1-U20"
    }
  },
  "success": true,
  "message": null
}

POST /api/v1/nodes

Create a new node.

Request Body

{
  "name": "new-router-01",
  "domain": "example.com",
  "vendor": "Cisco",
  "model": "ISR4431",
  "role": "Edge",
  "lifecycle": "Staging",
  "management_ip": "10.1.1.50",
  "location_id": "550e8400-e29b-41d4-a716-446655440001",
  "custom_data": {
    "cost_center": "IT-001",
    "rack_position": "R2-U10"
  }
}

Required Fields: name, vendor, model, role, lifecycle
Optional Fields: domain, management_ip, location_id, custom_data

Vendor Values: Cisco, Juniper, Arista, HPE, Dell, Ubiquiti, MikroTik, Fortinet, PaloAlto, CheckPoint, F5, A10, Riverbed, SilverPeak, VMware, Linux, Windows, Other

Role Values: Core, Distribution, Access, Edge, Firewall, LoadBalancer, WirelessController, WirelessAP, Server, Storage, Hypervisor, Container, IoT, Camera, Phone, Printer, Other

Lifecycle Values: Planning, Staging, Production, Maintenance, Decommissioned

PUT /api/v1/nodes/{id}

Update an existing node (partial updates supported).

Path Parameters

  • id (UUID) - Node identifier

Request Body (all fields optional)

{
  "name": "updated-router-01",
  "lifecycle": "Production",
  "management_ip": "10.1.1.51",
  "custom_data": {
    "maintenance_window": "Sunday 02:00-04:00"
  }
}

DELETE /api/v1/nodes/{id}

Delete a node.

Path Parameters

  • id (UUID) - Node identifier

Response

{
  "data": null,
  "success": true,
  "message": null
}

Node Derived State (SNMP Data)

GET /api/v1/nodes/{id}/status

Get current node status from SNMP polling.

Path Parameters

  • id (UUID) - Node identifier

Response

{
  "data": {
    "node_id": "550e8400-e29b-41d4-a716-446655440000",
    "last_updated": "2024-01-15T10:30:00Z",
    "reachable": true,
    "system_info": {
      "description": "Cisco IOS Software, Version 15.2(7)E6",
      "object_id": "1.3.6.1.4.1.9.1.516",
      "uptime_ticks": 123456789,
      "contact": "admin@example.com",
      "name": "core-01",
      "location": "Data Center Rack 1",
      "services": 72
    },
    "interfaces": [],
    "performance": null,
    "environmental": null,
    "vendor_metrics": {},
    "raw_snmp_data": {},
    "last_snmp_success": "2024-01-15T10:29:45Z",
    "last_error": null,
    "consecutive_failures": 0
  },
  "success": true,
  "message": null
}

GET /api/v1/nodes/{id}/interfaces

Get interface status for a node.

Path Parameters

  • id (UUID) - Node identifier

Response

{
  "data": [
    {
      "index": 1,
      "name": "GigabitEthernet1/0/1",
      "interface_type": 6,
      "mtu": 1500,
      "speed": 1000000000,
      "physical_address": "aa:bb:cc:dd:ee:ff",
      "admin_status": "Up",
      "oper_status": "Up",
      "last_change": "2024-01-15T08:00:00Z",
      "input_stats": {
        "octets": 1234567890,
        "unicast_packets": 9876543,
        "non_unicast_packets": 1000,
        "discards": 0,
        "errors": 0,
        "unknown_protocols": 0
      },
      "output_stats": {
        "octets": 987654321,
        "unicast_packets": 5432109,
        "non_unicast_packets": 500,
        "discards": 0,
        "errors": 0
      }
    }
  ],
  "success": true,
  "message": null
}

GET /api/v1/nodes/{id}/metrics

Get performance metrics for a node.

Path Parameters

  • id (UUID) - Node identifier

Response

{
  "data": {
    "cpu_utilization": 15.5,
    "memory_utilization": 45.2,
    "temperature": 42.0,
    "total_memory_kb": 524288,
    "available_memory_kb": 287309,
    "buffer_hit_ratio": 98.5,
    "uptime_seconds": 1234567
  },
  "success": true,
  "message": null
}

Policy Management

POST /api/v1/policies/evaluate

Evaluate policies against nodes.

Request Body

{
  "node_ids": ["550e8400-e29b-41d4-a716-446655440000"],
  "policies": [
    {
      "id": "cisco-compliance",
      "condition": "node.vendor == 'Cisco' && node.lifecycle == 'Production'",
      "action": "assert('Cisco device in production has proper config')"
    }
  ],
  "store_results": true
}

Fields:

  • node_ids (array, optional) - Node UUIDs to evaluate (default: all nodes)
  • policies (array, optional) - Policy rules to evaluate (default: load from configured source)
  • store_results (bool, optional) - Store results in database (default: true)

Response

{
  "data": {
    "results": {
      "550e8400-e29b-41d4-a716-446655440000": [
        {
          "policy_id": "cisco-compliance",
          "status": "Satisfied",
          "message": "Cisco device in production has proper config",
          "execution_time_ms": 12,
          "timestamp": "2024-01-15T10:30:00Z"
        }
      ]
    },
    "nodes_evaluated": 1,
    "policies_evaluated": 1,
    "evaluation_time_ms": 150,
    "summary": {
      "total_rules": 1,
      "satisfied_rules": 1,
      "unsatisfied_rules": 0,
      "error_rules": 0,
      "compliance_failures": 0
    }
  },
  "success": true,
  "message": null
}

GET /api/v1/policies/results

Get stored policy evaluation results.

Query Parameters

  • node_id (UUID, optional) - Filter by node
  • limit (int, optional) - Maximum results (default: 100)
  • offset (int, optional) - Results to skip (default: 0)

Response

{
  "data": {
    "results": [
      {
        "policy_id": "cisco-compliance",
        "status": "Satisfied",
        "message": "Cisco device in production has proper config",
        "execution_time_ms": 12,
        "timestamp": "2024-01-15T10:30:00Z"
      }
    ],
    "total_count": 1,
    "returned_count": 1
  },
  "success": true,
  "message": null
}

POST /api/v1/policies/validate

Validate policy rule syntax.

Request Body

[
  {
    "id": "valid-policy",
    "condition": "node.vendor == 'Cisco'",
    "action": "assert('Valid Cisco device')"
  },
  {
    "id": "invalid-policy",
    "condition": "",
    "action": "invalid_action()"
  }
]

Response

{
  "total_policies": 2,
  "valid_policies": 1,
  "invalid_policies": 1,
  "validation_results": [
    {
      "index": 0,
      "valid": true,
      "message": "Policy rule is valid"
    },
    {
      "index": 1,
      "valid": false,
      "message": "Policy rule has syntax errors"
    }
  ]
}

GET /api/v1/policies/status

Get policy engine status.

Response

{
  "policy_engine_enabled": true,
  "nodes_available": 25,
  "policies_available": 10,
  "last_evaluation": null,
  "evaluation_frequency": "on-demand"
}

Error Handling

Common Error Codes

CodeDescription
VALIDATION_ERRORRequest validation failed
NOT_FOUNDResource not found
CONSTRAINT_VIOLATIONDatabase constraint violated
DATASTORE_ERRORDatabase operation failed
POLICY_ERRORPolicy evaluation failed
SNMP_ERRORSNMP operation failed

Example Error Response

{
  "error": "Node with name 'duplicate-name' already exists",
  "code": "CONSTRAINT_VIOLATION",
  "success": false
}

Examples

Create a Complete Network Setup

# Create a location first
curl -X POST http://localhost:8080/api/v1/locations \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Data Center 1",
    "location_type": "Building",
    "address": "123 Server St"
  }'

# Create nodes
curl -X POST http://localhost:8080/api/v1/nodes \
  -H "Content-Type: application/json" \
  -d '{
    "name": "core-01",
    "domain": "example.com",
    "vendor": "Cisco",
    "model": "ASR9000",
    "role": "Core",
    "lifecycle": "Production",
    "management_ip": "10.1.1.1",
    "location_id": "550e8400-e29b-41d4-a716-446655440001"
  }'

# List nodes
curl http://localhost:8080/api/v1/nodes?vendor=Cisco

# Get node status
curl http://localhost:8080/api/v1/nodes/550e8400-e29b-41d4-a716-446655440000/status

Policy Evaluation

# Evaluate compliance policies
curl -X POST http://localhost:8080/api/v1/policies/evaluate \
  -H "Content-Type: application/json" \
  -d '{
    "policies": [
      {
        "id": "production-check",
        "condition": "node.lifecycle == \"Production\"",
        "action": "assert(\"Device is in production\")"
      }
    ]
  }'

# Get evaluation results
curl http://localhost:8080/api/v1/policies/results?limit=50

Configuration

Server Configuration

The API server can be configured via command line, environment variables, or configuration file:

# Command line
unet-server --host 0.0.0.0 --port 8080 --database-url sqlite://production.db

# Environment variables
export UNET_HOST=0.0.0.0
export UNET_PORT=8080
export UNET_DATABASE_URL=sqlite://production.db
unet-server

# Configuration file
unet-server --config /etc/unet/server.toml

CORS

The server enables permissive CORS for development. In production, configure appropriate CORS policies.


Future Enhancements

  • Authentication & Authorization - Token-based access control
  • Rate Limiting - Request throttling and abuse prevention
  • WebSocket Support - Real-time updates and notifications
  • GraphQL API - Alternative query interface
  • OpenAPI Specification - Auto-generated API documentation

For planned features, see the Roadmap.

Developer Guide

This guide provides comprehensive patterns, best practices, and decision trees for developing μNet. It complements the Architecture document with practical implementation guidance.

Quick Reference

Finding Implementation Patterns

  • New entities: Copy pattern from crates/unet-core/src/entities/nodes.rs
  • New API endpoints: Copy pattern from crates/unet-server/src/handlers/nodes/crud.rs
  • New CLI commands: Copy pattern from crates/unet-cli/src/commands/nodes/crud.rs
  • Database migrations: Copy pattern from crates/migrations/src/m20241221_000002_create_nodes_table.rs
  • SNMP integration: Study patterns in crates/unet-core/src/snmp/

Essential Search Terms

# Find similar API implementations
grep -r "async fn.*Result<Json" crates/unet-server/src/handlers/

# Find entity patterns
grep -r "DeriveEntityModel" crates/unet-core/src/entities/

# Find test patterns
grep -r "#\[tokio::test\]" crates/*/src/

# Find error handling patterns
grep -r "ApiError" crates/unet-server/src/

# Find SNMP patterns
grep -r "SnmpSession" crates/unet-core/src/snmp/

Decision Trees

Adding New Data Fields

Is this field user-configurable?
├─ Yes → Desired state (nodes, locations, links tables)
│   ├─ Required for basic functionality? → NOT NULL
│   └─ Optional enhancement? → NULL allowed
└─ No → Is it derived from SNMP/monitoring?
    ├─ Yes → Derived state (node_status, interface_status tables)
    │   ├─ Always available from SNMP? → NOT NULL
    │   └─ Device-dependent? → NULL allowed
    └─ No → Consider if this belongs in custom_data JSON field

Build & Test Performance

Lib-First Binaries (sccache-friendly)

  • Pattern: keep src/main.rs as a thin shim and move logic into src/lib.rs.
  • Benefits: lib artifacts (rlib) are reused across tests, coverage, and other bins by sccache.
  • Applied in this repo:
    • unet-cli: CLI parsing and execution in lib, main delegates.
    • unet-server: modules and run() in lib, main delegates.
    • config-slicer: CLI parsing and execution in lib, main delegates.
  • Writing tests: prefer in-process tests calling library functions; keep minimal binary smoke tests.

sccache Usage

  • Local defaults: .cargo/config.toml sets RUSTC_WRAPPER=sccache if not set.
  • CI: workflows install and cache ~/.cache/sccache.
  • Cache hints:
    • Keep flags consistent between tasks to maximize cache hits.
    • Prefer default features locally; use --all-features only in CI.
    • Avoid embedding non-deterministic build-time values unless gated.

Optional Fast Linker (Linux GNU)

  • lld/mold can reduce link time. Example usage for local runs:
# Requires clang + lld
RUSTFLAGS="-C link-arg=-fuse-ld=lld" \
  CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang \
  cargo build

# Or mold if installed
RUSTFLAGS="-C link-arg=-fuse-ld=mold" \
  CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang \
  cargo nextest run
  • Notes:
    • macOS uses Apple’s linker; lld/mold steps above are Linux-specific.
    • These flags are optional and not set globally to avoid portability issues.

Fast Coverage Loop

  • Local: mise run coverage-fast (tests only, --no-clean, show missing lines).
  • CI: mise run ci-coverage (workspace, all features/targets as configured).

Choosing Error Handling Approach

Where does the error originate?
├─ API endpoint → Use ApiError with appropriate HTTP status
│   ├─ User input validation → 400 Bad Request
│   ├─ Resource not found → 404 Not Found
│   ├─ Database constraint → 409 Conflict
│   └─ Internal system error → 500 Internal Server Error
├─ SNMP operation → Use csnmp error types
│   ├─ Network timeout → Retry with exponential backoff
│   ├─ Authentication failure → Log and mark node unreachable
│   └─ Parse error → Log raw data and continue
└─ Database operation → Use sea_orm::DbErr
    ├─ Transaction conflict → Retry operation
    └─ Schema mismatch → Return structured error

Database Query Optimization

What type of query?
├─ Single record by ID → Use find_by_id() - most efficient
├─ List with filters → Use find() with where clauses
│   ├─ Common filter? → Ensure index exists
│   ├─ Large result set? → Add pagination
│   └─ Complex joins? → Consider separate queries
└─ Aggregation → Use select() with group_by()
    ├─ Real-time display? → Cache results
    └─ Background reporting? → Direct SQL may be faster

Code Patterns

Standard Entity Implementation

When creating a new entity, follow this pattern:

// crates/unet-core/src/entities/example.rs
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};

/// Description of what this entity represents
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
#[sea_orm(table_name = "example")]
pub struct Model {
    /// Primary key - always use String for UUID
    #[sea_orm(primary_key, auto_increment = false)]
    pub id: String,
    
    /// Required fields come first
    pub name: String,
    pub example_type: String,
    
    /// Optional fields
    pub description: Option<String>,
    pub custom_data: Option<String>,
    
    /// Timestamps - always include these
    pub created_at: String,
    pub updated_at: String,
}

/// Database relations
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
    // Define relationships to other entities
}

impl ActiveModelBehavior for ActiveModel {}

Standard API Endpoint Implementation

// crates/unet-server/src/handlers/example/crud.rs
use axum::{extract::State, http::StatusCode, Json};
use crate::{ApiError, AppState};

/// Create a new example
pub async fn create_example(
    State(app_state): State<AppState>,
    Json(payload): Json<CreateExampleRequest>,
) -> Result<Json<Example>, ApiError> {
    // 1. Validate input
    payload.validate()?;
    
    // 2. Check permissions/authorization if needed
    
    // 3. Transform to domain model
    let example = Example::from(payload);
    
    // 4. Store via DataStore trait
    let created = app_state.datastore.create_example(example).await
        .map_err(|e| ApiError::internal_error("Failed to create example", e))?;
    
    // 5. Return response
    Ok(Json(created))
}

/// Request/response types
#[derive(Debug, Deserialize)]
pub struct CreateExampleRequest {
    pub name: String,
    pub example_type: String,
    pub description: Option<String>,
}

impl CreateExampleRequest {
    fn validate(&self) -> Result<(), ApiError> {
        if self.name.is_empty() {
            return Err(ApiError::bad_request("Name cannot be empty"));
        }
        Ok(())
    }
}

Standard Test Patterns

// Follow TDD - write test first!
#[tokio::test]
async fn test_create_example_success() {
    // Arrange
    let datastore = setup_test_datastore().await;
    let example = Example {
        id: Uuid::new_v4(),
        name: "test-example".to_string(),
        example_type: "test".to_string(),
        description: Some("Test description".to_string()),
        custom_data: None,
        created_at: chrono::Utc::now().to_rfc3339(),
        updated_at: chrono::Utc::now().to_rfc3339(),
    };
    
    // Act
    let result = datastore.create_example(example.clone()).await;
    
    // Assert
    assert!(result.is_ok());
    let created = result.unwrap();
    assert_eq!(created.name, example.name);
    assert_eq!(created.example_type, example.example_type);
    
    // Cleanup
    cleanup_test_data(&datastore).await;
}

#[tokio::test]
async fn test_create_example_duplicate_name() {
    // Test error conditions
    let datastore = setup_test_datastore().await;
    
    // Create first example
    let example1 = create_test_example(&datastore, "duplicate-name").await.unwrap();
    
    // Try to create second with same name
    let example2 = Example { name: "duplicate-name".to_string(), ..test_example() };
    let result = datastore.create_example(example2).await;
    
    assert!(result.is_err());
    // Verify specific error type
    
    cleanup_test_data(&datastore).await;
}

SNMP Integration Patterns

// crates/unet-core/src/snmp/collectors/example.rs
use crate::snmp::{SnmpSession, SnmpError};
use std::time::Duration;

pub struct ExampleCollector {
    session: SnmpSession,
}

impl ExampleCollector {
    pub fn new(session: SnmpSession) -> Self {
        Self { session }
    }
    
    pub async fn collect_example_data(&mut self, node_id: &str) -> Result<ExampleData, SnmpError> {
        // 1. Define OIDs to query
        let oids = vec![
            "1.3.6.1.2.1.1.1.0".to_string(), // sysDescr
            "1.3.6.1.2.1.1.3.0".to_string(), // sysUpTime
        ];
        
        // 2. Perform bulk query with timeout
        let results = self.session
            .bulk_get(oids)
            .timeout(Duration::from_secs(30))
            .await?;
        
        // 3. Parse results with error handling
        let mut data = ExampleData::default();
        for (oid, value) in results {
            match oid.as_str() {
                "1.3.6.1.2.1.1.1.0" => {
                    data.description = value.as_string().ok();
                }
                "1.3.6.1.2.1.1.3.0" => {
                    data.uptime = value.as_counter64()
                        .map(Duration::from_centiseconds)
                        .ok();
                }
                _ => {
                    tracing::warn!("Unexpected OID in response: {}", oid);
                }
            }
        }
        
        Ok(data)
    }
}

#[derive(Debug, Default)]
pub struct ExampleData {
    pub description: Option<String>,
    pub uptime: Option<Duration>,
}

Domain-Specific Patterns

Network Automation Best Practices

SNMP Polling Strategy

  • Bulk operations: Always use bulk_get for multiple OIDs
  • Timeout handling: Set reasonable timeouts (30s for system info, 60s for large tables)
  • Error recovery: Distinguish between temporary (network) and permanent (auth) failures
  • Rate limiting: Respect device capabilities - don't overwhelm network equipment

Policy Evaluation Performance

  • Cache policy ASTs: Parse policies once, evaluate many times
  • Batch evaluations: Process multiple nodes/policies in single transaction
  • Lazy loading: Only load data that policies actually reference
  • Early termination: Stop evaluation as soon as decision is clear

State Management

  • Desired State: User configurations, topology definitions, policy rules
  • Derived State: SNMP data, calculated metrics, policy evaluation results
  • Never mix: Keep clear separation between what users configure vs. what system discovers

Common Anti-Patterns to Avoid

Database Anti-Patterns

// DON'T: Bypass DataStore trait
let node = Node::find_by_id(node_id).one(&db).await?;

// DO: Use DataStore abstraction
let node = datastore.get_node(&node_id).await?;

// DON'T: N+1 queries
for node in nodes {
    let location = datastore.get_location(&node.location_id).await?;
}

// DO: Bulk operations
let location_ids: Vec<_> = nodes.iter().map(|n| &n.location_id).collect();
let locations = datastore.get_locations_by_ids(&location_ids).await?;

SNMP Anti-Patterns

// DON'T: Blocking calls in async context
let result = std::thread::spawn(|| snmp_sync_call()).join();

// DO: Use async SNMP operations
let result = snmp_session.get(oid).await?;

// DON'T: Ignore timeouts
let result = snmp_session.get(oid).await?;

// DO: Set appropriate timeouts
let result = snmp_session.get(oid).timeout(Duration::from_secs(30)).await?;

Error Handling Anti-Patterns

// DON'T: Generic error messages
return Err(ApiError::internal_error("Something went wrong"));

// DO: Specific, actionable errors
return Err(ApiError::bad_request("Node name must be between 1 and 255 characters"));

// DON'T: Expose internal details
return Err(ApiError::internal_error(format!("Database error: {}", db_error)));

// DO: Log internal details, return user-friendly message
tracing::error!("Database constraint violation: {}", db_error);
return Err(ApiError::conflict("A node with this name already exists"));

Debugging & Troubleshooting

SNMP Issues

Connection Problems

  1. Check network connectivity: ping <device_ip>
  2. Verify SNMP credentials: Test with snmpwalk command
  3. Check firewall rules: Ensure UDP 161 is accessible
  4. Validate community strings: Ensure they match device configuration

Query Failures

  1. OID validation: Verify OIDs exist on target device
  2. Permission checking: Ensure community has read access to OIDs
  3. MIB loading: Check if custom MIBs are needed
  4. Timeout tuning: Increase timeouts for slow devices

Performance Issues

  1. Bulk query optimization: Group related OIDs together
  2. Polling frequency: Reduce frequency for non-critical metrics
  3. Device capability: Some devices can't handle high query rates
  4. Network latency: Account for WAN links with higher timeouts

Database Performance

Slow Queries

  1. Check indexes: Ensure proper indexes on filtered columns
  2. Query analysis: Use EXPLAIN QUERY PLAN for complex queries
  3. Pagination: Add LIMIT/OFFSET for large result sets
  4. Connection pooling: Monitor connection pool utilization

Lock Contention

  1. Transaction scope: Keep transactions as short as possible
  2. Retry logic: Implement exponential backoff for lock timeouts
  3. Read replicas: Use read-only queries where possible
  4. Batch operations: Group multiple updates into single transaction

API Performance

Slow Endpoints

  1. Database queries: Profile database access patterns
  2. Serialization: Large JSON responses can be slow
  3. External dependencies: SNMP calls, file I/O
  4. Memory allocation: Check for unnecessary clones/allocations

Memory Issues

  1. Large datasets: Implement streaming for large responses
  2. Connection leaks: Monitor database connection usage
  3. Background tasks: Check for memory leaks in polling tasks
  4. Logging overhead: Excessive debug logging can consume memory

Task Recipes

Adding a New SNMP OID

  1. Research the OID

    # Test with snmpwalk first
    snmpwalk -v2c -c public <device_ip> <new_oid>
    
  2. Add to OID definitions

    // crates/unet-core/src/snmp/oids/standard.rs
    pub const NEW_METRIC_OID: &str = "1.3.6.1.2.1.x.x.x";
  3. Update collector

    // Add to relevant collector in crates/unet-core/src/snmp/collectors/
    let oids = vec![
        // existing OIDs...
        NEW_METRIC_OID.to_string(),
    ];
  4. Add to data model

    // Update derived state entity
    pub new_metric: Option<i64>,
  5. Write tests

    #[tokio::test]
    async fn test_collect_new_metric() {
        // Test successful collection
        // Test missing OID handling
        // Test parsing edge cases
    }
  6. Update migration

    # Create new migration file
    cargo run --bin migration -- generate add_new_metric_column
    

Adding a New Policy Rule Type

  1. Define AST node

    // crates/unet-core/src/policy/ast.rs
    pub enum Condition {
        // existing conditions...
        NewRuleType { field: String, operator: ComparisonOp, value: Value },
    }
  2. Update parser

    // crates/unet-core/src/policy/grammar.pest  
    new_rule = { "new_rule" ~ "(" ~ field ~ operator ~ value ~ ")" }
    
  3. Implement evaluator

    // crates/unet-core/src/policy/evaluator/conditions.rs
    Condition::NewRuleType { field, operator, value } => {
        let node_value = get_node_field(node, field)?;
        compare_values(&node_value, operator, value)
    }
  4. Add CLI support

    // crates/unet-cli/src/commands/policy/
    // Add new subcommand for rule type
    
  5. Write comprehensive tests

    #[tokio::test]
    async fn test_new_rule_evaluation() {
        // Test various value types
        // Test all operators
        // Test edge cases and errors
    }

Extending the Data Model

  1. Plan the change

    • Desired vs derived state?
    • Required vs optional field?
    • Index requirements?
  2. Create migration

    cargo run --bin migration -- generate add_new_field_to_table
    
  3. Update entity model

    // Add field to appropriate entity
    pub new_field: Option<String>,
  4. Update DataStore trait

    // Add methods if needed
    async fn update_new_field(&self, id: &str, value: String) -> Result<()>;
  5. Implement in datastores

    // Update the SQLite implementation
    
  6. Add API endpoints

    // Update request/response types
    // Add validation logic
    // Update handlers
    
  7. Update CLI

    // Add command line options
    // Update output formatting
    
  8. Write tests

    // Unit tests for data model
    // Integration tests for API
    // End-to-end tests for CLI
    

Performance Guidelines

Database Optimization

Query Patterns

  • Single record: Use find_by_id() with primary key
  • Filtered lists: Use find().filter() with indexed columns
  • Counts: Use count() instead of loading all records
  • Exists checks: Use count() > 0 for existence tests

Index Strategy

  • Primary keys: Automatic unique index
  • Foreign keys: Add index for join performance
  • Filter columns: Index frequently filtered columns
  • Composite indexes: For multi-column filters

Transaction Management

  • Read operations: No transaction needed for single queries
  • Write operations: Use transactions for multi-table updates
  • Long operations: Break into smaller transactions
  • Retry logic: Handle transaction conflicts gracefully

Memory Management

Large Datasets

  • Streaming: Process records in batches
  • Pagination: Limit result set sizes
  • Lazy loading: Load related data on demand
  • Connection pooling: Reuse database connections

Background Tasks

  • Resource cleanup: Properly close connections and files
  • Memory monitoring: Check for gradual memory leaks
  • Graceful shutdown: Handle termination signals properly
  • Error recovery: Restart failed background tasks

Network Optimization

SNMP Efficiency

  • Bulk operations: Query multiple OIDs together
  • Connection reuse: Maintain persistent SNMP sessions
  • Timeout tuning: Balance responsiveness vs. reliability
  • Error handling: Distinguish temporary vs. permanent failures

API Performance

  • Response size: Minimize JSON payload size
  • Caching: Cache expensive computations
  • Compression: Use gzip for large responses
  • Connection limits: Prevent resource exhaustion

This guide provides the foundation for efficient μNet development. Always refer to existing code patterns and follow the TDD practices outlined in AGENTS.md.

Codex Startup Script

Purpose: Document the commands run when a Codex environment starts

This script installs the development and CI tooling used by μNet. It is executed automatically for Codex containers.

rustup component add clippy rustfmt llvm-tools-preview
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
cargo binstall --disable-telemetry --no-confirm cargo-tarpaulin cargo-audit typos-cli mise mdbook cargo-llvm-cov
mise trust
curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin
cargo fetch
npm install markdownlint-cli2 --global --no-progress

Command Overview

  • rustup component add clippy rustfmt llvm-tools-preview – install Rust linting, formatting, and LLVM coverage components.
  • curl ... cargo-binstall ... – download and install the cargo-binstall helper.
  • cargo binstall ... – install code coverage, security audit, formatting, and other tooling.
  • mise trust – mark this repository's mise configuration as trusted.
  • curl ... nexte.st ... – fetch the nextest binary used to run tests.
  • cargo fetch – pre-download Rust dependencies.
  • npm install markdownlint-cli2 --global --no-progress – install the Markdown linter.

Architecture Overview – μNet Network Management System

Audience: Engineers and operators working with μNet
Status: Documents current implementation (v0.1.0)


Overview

μNet is a network configuration management system built in Rust, designed around three core principles:

  1. Single Binary Deployment - Both CLI and server are self-contained executables
  2. Modular Architecture - Clear separation between data, policy, and presentation layers
  3. Progressive Adoption - Start small, grow capabilities over time

System Architecture

Current Implementation

┌─────────────────────────────────────────────────────────────────────────┐
│                          μNet System (v0.1.0)                          │
│ ─────────────────────────────────────────────────────────────────────── │
│                                                                         │
│  ┌─────────────────┐           ┌─────────────────┐                     │
│  │   unet-cli      │    HTTP   │  unet-server    │                     │
│  │                 │◄──────────┤                 │                     │
│  │ • Commands      │    JSON   │ • REST API      │                     │
│  │ • Output Format │           │ • Background    │                     │
│  │ • Local/Remote  │           │   Tasks         │                     │
│  └─────────────────┘           └─────────────────┘                     │
│           │                             │                               │
│           │                             │                               │
│           ▼                             ▼                               │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                    unet-core Library                           │   │
│  │ ─────────────────────────────────────────────────────────────── │   │
│  │ • Data Models    • DataStore Trait   • Policy Engine          │   │
│  │ • SNMP Client    • Error Handling    • Configuration          │   │
│  └─────────────────────────────────────────────────────────────────┘   │
│                              │                                         │
│                              ▼                                         │
│  ┌─────────────────────────────────────────────────────────────────┐   │
│  │                    Data Storage                                │   │
│  │ ─────────────────────────────────────────────────────────────── │   │
│  │ SQLite Database                                          │   │
│  │ • SeaORM Entities                                       │   │
│  │ • Migrations                                            │   │
│  │ • ACID Transactions                                     │   │
│  └─────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────┘

External Network Devices
├── SNMP Polling ──────► Node Status, Interface Stats, System Info
├── Policy Evaluation ──► Compliance Checking
└── Configuration Management (Planned for v0.2.0)

Component Architecture

Core Library (unet-core)

The heart of μNet, providing all business logic as a reusable library.

Data Models

  • Node: Network devices with lifecycle management
  • Link: Connections between nodes (point-to-point and circuits)
  • Location: Hierarchical physical locations (campus → building → rack)
  • Derived State: SNMP-collected data (status, interfaces, metrics)

DataStore Abstraction

use sea_orm::DbErr;

// Example types for illustration
struct Node {
    id: String,
    name: String,
}

struct QueryOptions {
    limit: Option<u64>,
    offset: Option<u64>,
}

struct PagedResult<T> {
    items: Vec<T>,
    total: u64,
}

trait DataStore {
    async fn get_node(&self, id: &str) -> Result<Option<Node>, DbErr>;
    async fn create_node(&self, node: &Node) -> Result<(), DbErr>;
    async fn list_nodes(&self, options: QueryOptions) -> Result<PagedResult<Node>, DbErr>;
    // ... comprehensive CRUD operations
}

Implementations:

  • SQLiteStore: Production backend using SeaORM

Policy Engine

  • DSL Parser: Pest-based grammar for WHEN/THEN rules
  • Evaluator: Context-based rule execution against JSON data
  • Actions: Assert (compliance), Set (data modification)

SNMP Integration

  • Client: Async SNMP operations with connection pooling
  • Polling: Background tasks for device data collection
  • OID Mapping: Standard and vendor-specific MIB support

Server Binary (unet-server)

HTTP API server built with Axum framework.

API Features

  • REST Endpoints: Full CRUD operations for all data types
  • Pagination: Built-in support for large datasets
  • Filtering: Query nodes by vendor, role, lifecycle
  • Error Handling: Consistent JSON error responses
  • Derived State: SNMP data accessible via dedicated endpoints

Background Services

  • SNMP Polling: Continuous device monitoring
  • Policy Evaluation: Periodic compliance checking
  • Health Monitoring: Component status tracking

CLI Binary (unet-cli)

Command-line interface for operators and automation.

Command Structure

unet [global-options] <command> <subcommand> [args]

Commands:
├── nodes     - Device CRUD operations
├── links     - Connection management  
├── locations - Site management
├── policy    - Compliance operations
├── import    - Data import from JSON/YAML
└── export    - Data export to JSON/YAML

Features

  • Multiple Output Formats: Table, JSON, YAML
  • Local & Remote Operation: Direct database or HTTP API
  • Comprehensive Validation: Input checking and error reporting
  • Pagination Support: Handle large datasets efficiently

Data Flow

1. Device Management Flow

Operator ──► CLI Command ──► DataStore ──► Database
   │              │             │            │
   │              │             │            │
   ▼              ▼             ▼            ▼
Input          Validation   Business     Persistence
Parsing        & Building   Logic        & Integrity

2. SNMP Monitoring Flow

Device ──► SNMP Client ──► DataStore ──► Derived State
   │           │              │             │
   │           │              │             │
   ▼           ▼              ▼             ▼
Status      OID Mapping   Storage        API Access
Data        & Parsing     Update         & Queries

3. Policy Evaluation Flow

Policy Files ──► Parser ──► Evaluator ──► Results
     │             │           │            │
     │             │           │            │
     ▼             ▼           ▼            ▼
   Rules         AST       Context        Compliance
  Syntax      Building    Evaluation      Reports

Technology Stack

Core Technologies

ComponentTechnologyRationale
LanguageRustMemory safety, performance, async support
DatabaseSQLite + SeaORMZero-ops deployment, type-safe queries
HTTP ServerAxumModern async framework, high performance
CLI FrameworkClap v4Rich features, derive macros, shell completion
SNMP ClientcsnmpPure Rust, async-first SNMP implementation
Policy ParserPestPEG parser with detailed error reporting

Data Formats

Use CaseFormatDetails
API Requests/ResponsesJSONStandard REST API format
ConfigurationTOMLHuman-readable, well-structured
Data Import/ExportJSON/YAMLFlexible bulk operations
Error LoggingStructured JSONMachine-parsable logs

Async Architecture

All I/O operations are fully asynchronous using Tokio:

  • Database Operations: Non-blocking SeaORM queries
  • HTTP Server: Concurrent request handling
  • SNMP Polling: Parallel device monitoring
  • CLI Operations: Async throughout, no blocking calls

Current Capabilities

✅ Implemented Features

Data Management

  • Full CRUD Operations: Create, read, update, delete for all entities
  • Hierarchical Locations: Campus → Building → Floor → Rack structure
  • Lifecycle Management: Device states from planning to decommissioned
  • Custom Data Support: JSON fields for extensibility

Network Monitoring

  • SNMP Polling: Background collection of device status
  • Interface Statistics: Port-level traffic and error counters
  • System Information: Device description, uptime, contact info
  • Connection Pooling: Efficient SNMP session management

Policy & Compliance

  • DSL Language: WHEN/THEN rule syntax for network policies
  • Rule Evaluation: Real-time compliance checking
  • Bulk Operations: Evaluate policies across entire network
  • Result Storage: Historical compliance tracking

API & CLI

  • Comprehensive REST API: Full HTTP interface for automation
  • Rich CLI: Interactive commands with multiple output formats
  • Data Import/Export: Bulk operations for network topology
  • Error Handling: Detailed error messages and recovery guidance

🚧 Planned Features

  • Template Engine: Configuration generation (v0.2.0)
  • Advanced SNMP CLI: Historical metrics, polling controls
  • Configuration Push: Safe deployment to devices
  • Git Integration: Version control for policies and templates
  • Web UI: Browser-based management interface

Database Schema

Core Entities

-- Locations (hierarchical)
locations
├── id (UUID)
├── name (TEXT)
├── location_type (TEXT)
├── parent_id (UUID, FK)
├── address (TEXT)
└── custom_data (JSON)

-- Nodes (network devices)  
nodes
├── id (UUID)
├── name (TEXT)
├── domain (TEXT)
├── fqdn (TEXT, computed)
├── vendor (TEXT)
├── model (TEXT)
├── role (TEXT)
├── lifecycle (TEXT)
├── management_ip (TEXT)
├── location_id (UUID, FK)
└── custom_data (JSON)

-- Links (connections)
links
├── id (UUID)
├── node_a_id (UUID, FK)
├── interface_a (TEXT)
├── node_z_id (UUID, FK, nullable)
├── interface_z (TEXT, nullable)
├── circuit_id (TEXT, nullable)
├── bandwidth (BIGINT)
└── custom_data (JSON)

Derived State Tables

-- SNMP-collected data
node_status
├── node_id (UUID, FK)
├── last_updated (TIMESTAMP)
├── reachable (BOOLEAN)
├── system_info (JSON)
├── raw_snmp_data (JSON)
└── last_error (TEXT)

interface_status
├── node_id (UUID, FK)
├── interface_index (INTEGER)
├── name (TEXT)
├── admin_status (TEXT)
├── oper_status (TEXT)
├── statistics (JSON)
└── last_updated (TIMESTAMP)

Security Considerations

Current State

  • No Authentication: All endpoints publicly accessible
  • Input Validation: Comprehensive validation of all user inputs
  • SQL Injection Protection: SeaORM provides safe query building
  • Error Information: Sanitized error responses, no sensitive data exposure

Planned Security Features

  • Token-based Authentication: JWT or similar for API access
  • Role-based Authorization: Different permission levels
  • Audit Logging: Comprehensive change tracking
  • TLS/HTTPS: Encrypted communication

Performance Characteristics

Current Performance

  • Database: SQLite performs well for <10K devices
  • API Response Times: Sub-100ms for typical operations
  • SNMP Polling: Configurable intervals, parallel execution
  • Memory Usage: ~50MB base, scales with dataset size

Scalability Considerations

  • Horizontal Scaling: Not currently supported (SQLite limitation)
  • Vertical Scaling: Optimized single-machine performance
  • Caching: Minimal caching, relies on SQLite performance
  • Connection Pooling: SNMP connections reused efficiently

Development Philosophy

Code Quality

  • Type Safety: Rust's type system prevents many runtime errors
  • Error Handling: Comprehensive error types with context
  • Testing: Unit tests for business logic, integration tests for APIs
  • Documentation: Inline docs and comprehensive guides

Operational Excellence

  • Single Binary: No external dependencies for deployment
  • Configuration: Environment variables, files, or CLI arguments
  • Logging: Structured logging with multiple levels
  • Metrics: Built-in health checks and status endpoints

Future Architecture Plans

Template Engine (v0.2.0)

  • MiniJinja Integration: Rust-native templating
  • Configuration Generation: Device-specific config templates
  • Diff Engine: Compare generated vs. actual configurations
  • Partial Templates: Template only specific config sections

Enhanced Storage (v0.3.0)

  • PostgreSQL Support: Production-scale database backend
  • Time-Series Data: Historical metrics and performance data
  • Backup/Restore: Automated data protection
  • Multi-tenancy: Support for multiple organizations

Advanced Features (v1.0.0)

  • Configuration Push: Safe deployment to network devices
  • Rollback Mechanisms: Automatic recovery from failed changes
  • Change Management: Approval workflows and audit trails
  • High Availability: Clustering and replication support

The architecture is designed to grow incrementally while maintaining backward compatibility and operational simplicity.

Database Schema Reference

μNet uses a SQLite database with SeaORM for data persistence. The schema is designed with a clear separation between desired state (user-configured network topology) and derived state (real-time data from SNMP polling).

Overview

The database consists of two main categories of tables:

  • Desired State Tables: Store user-defined network topology and configuration
  • Derived State Tables: Store real-time operational data collected via SNMP

This separation ensures that configuration remains stable while allowing operational data to be updated frequently.

Core Tables

Locations

Physical or logical locations for organizing network devices in a hierarchical structure.

ColumnTypeConstraintsDescription
idTEXTPRIMARY KEY, NOT NULLUnique identifier
nameTEXTNOT NULLHuman-readable location name
typeTEXTNOT NULLType of location (datacenter, building, floor, rack, etc.)
pathTEXTNOT NULL, UNIQUEHierarchical path for tree navigation
parent_idTEXTFOREIGN KEYReference to parent location
descriptionTEXTOptional description
addressTEXTPhysical address or location details
coordinatesTEXTGPS coordinates or position data
custom_dataTEXTJSON string for custom attributes
created_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMPCreation timestamp
updated_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMPLast update timestamp

Indexes:

  • idx_location_path (unique on path)
  • idx_location_parent (on parent_id)

Nodes

Network devices and their static configuration attributes.

ColumnTypeConstraintsDescription
idTEXTPRIMARY KEY, NOT NULLUnique identifier
nameTEXTNOT NULLNode name (typically hostname)
fqdnTEXTFully qualified domain name
domainTEXTDNS domain
vendorTEXTNOT NULLDevice vendor (see Vendor enum)
modelTEXTNOT NULLDevice model number
roleTEXTNOT NULLDevice role (see DeviceRole enum)
lifecycleTEXTNOT NULLLifecycle stage (see Lifecycle enum)
serial_numberTEXTDevice serial number
asset_tagTEXTAsset tag for inventory tracking
location_idTEXTFOREIGN KEYReference to location
management_ipTEXTPrimary management IP address
descriptionTEXTOptional description
custom_dataTEXTJSON string for custom attributes
created_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMPCreation timestamp
updated_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMPLast update timestamp

Indexes:

  • idx_node_name (on name)
  • idx_node_fqdn (on fqdn)
  • idx_node_location (on location_id)
  • idx_node_role (on role)
  • idx_node_lifecycle (on lifecycle)

Network connections between devices, including both internal links and internet circuits.

ColumnTypeConstraintsDescription
idTEXTPRIMARY KEY, NOT NULLUnique identifier
nameTEXTNOT NULLHuman-readable link name
node_a_idTEXTNOT NULL, FOREIGN KEYReference to first node (required)
interface_aTEXTNOT NULLInterface name on first node
node_b_idTEXTFOREIGN KEYReference to second node (optional for internet circuits)
interface_bTEXTInterface name on second node
capacityBIGINTLink capacity in bits per second
utilizationREALCurrent utilization as percentage (0.0-1.0)
is_internet_circuitINTEGERNOT NULL, DEFAULT 0Whether this is an internet circuit (1) or internal link (0)
circuit_idTEXTProvider circuit identifier
providerTEXTService provider name
descriptionTEXTOptional description
custom_dataTEXTJSON string for custom attributes
created_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMPCreation timestamp
updated_atTEXTNOT NULL, DEFAULT CURRENT_TIMESTAMPLast update timestamp

Indexes:

  • idx_link_name (on name)
  • idx_link_node_a (on node_a_id)
  • idx_link_node_b (on node_b_id)
  • idx_link_circuit_id (on circuit_id)

Vendors

List of supported network equipment vendors.

ColumnTypeConstraintsDescription
nameTEXTPRIMARY KEY, NOT NULLVendor name

Seeded vendors include Cisco, Juniper, Arista, and others. Use the CLI to manage the list:

# List vendors
unet vendors list
# Add vendor
unet vendors add CustomVendor
# Remove vendor
unet vendors delete CustomVendor

Derived State Tables

Node Status

Real-time operational status and metrics for network nodes, populated by SNMP polling.

ColumnTypeConstraintsDescription
idTEXTPRIMARY KEY, NOT NULLUnique identifier
node_idTEXTNOT NULL, FOREIGN KEYReference to node table
last_updatedTEXTNOT NULLTimestamp of last status update
reachableBOOLEANNOT NULL, DEFAULT falseWhether node is reachable via SNMP
system_infoTEXTJSON containing system information (uptime, name, description)
performanceTEXTJSON containing performance metrics (CPU, memory)
environmentalTEXTJSON containing environmental data (temperature, fans)
vendor_metricsTEXTJSON containing vendor-specific metrics
raw_snmp_dataTEXTJSON containing raw SNMP response data
last_snmp_successTEXTTimestamp of last successful SNMP poll
last_errorTEXTLast error message encountered during polling
consecutive_failuresINTEGERNOT NULL, DEFAULT 0Number of consecutive failed polling attempts

Indexes:

  • idx_node_status_node_id (unique on node_id)
  • idx_node_status_last_updated (on last_updated)

Interface Status

Per-interface operational data and statistics from SNMP interface tables.

ColumnTypeConstraintsDescription
idTEXTPRIMARY KEY, NOT NULLUnique identifier
node_status_idTEXTNOT NULL, FOREIGN KEYReference to node_status table
indexINTEGERNOT NULLInterface index from SNMP ifTable
nameTEXTNOT NULLInterface name or description
typeINTEGERNOT NULLInterface type code from SNMP ifType
mtuINTEGERMaximum transmission unit in bytes
speedBIGINTInterface speed in bits per second
physical_addressTEXTPhysical MAC address of the interface
admin_statusTEXTNOT NULL, DEFAULT 'unknown'Administrative status (up/down/testing)
oper_statusTEXTNOT NULL, DEFAULT 'unknown'Operational status (up/down/testing/unknown/dormant/notPresent/lowerLayerDown)
last_changeINTEGERTime when interface last changed state
input_statsTEXTNOT NULLJSON containing input statistics (packets, bytes, errors)
output_statsTEXTNOT NULLJSON containing output statistics (packets, bytes, errors)

Indexes:

  • idx_interface_status_node_status_id (on node_status_id)
  • idx_interface_status_index (unique on node_status_id, index)

Polling Tasks

Configuration for SNMP polling tasks that collect operational data.

ColumnTypeConstraintsDescription
idTEXTPRIMARY KEY, NOT NULLUnique identifier
node_idTEXTNOT NULL, FOREIGN KEYReference to node table
targetTEXTNOT NULLSNMP target address or hostname
oidsTEXTNOT NULLJSON array of OIDs to poll
interval_secondsBIGINTNOT NULLPolling interval in seconds
session_configTEXTNOT NULLJSON containing SNMP session configuration
prioritySMALLINTNOT NULL, DEFAULT 128Task priority for scheduling
enabledBOOLEANNOT NULL, DEFAULT trueWhether task is currently enabled
created_atTEXTNOT NULLTask creation timestamp
last_successTEXTTimestamp of last successful poll
last_errorTEXTLast error message from polling
consecutive_failuresINTEGERNOT NULL, DEFAULT 0Number of consecutive failed polls

Indexes:

  • idx_polling_tasks_node_id (on node_id)
  • idx_polling_tasks_enabled (on enabled)

Enumerations

Device Role

Defines the network function of a device:

  • router - Network router
  • switch - Network switch
  • firewall - Firewall device
  • loadbalancer - Load balancer
  • accesspoint - Wireless access point
  • securityappliance - Network security appliance
  • monitor - Network monitoring device
  • server - Generic server
  • storage - Storage device
  • other - Other/unspecified device type

Lifecycle

Defines the operational state of a device:

  • planned - Device is planned but not yet deployed
  • implementing - Device is currently being implemented/deployed
  • live - Device is live and operational
  • decommissioned - Device is being decommissioned or is decommissioned

Vendor

Supported network equipment vendors:

  • cisco - Cisco Systems
  • juniper - Juniper Networks
  • arista - Arista Networks
  • paloalto - Palo Alto Networks
  • fortinet - Fortinet
  • hpe - HPE/Hewlett Packard Enterprise
  • dell - Dell Technologies
  • extreme - Extreme Networks
  • mikrotik - Mikrotik
  • ubiquiti - Ubiquiti
  • generic - Generic/unknown vendor

Schema Design Patterns

Primary Keys

All tables use text-based UUIDs as primary keys to ensure global uniqueness and enable distributed scenarios.

JSON Storage

Complex or flexible data is stored as JSON strings in columns like custom_data, system_info, and statistics fields. This allows for extensibility without schema changes.

Timestamps

All timestamps are stored as text in ISO 8601 format for consistency and readability.

Foreign Key Relationships

The schema maintains referential integrity through foreign key relationships:

  • Nodes → Locations (optional)
  • Links → Nodes (A-side required, B-side optional)
  • Node Status → Nodes (one-to-one)
  • Interface Status → Node Status (one-to-many)
  • Polling Tasks → Nodes (one-to-many)

Indexing Strategy

Indexes are created on:

  • Foreign key columns for efficient joins
  • Frequently queried columns (names, roles, status)
  • Unique constraints where needed

Usage Considerations

Data Separation

The schema enforces separation between:

  • Configuration data (locations, nodes, links) - changes infrequently
  • Operational data (status tables) - updated frequently via SNMP

Extensibility

Custom fields can be added via:

  • custom_data JSON columns on core entities
  • Additional OIDs in polling tasks
  • Vendor-specific metrics in status tables

Performance

  • Derived state tables are optimized for frequent updates
  • Indexes support common query patterns
  • JSON storage provides flexibility without normalization overhead

Missing Fields?

If you need additional fields for your network automation use case, consider:

  1. Custom Data Fields: Use the custom_data JSON columns for entity-specific extensions
  2. New Enums: Extend the vendor, role, or lifecycle enums if needed
  3. Additional Tables: For complex relationships not covered by existing schema
  4. SNMP Extensions: Add new OIDs to polling tasks for additional metrics

Open a pull request with your proposed schema changes and use cases to help expand μNet's capabilities.

μNet Roadmap

Current Status: ~60% complete. See /STATUS.md for detailed development status and immediate next steps.

This document outlines the planned features and release timeline for μNet.

Current Status (v0.1.0)

μNet has CLI, API, policy engine, and SNMP infrastructure implemented. Current development focuses on completing API endpoints and background task integration. See /STATUS.md for detailed completion status.

Planned Features

Milestone 4: Template Engine

  • Configuration Templates: Jinja2-compatible templating system
  • Partial Configuration Management: Template-match headers for selective config management
  • Intelligent Diffing: Hierarchical configuration comparison
  • CLI Commands:
    • unet template render --node <id> --template <file>
    • unet template diff --node <id> --template <file>
    • unet template validate --path <dir>

Milestone 5: Advanced SNMP CLI

  • SNMP Polling Controls: CLI commands to manage background polling
  • Device Discovery: Automatic capability detection
  • Historical Metrics: Time-series data storage and retrieval
  • CLI Commands (planned):
    • unet nodes polling start/stop/status
    • unet nodes history --metrics --since 1d
    • unet nodes compare <node1> <node2>

Milestone 6: Configuration Push

  • Safe Configuration Deployment: Push generated configs to devices
  • Rollback Mechanisms: Automatic recovery from failed changes
  • Change Management: Audit trails and approval workflows

Future Enhancements

Enhanced CLI Experience

  • unet init --with-examples - Quick setup with sample data
  • unet locations tree - Hierarchical location display
  • Advanced filtering and output formatting
  • Interactive mode for guided operations

Web UI

  • Browser-based interface for non-CLI users
  • Visual topology maps
  • Policy authoring assistance
  • Real-time monitoring dashboards

Enterprise Features

  • Authentication & Authorization: Token-based access control
  • Multi-tenancy: Support for multiple organizations
  • Integration APIs: Webhooks and event streaming
  • High Availability: Clustering and replication

Advanced Policy Features

  • Policy Libraries: Pre-built compliance templates
  • Custom Actions: Extensible action framework
  • Conditional Logic: More sophisticated rule evaluation
  • Policy Testing: Dry-run and simulation capabilities

Network Discovery

  • Topology Auto-Discovery: LLDP/CDP-based link detection
  • Device Fingerprinting: Automatic vendor/model identification
  • Network Mapping: Visual topology generation

Release Sequence

  • v0.2.0: Template Engine + Configuration Generation
  • v0.3.0: Advanced SNMP Monitoring + CLI
  • v0.4.0: Configuration Push + Rollback
  • v1.0.0: Web UI

Contributing to the Roadmap

We welcome input on prioritization and feature requests:

  • Feature Requests: GitHub Issues with enhancement label
  • Architecture Discussions: GitHub Discussions
  • Implementation Help: Check good first issue labels on planned features

Design Principles for Future Features

All new features will maintain μNet's core principles:

  • Progressive Adoption: You can adopt new capabilities gradually
  • Safety First: Always show what changes before applying them
  • Single Binary: Minimal deployment complexity
  • Multi-vendor: Work consistently across network vendors
  • Git Integration: Version control for all configuration artifacts