Conversation
Hide the Update button when a daemon is unreachable since it cannot be upgraded without connectivity. This prevents the Retry Connection and Update buttons from rendering on top of each other.
- Change display logic from OR to AND so checklist hides when all steps complete OR when user dismisses - Remove allComplete guard on dismiss button so users can dismiss at any time - Remove dead "Setup complete" heading branch (unreachable)
- Add uniqueness check in start_session() using discovery_sessions map - Return 409 Conflict when a session is already running for a discovery - Change start_session() return type from anyhow::Error to ApiError - Sync discovery_sessions removal in all session lifecycle methods: update_session, cancel_session, clear_sessions_for_daemon, cleanup_old_sessions, cleanup_stalled_sessions - Add 409 response to start_session OpenAPI spec
- Add with_snmp() helper to set sys_descr, sys_object_id, sys_location, sys_contact, and chassis_id on host tuples from create_host() - Populate SNMP fields on 13 hosts: firewalls (pfSense, FortiGate), switches (UniFi, Arista), hypervisors (Proxmox), NAS (TrueNAS, Synology), APs (UniFi U6-Pro/LR/Lite), and printer (HP LaserJet) - Add snmp_credential_id (Network Devices) to 3 APs that were missing it - Set chassis_id on switches and APs for LLDP deduplication - VMs, containers, and software servers remain without SNMP (realistic)
- Replace TelemetryOperation enum with BillingOperation (10 variants) and OnboardingOperation (14 variants, no legacy) - Replace TelemetryEvent struct with BillingEvent and OnboardingEvent - Update Event enum: Telemetry → Billing + Onboarding - Update EventFilter, EventBus publish methods, and all subscribers - Graceful JSONB deserialization drops legacy variants silently - Remove legacy guards (PersonalPlanSelected, CommercialPlanSelected) - Update frontend schema and 4 Svelte components
- Add /share/{*rest} route to public_share_app serving index.html
without the frame-ancestors 'self' header that blocked embedding
- Only share pages are affected; all other SPA pages retain
clickjacking protection via protected_app's fallback
- API-level embed enforcement (billing gate, domain restrictions)
remains unchanged
…ipts - Extract ALLOWED_LOGO_DOMAINS constant to definitions/mod.rs for shared use - Build CSP img-src dynamically from ALLOWED_LOGO_DOMAINS (keeps test + CSP in sync) - Allow PostHog analytics (ph.scanopy.net) in script-src and connect-src - Allow 'unsafe-inline' in script-src for SvelteKit adapter-static inline scripts
- Add chrono-tz dependency and timezone field to RunType::Scheduled - Use JobBuilder with .with_timezone() for DST-correct cron evaluation - Validate timezone on create/update, reschedule on timezone change - Replace frequency days/hours UI with day-of-week toggles + time picker - Add raw cron editor toggle for advanced users - Add timezone selector defaulting to browser timezone - Add TimeInput.svelte component following DateInput pattern - Update schedule card to show "Mon, Wed at 03:00 (America/New_York)" - Backward compatible: existing records without timezone default to UTC
- Replace single-origin CORS with mirror_request() to reflect any requesting origin, enabling browser-based API key consumers from arbitrary domains - Use AllowCredentials::predicate() to send credentials header only for app.scanopy.net and demo.scanopy.net origins (session cookies) - Give health endpoint its own permissive CORS layer (Any origin, GET only) so marketing site and uptime monitors can reach it - Remove unnecessary cors.clone() since cors is now used only once
- Add scan_subnet_streaming() to sendarp.rs that returns mpsc::Receiver, matching the broadcast ARP interface for the discovery pipeline - Wire up SendARP streaming in arp/mod.rs so Windows daemons with use_npcap=false can scan subnets - Fix Npcap fallback: when use_npcap=true but broadcast fails, fall through to SendARP instead of returning the error
…ation + OnboardingOperation
- Host modal: all 7 tabs always visible, progressively unlocked via furthestReached as user advances through wizard steps. Data-dependent tabs (IF Entries, Virtualization) disabled based on data availability. - Group modal: all 3 tabs always visible, same progressive unlock pattern. - Both modals use enabledTabs derivation for navigation, skipping disabled tabs when clicking Next/Back. - Edit mode: all wizard-step tabs enabled (data-dependent tabs still conditional). Matches existing daemon modal pattern.
- Add hidden `website` field to RegisterRequest (backend + frontend) - If filled, return fake 200 success without creating user/org/session - Log blocked attempts with IP, email, and honeypot value - Hidden input uses off-screen positioning, aria-hidden, tabindex=-1
- Wrap SnmpQueryCredential.community in redact::Secret<String> so it is redacted by default in Debug output, serde serialization, SSE streams, and all API responses - Add to_daemon_value()/to_exposed_value() for the single code path that needs plaintext: HTTP transmission to the daemon for SNMP queries - Remove sanitized() chain — no longer needed since Secret<String> handles redaction at the type level
- Wrap day-of-week buttons in form.Field for Svelte 5 reactivity (field.state.value triggers re-render, form.state.values did not) - Use bail_validation! for invalid timezone (returns 400 not 500) - Collapse if-let per clippy collapsible_if lint
- Use wizardSteps array for last-step detection instead of enabledTabs length (enabledTabs only had 1 item at furthestReached=0, causing immediate submit instead of advancing) - IF Entries tab now always enabled in edit mode (shows empty state message when no data); still disabled in create mode without data
…c::string::String] Custom serialize_with function matches the convention used by SnmpCredentialBase's redact_secret serializer.
@const inside {#each} evaluates once and never re-evaluates when field.state.value changes. Replaced with isDaySelected() and toggleDay() helper functions that read field.state.value on each render, allowing Svelte 5 to track the reactive dependency.
- Create OsSelector.svelte with OS button group, Linux binary/docker sub-toggle, and FreeBSD/OpenBSD unsupported warnings with PostHog feature-request buttons - Update InstallStep.svelte and DaemonUpgradeModal.svelte to use OsSelector, eliminating ~60 lines of duplicated markup each - Add i18n keys for upgrade-specific labels (upgradeDownload, upgradeRestartProcess, upgradeRestartSystemd)
The previous order (download, then restart) doesn't make sense for macOS/Windows where no service manager handles the process. Reorder to: (1) stop daemon, (2) download new version, (3) start daemon. Linux systemd stays as download + restart since systemctl handles it.
- Add copyable stop/start commands for macOS (pkill/scanopy-daemon) and Windows (Stop-Process/exe) instead of generic text - Include --name flag in start commands for custom-named daemons - Add "config preserved" info note so users know no flags are needed - Show actual target version in Docker pinned image tag (v0.14.9) instead of :latest
Linux binary previously used download + systemctl restart, which assumed a default service name and didn't handle custom daemon names. Now all platforms (Linux, macOS, Windows) use the same 3-step flow: stop daemon, download update, start daemon — with --name flag included when the daemon has a custom name.
- Always include --name flag in start commands for all platforms, since users may run multiple daemons on one machine - Unify Linux binary upgrade to same stop/download/start flow as macOS and Windows (removes systemd-specific restart) - Make upgrade modal deep-linkable via ?modal=upgrade-daemon&id=<id>
Show the "config is preserved" info once at the top of the upgrade modal rather than repeated at the bottom of each OS section.
Adds an InlineInfo note to each binary upgrade section (Linux, macOS, Windows) warning users with multiple daemons that they share the same binary and need to restart each one individually. Includes a platform-specific command to list daemon config directories. Also bumps modal size from lg to xl.
Replace clunky InlineInfo + CodeContainer combo with a native <details> element. When collapsed, shows a single clickable line "Running multiple daemons on this machine?" that most users skip. When expanded, shows explanation, platform-specific config listing command, and link to docs at scanopy.net/docs/multiple-daemons/.
Move collapsible details between "Step 3" label and its code container so it reads as a sub-note of the step. Style summary as text-tertiary for visual distinction from step headers. Replace arrow entity with ExternalLink icon from lucide-svelte, matching BlockerFlow convention.
Replace {@html} docs links with a DocsHint component that renders the
lucide ExternalLink icon natively. i18n keys now use a {link} placeholder
so translators can position the link freely in each language's sentence
structure. Removes .docs-hint CSS from InstallStep and AdvancedStep.
Also updates the multiple daemons question to be use-case oriented:
"Scanning multiple networks from a single machine?"
Adds docs hint for multiple daemons to the install step alongside
existing multi-VLAN and macvlan hints.
Prevents checkboxes from being interleaved with text/number inputs in the 2-column grid, keeping the layout visually clean.
…mon_docsLink
Paraglide was interpreting {link} as a parameter and replacing it with
undefined. Switch to %link% which paraglide ignores, letting DocsHint
split on it instead.
Extract common_docsLink ("For more details, see the %link%.") for
generic docs hints. Remove redundant daemons_docsDockerProxy and
daemons_docsMultipleDaemons text keys. Keep macvlan question format
since it adds useful context.
… step
The create daemon modal needs contextual framing ("Scanning multiple
networks from a single machine?") since the user may not be aware of the
feature. The upgrade modal keeps common_docsLink since the user has
already expanded the multi-daemon details section.
- Bump svelte 5.53.2 → 5.53.6 (fixes XSS in SSR hydration markers and contenteditable binding) - Bump minimatch 10.2.2 → 10.2.4 (fixes ReDoS in matchOne) - Move isLastWizardStep declaration before first use in GroupEditModal - Add email campaign docs to gitignore
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.