Conversation
- Add useServicesCacheQuery() hook to read from hosts-populated cache
- Update 15 components to use cache query instead of useServicesQuery()
Root cause: Query key mismatch between hosts query (sets data at
['services']) and services query (reads from ['services', {params}]).
This caused components to make separate API calls, receiving only
50 services (backend default limit) instead of all services.
Affected components now correctly read from the cache populated by
useHostsQuery, ensuring all services are available for filtering
by host_id.
- Fix page size not persisting across refresh by notifying parent component when restoring state from localStorage - Fix "X out of Y" count showing reversed values (e.g., "41 out of 20") by using server's total_count for both values in single-page case - Add tests for pagination count calculation logic
- Add csv crate (1.3) dependency - Extend Entity trait with CsvRow, csv_headers(), to_csv_row() - Create generic export_csv_handler in shared/handlers/csv.rs - Add crud_export_csv_handler! macro for OpenAPI documentation - Implement CSV export for 16 entities: Host, Subnet, Interface, Port, Service, Binding, Group, Tag, Daemon, User, Share, Network, Discovery, Topology, UserApiKey, DaemonApiKey - Exclude sensitive fields from CSV output (passwords, API keys, secrets) - Wire up /export/csv routes with Viewer permission requirement
- Renamed config field from interface_filter to interfaces to match CLI arg - Added explicit comma-split parsing for env var (Figment doesn't auto-split) - Added regression test to prevent future breakage Fixes #463
- Add entities.ts with EntityDiscriminants to API path mapping - Add csvExport.ts utility for triggering CSV downloads - Add onCsvExport callback prop to DataControls component - Add CSV button with loading state next to filter button - Wire up CSV export in 7 tab components (Host, Service, Subnet, Group, Tag, Daemon, Network) - Host and Service tabs pass server-side filters to export - Other tabs export all records
- Add scan_rate_pps config (default 500) to stagger TCP connection starts - Connections now start 2ms apart instead of bursting simultaneously - Add probe_host_capacity() to determine optimal batch size per host - Batch sizes now adaptive: 128-400 based on host response characteristics - Prevents SYN flood that was overwhelming network device listen queues Fixes #455
- Add 4 new endpoints for granular topology updates:
- POST /{id}/node-position - drag operations
- POST /{id}/node-resize - resize operations
- POST /{id}/edge-handles - edge reconnect operations
- POST /{id}/metadata - name/parent updates
- Reduces payload from ~6-7MB to ~100-200 bytes (99.99% reduction)
- Frontend updated to use new lightweight mutations
- Fixes HTTP 413 errors on large topologies
Fixes #451
- Add new Inbound mode where server initiates all connections to daemon - Daemon no longer needs to make outbound connections in this mode - Add DaemonStateProvider trait and EntityBuffer for daemon-side state - Add DaemonDataProcessor trait and DaemonPoller for server-side polling - Add new daemon endpoints: GET /api/status, /api/discovery/progress, /api/discovery/results - Add migration for daemon API key linking - Deprecate Push/Pull as aliases for Outbound mode - Full architecture documented in TASK.md Fixes #438
Backend: - Add SnmpCredential entity with organization-scoped credential storage - Add IfEntry entity for SNMP ifTable data (physical/logical interfaces) - Extend Host with SNMP system MIB fields (sysDescr, sysObjectID, etc.) - Extend Network with default SNMP credential reference - Add credential resolution: host override → network default → none - Implement neighbor discovery via LLDP/CDP in IfEntry - Require Admin permission for SNMP mutations - Block non-owners from SNMP changes in demo mode Daemon: - Add SNMP client utilities for SNMPv2c polling - Integrate SNMP discovery into network scan pipeline - Collect ifTable entries and system MIB during host discovery Frontend: - Add SNMP Credentials management tab in organization settings - Add SNMP credential selector to Network modal - Add SNMP tab to Host modal (credential override + system info) - Add IfEntries tab to Host modal (read-only interface list) - Disable SNMP fields for non-owners in demo organizations Migrations: - 20260116010000: snmp_credentials table + networks.snmp_credential_id - 20260116020000: Host SNMP fields (sys_*, chassis_id, credential FK) - 20260116030000: if_entries table with neighbor resolution
- Add ServerPoll mode where server initiates connections to daemons (for daemons that cannot make outbound connections) - Implement daemon provisioning endpoint with API key generation - Add entity buffer for accumulating discovered entities in ServerPoll mode - Create polling loop with circuit breaker (marks unreachable after failures) - Add retry-connection endpoint to reset unreachable daemons - Consolidate poller.rs and processor.rs into service.rs - Add event subscriber for discovery start/cancel in ServerPoll mode - Rename is_reachable to is_unreachable (cleaner default semantics) - Add get_from_daemon/post_to_daemon helpers with built-in retry - Reduce backon delays from 30-240s to 5-30s for faster recovery - Remove unused EntityBuffer methods (clear_created, drain_pending) - Remove unused DaemonApiClient methods (post_raw, post_empty_raw) - Update UI with daemon mode selection and retry connection button
…erpoll implementation
- Add beszel_agent.rs: Port 45876/tcp detection for Beszel monitoring agent - Add zabbix_agent.rs: Port 10050/tcp detection for Zabbix monitoring agent - Both use port-only detection with medium confidence
- Add BACnet variant to PortType enum (UDP 47808) - Add test_bacnet_service() UDP probe function in scanner - Create BACnet service definition (IoT category) - Wire BACnet probe into scan_udp_ports()
- Appwrite: backend-as-a-service platform (ports 80/443) - Prometheus Node Exporter: hardware/OS metrics (port 9100) - Nvidia GPU Exporter: GPU metrics for Prometheus (port 9835) - MikroTik: RouterOS network devices (port 80) - OpenSpeedTest: self-hosted speed test (ports 3000/3001) - Dockge: Docker compose stack management (port 5001) - NCPA Agent: Nagios cross-platform agent (port 5693) - Roborock Vacuum: IoT robot vacuum (port 58867 + MAC vendor) - Ubiquiti Discovery: device discovery service (UDP 10001 + MAC vendor) Also adds ROBOROCK vendor constant to patterns.rs. Closes #471, #439, #417, #414, #413, #366, #470, #337
ServerPoll discovery was stalling at ~70% progress with "no updates received
from daemon for more than 5 minutes". Two issues were identified and fixed:
1. Terminal payload not persisted for ServerPoll mode:
- Added `terminal_payload` field to DaemonDiscoveryService
- Store terminal state (Complete/Failed/Cancelled) before clearing session
- Modified get_progress() to return terminal payload when no active session
- Allows server to poll and receive final state even after session ends
2. Test SSE stream catching wrong session failures:
- Modified run_discovery() to accept optional session_id parameter
- When filtering by session_id, ignores updates from other sessions
- Prevents test from catching stalled session errors from DaemonPoll
daemon when waiting for ServerPoll daemon's discovery
Also added CancellationToken to await_subnet() and await_host() methods
to enable fast cancellation during ServerPoll entity confirmation waits.
HubSpot Metrics Sync: - Create HubSpotMetricsSubscriber to update scanopy_network_count, scanopy_host_count, and scanopy_user_count in HubSpot when entities are created or deleted - Register subscriber in ServiceFactory with access to entity services - Skip sync if company doesn't exist yet (prevents duplicate companies due to HubSpot's eventual consistency during registration) - Look up org_id via network for host events (hosts only have network_id) Enterprise Inquiry Form: - Switch from CRM API to HubSpot Forms API for enterprise inquiries - Forms API triggers workflows and email notifications, unlike CRM API which only creates/updates records - Add HubSpotFormField type and submit_enterprise_inquiry_form() method - Hard-code portal ID (50956550) and form GUID for enterprise inquiries
The port scan batch size was calculated independently from concurrent host scans, leading to FD exhaustion. get_optimal_port_batch_size() returned ~1000 based on total FDs, while get_optimal_concurrent_scans() calculated port_batch=33 considering concurrent hosts but only logged it. The fix: - Add ScanConcurrencyParams struct to return both concurrent_scans and port_batch_size together - Update get_optimal_concurrent_scans to return the struct and take port_batch_config as parameter - Remove standalone get_optimal_port_batch_size which gave wrong values - Update network.rs and docker.rs to use the coordinated calculation Before: Controller initialized with 200, FD exhaustion within seconds After: Controller initialized with FD-safe value (e.g., 33)
- bindings/handlers.rs: Add network_id scoping to binding conflict validation, preventing cross-network information leakage - daemons/service.rs: Use new_for_daemon_poller_system_job() which filters by mode and reachability at the DB level instead of in memory - shared/storage/generic.rs: Use new_from_entity_id() in get_by_id()
- bindings/handlers.rs: Add network_id scoping to binding conflict validation, preventing cross-network information leakage - daemons/service.rs: Use new_for_daemon_poller_system_job() which filters by mode and reachability at the DB level instead of in memory - shared/storage/generic.rs: Use new_from_entity_id() in get_by_id()
HubSpot: - Refactor HubSpotService to accept entity services in constructor - Remove HubSpotMetricsSubscriber (metrics sync moved to service) - Add dual submission for enterprise inquiries (Form API + CRM API) - Add hutk cookie and IP address tracking for form submissions Onboarding: - Add use_case, company_size, job_title to pending setup state - Simplify daemon setup to single active setup (not accumulating) - Merge use_case from onboarding step into setup data - Fix scrollable content layout in UseCaseStep Telemetry: - Add FirstUserApiKeyCreated event when first API key is created Config: - Add port_scan_batch_size daemon config option (CLI + env + UI) Tests: - Add SNMP credential CRUD integration tests - Add Discovery CRUD integration tests
Backend - Daemon Discovery: - Simplify file descriptor budget calculation by removing ConcurrentPipelineOps abstraction; calculate deep scan concurrency based only on ARP subnet count - Streamline network scan pipeline in daemon discovery service Backend - Service Definitions: - Fix acronym casing: DHCP Server, DNS Server, HP Printer (with migration) - Add SNMP service category and move SNMP service to it - Update Roborock Vacuum logo URL (Brandfetch blocked hotlinking) - Add service ID migration allowlist in tests for intentional renames - Add User-Agent to logo URL test to avoid CDN bot detection Backend - Host Service: - Merge SNMP fields (sys_descr, sys_object_id, sys_location, sys_contact, management_url, chassis_id) during discovery upsert Backend - Topology: - Preserve deleted entity data when pending removals exist so conflict modal can display entity names Backend - SNMP Credentials: - Add tags field support with entity_tags junction table hydration - Add sanitized() method to redact community strings in EntitySource to prevent credential leakage in API responses Frontend - Host Edit Modal: - Remove onCreateAndContinue flow, simplify delete callback signature - Read ifEntries from query cache (read-only, populated by discovery) - Remove EntityMetadataSection from details tab Frontend - SNMP: - Add tag picker to SNMP credentials card and edit modal - Remove beta tag from SNMP feature Frontend - i18n: - Remove 11 unused translation keys - Update ifEntries terminology to "ifTable Entries" - Add test allowlists for context-specific duplicates and single-word keys Frontend - Shared Components: - Redesign CodeContainer expand/collapse UI - Simplify EntityMetadataSection (remove ID/timestamp display) Cleanup: - Delete unused scripts/create_test_hosts.sh - Regenerate API schema
Fixes CI hang in promote_to_latest workflow where npx would attempt to download vite-node on-the-fly and stall waiting for confirmation.
- Add paraglide-js compile to npm run check script - Remove generated paraglide files from git tracking - Add /src/lib/paraglide/ to .gitignore
mayanayza
added a commit
that referenced
this pull request
Feb 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.