Skip to content

refactor: cut dead code, redundant parsers, and unused frontend deps - #252

Open
s0up4200 wants to merge 5 commits into
developfrom
refactor/ponytail-audit-cuts
Open

refactor: cut dead code, redundant parsers, and unused frontend deps#252
s0up4200 wants to merge 5 commits into
developfrom
refactor/ponytail-audit-cuts

Conversation

@s0up4200

@s0up4200 s0up4200 commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Repo-wide over-engineering audit. No behavior change: 80 insertions, 1393 deletions.

Backend drops the unused internal/broadcaster package and its pass-through wrapper (the real wiring is a plain func value), three dead interfaces, some unused query helpers, and a duplicate getMigrationVersion. The tailscale Client interface and its two identical wrapper structs collapse into a type alias for local.Client, which both already wrapped. The batch traceroute parsers go too — there is one exec path and it uses the streaming parser, whose parseHopLine already handles Windows and carries its own IPv6 test. Seven config knobs that were parsed, defaulted and written to the generated TOML but never read are gone along with their README entries; unknown keys are ignored on decode, so existing config files keep working. tsaddr.IsTailscaleIP replaces a hand-rolled CIDR check, and stdlib crypto/rand.Text replaces GenerateSecureToken, dropping four error branches — the session secret concatenates two calls to keep its previous ~256 bits.

Frontend removes eight dependencies: @mui/material plus its two emotion peers (used for a single Container that Tailwind classes replace exactly), @headlessui/react (zero imports), and four @fortawesome packages covering six icons react-icons already provides. Bundle drops 164 kB, 50 kB gzipped.

Verified: go build, go vet, go test ./... green; tsc --noEmit clean; pnpm build succeeds; lint is 25 problems, identical to develop. UI checked in a browser against the running binary — the replaced container measures max-width 1536px, 24px gutters, border-box, centering exactly, matching MUI's Container maxWidth="xl". Cross-compiles clean on darwin, linux, windows and freebsd.

Draft because two icon swaps (Linux/Apple/OpenID/Laptop) sit behind auth or need configured agents, so they are covered by typecheck and build but not visually confirmed.

Summary by CodeRabbit

  • New Features

    • Added optional update notifications, configurable through settings or environment variables.
    • Added public and account-level theme configuration, including synchronized browser theme colors.
    • Traceroute results now update progressively and may stop early after repeated timeouts.
    • ntfy notifications now include titles and support non-TLS self-hosted servers.
  • Improvements

    • Simplified configuration options and documentation.
    • Updated interface icons and styling for a more consistent appearance.
    • Speed test records now expose completion and scheduling status.

Repo-wide over-engineering audit. No behavior change.

Backend: delete the unused internal/broadcaster package and its
pass-through wrapper (the real wiring is a plain func value), the dead
TestRunner/ProgressBroadcaster/UserService interfaces, unused query
helpers, and a duplicate getMigrationVersion. Collapse the tailscale
Client interface and its two identical wrapper structs into a type alias
for local.Client, which they both already wrapped. Drop the redundant
batch traceroute parsers: there is one exec path and it uses the
streaming parser, whose parseHopLine already handles Windows and carries
its own IPv6 test.

Remove seven config knobs that were parsed, defaulted and written to the
generated TOML but never read, along with their README entries. Unknown
keys are ignored on decode, so existing config files keep working.

Swap the hand-rolled Tailscale CIDR check for tsaddr.IsTailscaleIP from
the tailscale dep already in the tree, and GenerateSecureToken for
stdlib crypto/rand.Text, which drops four error branches. The session
secret concatenates two calls to keep its previous ~256 bits.

Frontend: drop @mui/material and its two emotion peers, used for a
single Container that Tailwind classes replace exactly; @headlessui/react,
which had no imports; and four @FortAwesome packages covering six icons
that react-icons already provides. Bundle drops 164 kB (50 kB gzipped).
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR reduces obsolete Go and frontend APIs, adds update-checking and licensing/theme server wiring, streams traceroute parsing, revises Tailscale and ntfy behavior, simplifies migration configuration, updates frontend icon and theme handling, and refreshes configuration documentation.

Changes

Netronome cleanup

Layer / File(s) Summary
Configuration, authentication, and server wiring
.golangci.yml, config/*, internal/auth/*, internal/server/*
Configuration fields and environment mappings were reduced or extended, token generation changed, authentication helpers were removed, and licensing/update routes were added.
Database and migration API simplification
internal/database/*, pkg/migrator/*
Database helpers, test helpers, and migration APIs were removed; migration parsing uses strconv, and initial schema application uses the first migration.
Traceroute and Tailscale runtime changes
internal/speedtest/*, internal/tailscale/*, internal/monitor/*, internal/utils/tailscale.go
Traceroute output is parsed incrementally with progress events and early termination; Tailscale clients and IP detection use updated types and libraries.
Frontend API and utility contracts
web/src/api/*, web/src/types/*, web/src/utils/*, web/src/components/speedtest/traceroute/*
Unused exports were removed, SpeedTest gained completion and scheduling fields, and theme/time utilities were adjusted.
Frontend UI and documentation
web/*, README.md
Icons and layout wrappers were updated, public themes are applied in public views, dependencies were reduced, and configuration references were refreshed.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: go, web

Poem

I hopped through routes where traceroutes stream,
And nudged bright themes from a server dream.
Old APIs rested beneath the moon,
While ntfy titles arrived in tune.
Config keys danced, migrations grew neat—
This rabbit declares the cleanup complete!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description summarizes the change, but it does not follow the required template sections or checklist items. Rewrite it using the repo template with Summary, Why, Testing, Screenshots, and Checklist sections, and fill in the required test/check items.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main refactor and dependency cleanup.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/ponytail-audit-cuts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

s0up4200 added 3 commits July 28, 2026 15:37
Follow-up to the audit. Whole-module deadcode analysis reported these as
unreachable from any entry point including tests, and each was confirmed
by grep to have no caller.

Dropped auth.HashPassword and auth.CheckPassword, dead duplicates of the
bcrypt path that database/user.go actually uses; OIDCConfig.AuthURL,
superseded by AuthURLWithPKCE; config.GetDefaultConfigPath, which
DefaultConfigPaths replaced; migrations.ReadMigration;
notifications.MigrateDiscordWebhook; Server.SetPacketLossService;
web.BuildFrontend, which shelled out to pnpm and has no caller in Go,
the Makefile or CI; and two unused test helpers.

pkg/migrator loses its unreachable API surface: the WithTableName,
WithSchemaString and WithSchemaFile options, LoggerFunc, Migration.Id,
TableDrop, Exec, BeginTx, Pending, and migrateInitialSchemaOpt. Removing
the schema options makes the initialSchema and initialSchemaFile fields
dead, so those go too. tableName stays; it still has a default and is
read when building the version table.

Finally, migrations.parseInt was a hand-rolled strconv.Atoi. The two
agree on every input reachable here, including the empty string, which
both resolve to a zero version.
Third audit pass. Each type below appeared exactly twice in the tree,
as its own declaration and doc comment, with no other reference:
types.MonitorFullData, an 85-line vnstat export struct the handler
never used because it builds a map by hand; types.MonitorBandwidth,
which describes a table no migration creates; speedtest.IperfResult,
superseded by iperfEndData; and notifications.PacketLossNotification.

web/src/api/tailscale.ts had no importers. The packetloss history
cutover plan under docs/ shipped with 20 unticked boxes and absolute
paths from a local worktree; migration 021 shows the work landed.
scripts/check_vnstat_data.sh is referenced from nothing.

.golangci.yml pointed local-prefixes at github.com/autobrr/qui, so
import grouping never applied to this project.
Fourth audit pass, frontend side. The repo's knip.json turns off export
checking and ignores api/, utils/, types/ and constants/, so none of this
surfaces normally; it was found with a temporary config and then each
symbol was checked by hand.

Deleted 17 exports and types that had no reference anywhere:
getOIDCLoginUrl, getMonitorAgent, getThresholdOperatorLabel,
getEventCategoryIcon, SPRING_TRANSITION, SERVER_DISPLAY_INCREMENT,
getRTTColorClass, formatHopData, toggleDarkMode, hasManualPreference,
formatDate, convertUTCToTimezone, convertTimezoneToUTC,
formatUTCInTimezone, MonitorRefreshInterval, SpeedTestHistory and
SpeedUpdate. formatDate and SPRING_TRANSITION looked used but are
shadowed by separate local definitions in MonitorResultsTable and
TabNavigation.

Six more were exported yet only ever called inside their own file, so
they lose the export instead of being removed:
convertIperfServersToServerFormat, filterServers, sortServers,
flagEmojis, resetToSystemTheme and getEffectiveTimezone. Dropping the
last of the timezone converters left toZonedTime unused, so it comes off
the date-fns-tz import; the package stays for fromZonedTime and
formatInTimeZone.

pwa.d.ts declared virtual:pwa-register/react, which is never imported
because the app uses workbox-window directly; service-worker.d.ts
declared two interfaces nothing referenced. The EventRuleItem re-export
in the notifications barrel was unused, as the one consumer imports the
component directly.

Verified: tsc clean, built CSS byte-identical, lint unchanged at 25.
@s0up4200
s0up4200 marked this pull request as ready for review July 28, 2026 18:54

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
README.md (1)

784-787: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document removed configuration in docs/.

Add a migration note listing removed variables and their replacement or removal behavior; README updates alone do not meet the repository requirement.

As per coding guidelines, document configuration changes in docs/ when behavior changes.

Also applies to: 800-802, 819-820, 845-848

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 784 - 787, Document the removed configuration
variables shown in the README diff in the appropriate docs migration note,
including each variable’s replacement or explicit removal behavior. Keep the
README changes, but add the required documentation under docs/ so all affected
settings are covered.

Source: Coding guidelines

pkg/migrator/migrator.go (2)

222-245: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Keep the base migration and version record atomic.

migration.Run(m.db) executes outside tx, while the version row is written inside it. If version recording or commit fails, the schema change can persist without its migration record, causing the base migration to be attempted again. Require a transactional RunTx for the initial migration, or redesign Run to receive the active transaction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/migrator/migrator.go` around lines 222 - 245, Make the initial migration
path atomic with its schema-version update by removing or disallowing the
non-transactional migration.Run(m.db) branch for the base migration. Require
migration.RunTx(tx), or change the migration.Run contract to receive and use the
active transaction, while preserving the existing transactional
updateSchemaVersion flow.

190-218: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Propagate initial-schema commit failures.

This function has an unnamed return value, so return err evaluates before the deferred tx.Commit(). A commit failure is assigned only to the local err and the caller receives nil, reporting a failed base migration as successful. Use a named err result and apply the same correction to migrate.

Proposed fix
-func (m *Migrator) migrateInitialSchema(migration *Migration) error {
+func (m *Migrator) migrateInitialSchema(migration *Migration) (err error) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/migrator/migrator.go` around lines 190 - 218, Update migrateInitialSchema
and migrate to use named error return values so deferred transaction commit
failures are propagated to callers. Preserve the existing rollback and commit
logic, ensuring the deferred assignment to err is returned when either migration
function completes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/src/components/Footer.tsx`:
- Line 31: Preserve decorative SVG accessibility by adding aria-hidden="true" to
FaDiscord and SiReadme in web/src/components/Footer.tsx (lines 31 and 51), the
Apple/Linux icons in web/src/components/monitor/MonitorSystemInfo.tsx (lines
85-87), the OS icon returned by getOSIcon() and mobile kernel icons in
web/src/components/monitor/tabs/MonitorOverviewTab.tsx (lines 292-295 and
484-486), and the returned laptop icon abstraction in
web/src/utils/agentIcons.tsx (line 37).

---

Outside diff comments:
In `@pkg/migrator/migrator.go`:
- Around line 222-245: Make the initial migration path atomic with its
schema-version update by removing or disallowing the non-transactional
migration.Run(m.db) branch for the base migration. Require migration.RunTx(tx),
or change the migration.Run contract to receive and use the active transaction,
while preserving the existing transactional updateSchemaVersion flow.
- Around line 190-218: Update migrateInitialSchema and migrate to use named
error return values so deferred transaction commit failures are propagated to
callers. Preserve the existing rollback and commit logic, ensuring the deferred
assignment to err is returned when either migration function completes.

In `@README.md`:
- Around line 784-787: Document the removed configuration variables shown in the
README diff in the appropriate docs migration note, including each variable’s
replacement or explicit removal behavior. Keep the README changes, but add the
required documentation under docs/ so all affected settings are covered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f56df75-4514-48b8-bac5-d785f2d5c27b

📥 Commits

Reviewing files that changed from the base of the PR and between abcac5d and 86ae5b7.

⛔ Files ignored due to path filters (1)
  • web/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (52)
  • .golangci.yml
  • README.md
  • config/config.toml
  • docs/superpowers/plans/2026-04-09-packetloss-history-cutover.md
  • internal/auth/auth.go
  • internal/auth/oidc.go
  • internal/broadcaster/broadcaster.go
  • internal/config/config.go
  • internal/database/database.go
  • internal/database/database_test.go
  • internal/database/migrations/migrations.go
  • internal/database/user.go
  • internal/monitor/tailscale_discovery.go
  • internal/notifications/notifications.go
  • internal/server/auth.go
  • internal/server/auth_oidc.go
  • internal/server/server.go
  • internal/speedtest/iperf.go
  • internal/speedtest/progress_broadcaster.go
  • internal/speedtest/traceroute.go
  • internal/speedtest/traceroute_test.go
  • internal/speedtest/types.go
  • internal/tailscale/tailscale.go
  • internal/types/types.go
  • internal/utils/crypto.go
  • internal/utils/tailscale.go
  • pkg/migrator/migrator.go
  • scripts/check_vnstat_data.sh
  • web/build.go
  • web/package.json
  • web/src/api/auth.ts
  • web/src/api/monitor.ts
  • web/src/api/notifications.ts
  • web/src/api/tailscale.ts
  • web/src/components/Footer.tsx
  • web/src/components/Main.tsx
  • web/src/components/auth/Login.tsx
  • web/src/components/monitor/MonitorSystemInfo.tsx
  • web/src/components/monitor/tabs/MonitorOverviewTab.tsx
  • web/src/components/settings/notifications/index.ts
  • web/src/components/speedtest/traceroute/constants/tracerouteConstants.ts
  • web/src/components/speedtest/traceroute/utils/serverUtils.ts
  • web/src/components/speedtest/traceroute/utils/tracerouteUtils.ts
  • web/src/constants/monitorRefreshIntervals.ts
  • web/src/types/pwa.d.ts
  • web/src/types/service-worker.d.ts
  • web/src/types/speedtest.ts
  • web/src/types/types.ts
  • web/src/utils/agentIcons.tsx
  • web/src/utils/countryFlags.ts
  • web/src/utils/darkMode.ts
  • web/src/utils/timeSettings.ts
💤 Files with no reviewable changes (28)
  • config/config.toml
  • scripts/check_vnstat_data.sh
  • internal/broadcaster/broadcaster.go
  • internal/speedtest/progress_broadcaster.go
  • web/src/types/pwa.d.ts
  • internal/utils/crypto.go
  • web/src/api/tailscale.ts
  • docs/superpowers/plans/2026-04-09-packetloss-history-cutover.md
  • internal/auth/oidc.go
  • web/src/api/auth.ts
  • web/src/types/service-worker.d.ts
  • web/src/api/monitor.ts
  • web/package.json
  • web/src/types/speedtest.ts
  • web/src/api/notifications.ts
  • web/build.go
  • web/src/types/types.ts
  • internal/speedtest/iperf.go
  • internal/server/server.go
  • internal/speedtest/types.go
  • internal/database/database_test.go
  • internal/types/types.go
  • web/src/components/speedtest/traceroute/utils/tracerouteUtils.ts
  • internal/database/database.go
  • web/src/components/speedtest/traceroute/constants/tracerouteConstants.ts
  • internal/speedtest/traceroute_test.go
  • internal/speedtest/traceroute.go
  • internal/notifications/notifications.go

}}
>
<FontAwesomeIcon icon={faDiscord} className="h-4 w-4" />
<FaDiscord className="h-4 w-4" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== affected files =="
git ls-files | rg '^web/src/(components/Footer\.tsx|components/monitor/MonitorSystemInfo\.tsx|components/monitor/tabs/MonitorOverviewTab\.tsx|utils/agentIcons\.tsx)$' || true

echo
echo "== package versions =="
for f in package.json web/package.json; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    node -e "const p=require('./$f'); console.log(JSON.stringify({deps:p.dependencies, devDeps:p.devDependencies}, null, 2))" | rg -i 'react-icons|fontawesome|font-awesome|tailwind|vite|eslint' -C 1 || true
  fi
done

echo
echo "== imports/usages in affected files =="
for f in web/src/components/Footer.tsx web/src/components/monitor/MonitorSystemInfo.tsx web/src/components/monitor/tabs/MonitorOverviewTab.tsx web/src/utils/agentIcons.tsx; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    sed -n '1,120p' "$f" | cat -n
  fi
done

echo
echo "== react-icons and fontawesome deps in manifests/lockfiles =="
rg -n '"react-icons"|react-icons@|`@fortawesome`|font-awesome"|"react-icons' -S package.json web/package.json pnpm-lock.yaml web/package.json 2>/dev/null || true

Repository: autobrr/netronome

Length of output: 17612


🌐 Web query:

react-icons 5.7.0 iconBase aria-hidden default SVG

💡 Result:

In react-icons version 5.7.0, the IconBase component does not apply a default aria-hidden attribute to the SVG element [1]. The component renders the SVG element without any automatic accessibility attributes by default [1]. To ensure icons are properly hidden from assistive technologies (which is recommended for decorative icons), you must explicitly add the aria-hidden="true" attribute [2]. There are two primary ways to apply this: 1. Per-Icon: You can pass the attribute directly to the icon component: [2] 2. Globally via IconContext: You can use the IconContext.Provider to apply the attribute to all icons within your application or a specific section of your component tree [3][4]: <IconContext.Provider value={{ attr: { 'aria-hidden': 'true' } }}> </IconContext.Provider> [4] The IconBase component merges the attr object from the IconContext with any other props passed to the icon [1][5][4]. If you need to include other SVG-related attributes (such as focusable="false"), you can include them within the same attr object in your context configuration [4][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== MonitorOverviewTab icon usages =="
sed -n '260,310p' web/src/components/monitor/tabs/MonitorOverviewTab.tsx | cat -n
sed -n '460,495p' web/src/components/monitor/tabs/MonitorOverviewTab.tsx | cat -n

echo
echo "== iconContext usage =="
rg -n "IconContext|IconContext\.Provider|aria-hidden" web/src -S

Repository: autobrr/netronome

Length of output: 10119


Preserve decorative SVG accessibility across the icon migration. react-icons@5.7.0 does not add aria-hidden automatically, so these decorative icons should either opt into a shared IconContext attribute or set aria-hidden="true" where used.

  • web/src/components/Footer.tsx#L31: add decorative SVG attributes to FaDiscord.
  • web/src/components/Footer.tsx#L51: add decorative SVG attributes to SiReadme.
  • web/src/components/monitor/MonitorSystemInfo.tsx#L85-87: add aria-hidden="true" to the Apple/Linux icons.
  • web/src/components/monitor/tabs/MonitorOverviewTab.tsx#L292-295: add aria-hidden="true" to the OS icon returned by getOSIcon().
  • web/src/components/monitor/tabs/MonitorOverviewTab.tsx#L484-486: add aria-hidden="true" to the mobile kernel icons.
  • web/src/utils/agentIcons.tsx#L37: preserve the attribute in the returned laptop icon abstraction.
📍 Affects 4 files
  • web/src/components/Footer.tsx#L31-L31 (this comment)
  • web/src/components/Footer.tsx#L51-L51
  • web/src/components/monitor/MonitorSystemInfo.tsx#L85-L87
  • web/src/components/monitor/tabs/MonitorOverviewTab.tsx#L292-L295
  • web/src/components/monitor/tabs/MonitorOverviewTab.tsx#L484-L486
  • web/src/utils/agentIcons.tsx#L37-L37
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/components/Footer.tsx` at line 31, Preserve decorative SVG
accessibility by adding aria-hidden="true" to FaDiscord and SiReadme in
web/src/components/Footer.tsx (lines 31 and 51), the Apple/Linux icons in
web/src/components/monitor/MonitorSystemInfo.tsx (lines 85-87), the OS icon
returned by getOSIcon() and mobile kernel icons in
web/src/components/monitor/tabs/MonitorOverviewTab.tsx (lines 292-295 and
484-486), and the returned laptop icon abstraction in
web/src/utils/agentIcons.tsx (line 37).

Source: MCP tools

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/config/config.go (1)

112-116: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Document the removed configuration keys in docs/.

DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE, the packet-loss defaults, MONITOR_RECONNECT_INTERVAL, and TAILSCALE_AGENT_ACCEPT_ROUTES are no longer accepted by the config parser, and there is no documentation reference for them. Add a migration/reference note under docs/ describing these removals and their ignored behavior, as required for configuration changes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/config/config.go` around lines 112 - 116, Add a migration/reference
note under docs documenting that DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE, the
packet-loss defaults, MONITOR_RECONNECT_INTERVAL, and
TAILSCALE_AGENT_ACCEPT_ROUTES were removed from the config parser and are now
ignored. Keep the note focused on configuration migration behavior and reference
the PaginationConfig change where appropriate.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tailscale/tailscale.go`:
- Around line 63-64: Update ListenOnTailscale to build its listener address with
net.JoinHostPort instead of fmt.Sprintf, preserving the selected Tailscale IP
and port for both IPv4 and IPv6. Add table-driven regression tests covering both
address families and verify the function reaches net.Listen with a valid
host-port address.

---

Outside diff comments:
In `@internal/config/config.go`:
- Around line 112-116: Add a migration/reference note under docs documenting
that DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE, the packet-loss defaults,
MONITOR_RECONNECT_INTERVAL, and TAILSCALE_AGENT_ACCEPT_ROUTES were removed from
the config parser and are now ignored. Keep the note focused on configuration
migration behavior and reference the PaginationConfig change where appropriate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 53a9bfa1-9b01-41e7-bc18-ee419de2041c

📥 Commits

Reviewing files that changed from the base of the PR and between abcac5d and 86ae5b7.

⛔ Files ignored due to path filters (1)
  • web/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (52)
  • .golangci.yml
  • README.md
  • config/config.toml
  • docs/superpowers/plans/2026-04-09-packetloss-history-cutover.md
  • internal/auth/auth.go
  • internal/auth/oidc.go
  • internal/broadcaster/broadcaster.go
  • internal/config/config.go
  • internal/database/database.go
  • internal/database/database_test.go
  • internal/database/migrations/migrations.go
  • internal/database/user.go
  • internal/monitor/tailscale_discovery.go
  • internal/notifications/notifications.go
  • internal/server/auth.go
  • internal/server/auth_oidc.go
  • internal/server/server.go
  • internal/speedtest/iperf.go
  • internal/speedtest/progress_broadcaster.go
  • internal/speedtest/traceroute.go
  • internal/speedtest/traceroute_test.go
  • internal/speedtest/types.go
  • internal/tailscale/tailscale.go
  • internal/types/types.go
  • internal/utils/crypto.go
  • internal/utils/tailscale.go
  • pkg/migrator/migrator.go
  • scripts/check_vnstat_data.sh
  • web/build.go
  • web/package.json
  • web/src/api/auth.ts
  • web/src/api/monitor.ts
  • web/src/api/notifications.ts
  • web/src/api/tailscale.ts
  • web/src/components/Footer.tsx
  • web/src/components/Main.tsx
  • web/src/components/auth/Login.tsx
  • web/src/components/monitor/MonitorSystemInfo.tsx
  • web/src/components/monitor/tabs/MonitorOverviewTab.tsx
  • web/src/components/settings/notifications/index.ts
  • web/src/components/speedtest/traceroute/constants/tracerouteConstants.ts
  • web/src/components/speedtest/traceroute/utils/serverUtils.ts
  • web/src/components/speedtest/traceroute/utils/tracerouteUtils.ts
  • web/src/constants/monitorRefreshIntervals.ts
  • web/src/types/pwa.d.ts
  • web/src/types/service-worker.d.ts
  • web/src/types/speedtest.ts
  • web/src/types/types.ts
  • web/src/utils/agentIcons.tsx
  • web/src/utils/countryFlags.ts
  • web/src/utils/darkMode.ts
  • web/src/utils/timeSettings.ts
💤 Files with no reviewable changes (28)
  • web/src/api/tailscale.ts
  • scripts/check_vnstat_data.sh
  • web/src/types/types.ts
  • internal/broadcaster/broadcaster.go
  • docs/superpowers/plans/2026-04-09-packetloss-history-cutover.md
  • internal/speedtest/traceroute_test.go
  • internal/types/types.go
  • web/src/types/pwa.d.ts
  • internal/utils/crypto.go
  • internal/speedtest/progress_broadcaster.go
  • web/src/api/notifications.ts
  • web/src/components/speedtest/traceroute/utils/tracerouteUtils.ts
  • web/src/api/monitor.ts
  • internal/server/server.go
  • internal/speedtest/types.go
  • web/src/types/service-worker.d.ts
  • web/package.json
  • web/src/components/speedtest/traceroute/constants/tracerouteConstants.ts
  • internal/speedtest/iperf.go
  • web/src/api/auth.ts
  • web/src/types/speedtest.ts
  • web/build.go
  • internal/auth/oidc.go
  • config/config.toml
  • internal/database/database_test.go
  • internal/notifications/notifications.go
  • internal/speedtest/traceroute.go
  • internal/database/database.go
🚧 Files skipped from review as they are similar to previous changes (21)
  • internal/monitor/tailscale_discovery.go
  • web/src/components/Footer.tsx
  • web/src/utils/countryFlags.ts
  • .golangci.yml
  • web/src/components/speedtest/traceroute/utils/serverUtils.ts
  • web/src/constants/monitorRefreshIntervals.ts
  • internal/utils/tailscale.go
  • web/src/components/monitor/MonitorSystemInfo.tsx
  • internal/auth/auth.go
  • web/src/components/auth/Login.tsx
  • internal/database/user.go
  • internal/server/auth.go
  • web/src/components/Main.tsx
  • web/src/utils/agentIcons.tsx
  • web/src/components/monitor/tabs/MonitorOverviewTab.tsx
  • web/src/utils/darkMode.ts
  • internal/server/auth_oidc.go
  • README.md
  • internal/database/migrations/migrations.go
  • web/src/utils/timeSettings.ts
  • pkg/migrator/migrator.go

Comment on lines 63 to 64
addr := fmt.Sprintf("%s:%d", status.Self.TailscaleIPs[0], port)
return net.Listen("tcp", addr)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 3 'func ListenOnTailscale|TailscaleIPs\[0\]|JoinHostPort' internal/tailscale/tailscale.go
fd -t f --glob '*tailscale*_test.go' internal

Repository: autobrr/netronome

Length of output: 703


🏁 Script executed:

#!/usr/bin/env batch
set -euo pipefail

echo '== package imports and ListenOnTailscale context =='
sed -n '1,80p' internal/tailscale/tailscale.go

echo
echo '== existing tailscale tests =='
for f in internal/config/tailscale_config_test.go internal/utils/tailscale_test.go; do
  if [ -f "$f" ]; then
    echo "--- $f"
    wc -l "$f"
    sed -n '1,220p' "$f"
  fi
done

echo
echo '== deterministic Go net.JoinHostPort equivalent behavior probe (Go reference source not run, use installed Go if available) =='
if command -v go >/dev/null 2>&1; then
  tmp="$(mktemp -d)"
  cat > "$tmp/probe.go" <<'EOF'
package main

import (
	"fmt"
	"net"
)

func main() {
	for _, ip := range []string{"100.64.1.2", "fd7a:115c:a1e0:ab12:4843:cd96:6240:102"} {
		port := 9000
		invalid := fmt.Sprintf("%s:%d", ip, port)
		valid := net.JoinHostPort(ip, "9000")
		fmt.Printf("ip=%s invalid=%q valid=%q\n", ip, invalid, valid)
		_, err := net.ResolveTCPAddr("tcp", invalid)
		fmt.Printf("resolve invalid err: %T %v\n", err, err)
		r, err := net.ResolveTCPAddr("tcp", valid)
		fmt.Printf("resolve valid addr: %v err: %T %v\n", r, err, err)
		if l, err := net.Listen("tcp", valid); err != nil {
			fmt.Printf("listen err: %T %v\n", err, err)
		} else {
			fmt.Printf("listen ok addr=%s resolved=%s\n", l.Addr(), l.Addr().String())
			l.Close()
		}
	}
}
EOF
  (cd "$tmp" && go run probe.go)
else
  echo "go not installed"
fi

Repository: autobrr/netronome

Length of output: 12215


🏁 Script executed:

#!/usr/bin/bash
set -euo pipefail

echo '== package imports and ListenOnTailscale context =='
sed -n '1,80p' internal/tailscale/tailscale.go

echo
echo '== existing tailscale tests =='
for f in internal/config/tailscale_config_test.go internal/utils/tailscale_test.go; do
  if [ -f "$f" ]; then
    echo "--- $f"
    wc -l "$f"
    sed -n '1,220p' "$f"
  fi
done

echo
echo '== deterministic net.JoinHostPort behavior probe =='
temp="$(mktemp -d)"
cat > "$temp/probe.go" <<'EOF'
package main

import (
	"fmt"
	"net"
)

func main() {
	for _, ip := range []string{"100.64.1.2", "fd7a:115c:a1e0:ab12:4843:cd96:6240:102"} {
		port := 9000
		invalid := fmt.Sprintf("%s:%d", ip, port)
		valid := net.JoinHostPort(ip, "9000")
		fmt.Printf("ip=%s invalid=%q valid=%q\n", ip, invalid, valid)
		_, err := net.ResolveTCPAddr("tcp", invalid)
		fmt.Printf("resolve invalid err: %T %v\n", err, err)
		r, err := net.ResolveTCPAddr("tcp", valid)
		fmt.Printf("resolve valid addr: %v err: %T %v\n", r, err, err)
		if listener, err := net.Listen("tcp", valid); err != nil {
			fmt.Printf("listen err: %T %v\n", err, err)
		} else {
			fmt.Printf("listen ok addr=%s resolved=%s\n", listener.Addr(), listener.Addr().String())
			listener.Close()
		}
	}
}
EOF
if command -v go >/dev/null 2>&1; then
  (cd "$temp" && go run probe.go)
else
  echo "go not installed"
fi

Repository: autobrr/netronome

Length of output: 12140


Use net.JoinHostPort for the listener address.

fmt.Sprintf("%s:%d", ...) accepts IPv6 Tailscale addresses as-is, which Go parses invalidly because the IPv6 literal needs brackets. This makes ListenOnTailscale fail to parse the address before listening; add IPv4 and IPv6 table-driven regression coverage for this function.

Proposed fix
+	"strconv"
+
-	addr := fmt.Sprintf("%s:%d", status.Self.TailscaleIPs[0], port)
+	addr := net.JoinHostPort(status.Self.TailscaleIPs[0].String(), strconv.Itoa(port))
 	return net.Listen("tcp", addr)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
addr := fmt.Sprintf("%s:%d", status.Self.TailscaleIPs[0], port)
return net.Listen("tcp", addr)
addr := net.JoinHostPort(status.Self.TailscaleIPs[0].String(), strconv.Itoa(port))
return net.Listen("tcp", addr)
🧰 Tools
🪛 golangci-lint (2.12.2)

[error] 64-64: net.Listen must not be called. use (*net.ListenConfig).Listen

(noctx)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tailscale/tailscale.go` around lines 63 - 64, Update
ListenOnTailscale to build its listener address with net.JoinHostPort instead of
fmt.Sprintf, preserving the selected Tailscale IP and port for both IPv4 and
IPv6. Add table-driven regression tests covering both address families and
verify the function reaches net.Listen with a valid host-port address.

Source: Coding guidelines

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/src/components/Main.tsx (1)

59-73: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restore the public theme when leaving public mode.

The public-state effect only flags late promise updates; it does not restore the prior theme when Main unmounts from /public. Add effect cleanup or route-level reset so protected routes cannot remain styled with the public theme.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/src/components/Main.tsx` around lines 59 - 73, Update the public-mode
effect in Main’s useEffect so its cleanup restores the previously active
non-public theme when isPublic becomes false or the component unmounts, while
retaining the active guard for late getPublicTheme results. Use the existing
theme-application/reset mechanism rather than introducing a separate styling
path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@web/src/components/Main.tsx`:
- Around line 59-73: Update the public-mode effect in Main’s useEffect so its
cleanup restores the previously active non-public theme when isPublic becomes
false or the component unmounts, while retaining the active guard for late
getPublicTheme results. Use the existing theme-application/reset mechanism
rather than introducing a separate styling path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 51865194-3c7f-4b75-9011-252352138638

📥 Commits

Reviewing files that changed from the base of the PR and between 86ae5b7 and 8eece87.

📒 Files selected for processing (11)
  • README.md
  • config/config.toml
  • internal/config/config.go
  • internal/notifications/notifications.go
  • internal/server/server.go
  • web/src/api/notifications.ts
  • web/src/components/Main.tsx
  • web/src/components/monitor/tabs/MonitorOverviewTab.tsx
  • web/src/components/speedtest/traceroute/utils/serverUtils.ts
  • web/src/utils/darkMode.ts
  • web/src/utils/timeSettings.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/src/components/speedtest/traceroute/utils/serverUtils.ts
  • README.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant