Commit Graph
29 Commits
Author SHA1 Message Date
2GT-RichandClaude Opus 5 33ca7cc651 chore: clear the dependency backlog, and fix a log-injection finding (v0.23.32-beta)
Two pieces of housekeeping that had gone quiet.

**A code-scanning alert nobody had looked at.** CodeQL flagged js/log-injection
in the preflight handler: a request value interpolated straight into a log line.
Log entries are newline-delimited, so a value containing a line break forges
additional entries — and an audit trail its own subject can write into is worse
than none, because it is believed.

The interesting part is that the risk had already been recognised. Two sites in
the clients routes strip carriage returns inline, ad hoc, and the third was
simply missed. That is what a shared helper is for, so there is now a `logSafe`
utility with tests, used at all three. It replaces control characters with a
visible marker rather than stripping them, so a tampered value reads as tampered
instead of being quietly tidied, and truncates absurd input so one field cannot
flood the log.

**Twelve Dependabot pull requests, the oldest six weeks old.** Nine had passing
checks, but those runs were from July against a main that has moved a long way,
so rather than merging stale branches serially the eight safe ones are applied
here as one change and verified together: bullmq, pg, helmet, @types/supertest,
tailwind-merge, vite, actions/setup-node and github/codeql-action.

Deliberately excluded, and left open:

  * bcryptjs 2.4.3 to 3.0.3 (#79) — a major on the password-hashing path.
    Dependabot groups it with routine bumps; it is not one, and it deserves
    its own verification rather than riding along in a batch.
  * typescript 5.9 to 7.0 (#81), tailwindcss 3.4 to 4.3 (#76) and
    eslint-plugin-react-hooks (#78) — all three already fail their own checks.

Verified beyond the gates: the application was rebuilt and exercised on the new
dependencies — authentication, the BullMQ-backed poller, Postgres reads and
helmet's headers all behave.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 16:17:35 -07:00
2GT-RichandClaude Opus 4.8 d44a0ea8a7 fix(deps): patch socket.io-parser advisory; add local CI preflight gate
Security Audit failed on a newly-published advisory, GHSA-2m8v-j782-fhvr
(socket.io-parser "Zero-attachment Memory Exhaustion", high). It affected both
projects transitively via socket.io / socket.io-client. Patched to 4.2.7 in both
lockfiles; no direct dependency versions changed.

Also adds the gate that should have caught the previous two CI failures before
they reached GitHub:

- scripts/ci-preflight.sh runs every gate from .github/workflows/ci.yml
  (frontend and backend lint/type-check/build, plus both prod-dependency audits
  with the same audit-ci flags and allowlist) and additionally the backend Jest
  suite, which CI does not currently run. It runs all gates rather than failing
  fast, so one invocation surfaces every problem. ~35s.
- scripts/claude-push-gate.sh wires that into a Claude Code PreToolUse hook so a
  `git push` is refused while any gate fails, with the failure detail returned
  inline. Non-push commands and --dry-run pass straight through.

Verified: with the fix reverted, the gate correctly denied the push and reported
"backend: lint FAIL"; with it restored, all 9 gates pass and both audit-ci
invocations exit 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-10 09:27:40 -07:00
2GT-Rich 4ef9fd0e37 chore(ci): fix Security Audit — audit prod deps via audit-ci, patch dev advisories
The Security Audit job failed because new advisories dropped against existing
deps and `npm audit --audit-level=high` audits the whole tree (incl. dev/build
tooling that isn't shipped).

- Switch both audit steps to `audit-ci --high --skip-dev`, so the gate reflects
  what's actually deployed (backend ships --omit=dev; frontend ships a static
  build) while still failing on real high/critical production advisories.
- Allowlist GHSA-qwww-vcr4-c8h2 (React Router "RSC Mode CSRF") for the frontend:
  this is a client-side SPA using BrowserRouter — RSC mode is not used — and
  there is no forward-compatible fix for react-router-dom 7.x (only a downgrade).
- `npm audit fix` on both lockfiles to patch non-breaking transitive dev
  advisories (js-yaml, postcss, brace-expansion, minimatch). No direct/prod
  dependency versions changed; app runtime is unchanged.

Verified: backend 114 tests pass, frontend builds, and audit-ci passes for both
projects locally.
2026-07-29 15:47:52 -07:00
2GT-RichandClaude Opus 4.8 3fe8341b71 chore(deps): batch Dependabot bumps + ES2022 tsconfig (v0.17.1-beta)
Apply the open Dependabot updates as one validated batch (build + test + lint +
local Docker smoke test all green) rather than 11 separate merges.

Backend:
- @types/node 20.19.43 -> 26.1.1 (aligns types with the Node 26 runtime)
- typescript-eslint 8.58.2 -> 8.64.0
- eslint 10.5.0 -> 10.7.0
- eslint-plugin-security 4.0.0 -> 4.0.1
- nodemailer 9.0.1 -> 9.0.3
- tsconfig target/lib ES2020 -> ES2022 so Array.prototype.at() (devices.ts)
  type-checks under the new @types/node — this is what unblocked #72.

Frontend:
- axios 1.18.0 -> 1.18.1
- react-router-dom 7.18.0 -> 7.18.1
- lucide-react 1.21.0 -> 1.23.0
- @xyflow/react 12.10.2 -> 12.11.1
- @vitejs/plugin-react 6.0.2 -> 6.0.3

CI:
- docker/setup-qemu-action v3 -> v4

Closes #58
Closes #60
Closes #62
Closes #65
Closes #66
Closes #67
Closes #68
Closes #69
Closes #70
Closes #71
Closes #72

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 09:33:26 -07:00
2GT-RichandClaude Opus 4.8 c0f230bdf2 feat(auth): OIDC / SSO single sign-on (v0.17.0-beta)
Add OpenID Connect single sign-on so the platform can authenticate against
any standards-compliant provider (Entra ID, Okta, Google Workspace, Keycloak,
Authentik, …) alongside local accounts. Resolves the feature request in #73.

Flow (backend-driven Authorization Code + PKCE):
- GET /api/auth/oidc/login builds the authorize URL and stores the PKCE/nonce
  transaction in Redis (single-use, 10m TTL); the callback validates the ID
  token via openid-client (JWKS signature, iss/aud/exp/nonce), resolves the
  identity to a local user, and mints the platform's normal session JWT —
  handed to the SPA via URL fragment. No sessions/cookies introduced.

Identity mapping (users table gains email/oidc_subject/oidc_issuer/
auth_provider; password_hash now nullable; partial unique indexes):
- First sign-in auto-provisions a user, or links to an existing local account
  when the IdP email is verified and matches.
- Roles derive from a configurable IdP group -> role map with a default
  fallback; existing users are never auto-demoted on a groupless login.

Configuration (admin-only, no env/redeploy needed):
- Stored as an app_settings row with the client secret encrypted at rest
  (utils/crypto); masked in responses and excluded from GET /api/settings.
- New UI: Settings -> SSO / OIDC panel (issuer/client, claim + group->role
  mapping, provisioning toggles, discovery test, copyable redirect URI), a
  login-page SSO button, and an SSO badge in Users & Roles.

Security: local break-glass login preserved; PKCE + single-use state; email
linking requires email_verified; same-site-only post-login redirect.

Adds openid-client@^5 (CommonJS). 17 new unit tests (claim/role mapping,
username derivation, config secret round-trip/masking); 114 backend tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 18:54:36 -07:00
2GT-RichandClaude Fable 5 27f155f778 feat(firmware): in-app MikroTik release notes + posture findings for pending updates (v0.16.6-beta)
- New GET /api/firmware/changelog/:version proxies MikroTik's official
  per-version release notes (download.mikrotik.com/routeros/<ver>/CHANGELOG)
  with strict version validation and process-lifetime caching
- ChangelogModal: "What's new in X.Y.Z" on the device Config tab's
  update box and on the Firmware page's latest-version cells opens the
  changelog in-app, with an external mikrotik.com link and graceful
  fallback when the CDN is unreachable
- Security posture: a pending RouterOS update is now a medium-severity
  finding and a pending RouterBOOT upgrade a low-severity one; titles
  are version-free so Common Findings aggregates the fleet into one row
- chore(deps): npm audit fix bumps morgan (GHSA-4vj7-5mj6-jm8m); both
  workspaces audit clean

Validation: backend tsc/lint/92 tests, frontend tsc/lint/build/11 tests,
endpoint tested (valid/invalid/unknown versions), browser-verified on
Firmware page, device Config tab, Security Center, and device Security
tab; security review of the diff found no findings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 15:45:53 -07:00
2GT-RichandClaude Fable 5 6f0fbdb74f chore(deps): dependency upgrades — react-router 7, eslint 10, TS 6, plugin-react 6; drop unused zod (v0.16.5-beta)
Applies the open dependabot PRs in one validated pass:

- react-router-dom 6.30 -> 7.18 (drop-in for our API surface; verified
  in-browser: login, sidebar routing, ?type= deep-links, legacy redirects)
- react + react-dom -> 19.2.7, axios -> 1.18.0, lucide-react -> 1.21.0
- actions/checkout v6 -> v7 across all workflows
- backend: eslint 10 + @eslint/js 10 (fix 5 new no-useless-assignment
  findings), typescript 6.0.3 (explicit types: ["node","jest"] in
  tsconfig — TS 6 no longer auto-includes @types), remove zod (unused)
- frontend: @vitejs/plugin-react 6

Not taken: ioredis 5.11.1 (#55) — bullmq pins ioredis to exactly 5.10.1
(including latest bullmq 5.79), so the bump nests a second ioredis and
breaks BullMQ connection types.

Validation: backend tsc/lint/build + 92 tests green; frontend tsc/lint/
build + 11 tests green; docker stack rebuilt and browser-verified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 20:35:21 -07:00
2GT-RichandClaude Opus 4.8 9dfb8a5333 feat: Guest WiFi, network intelligence, firmware orchestration, platform automation, api-ssl (v0.16.3-beta)
Guest WiFi (Hotspot): one-click captive-portal wizard that creates the guest
SSID (virtual AP per radio), VLAN/bridge segregation + L3 VLAN interface, pool,
DHCP, portal, rate-limited guest profile, and masquerade; vouchers with limits +
printable sheets; live guest sessions; walled garden.

Network intelligence: per-client device fingerprinting (vendor/hostname →
category) with a persisted per-client override on the detail page; rogue/neighbor
AP detection from stored AP scans (evil-twin flagging); Mist-style anomaly
insights (client-count/CPU vs same-hour 14-day baseline + error bursts) in the
Operations engine.

Firmware orchestration: staged wave-based RouterOS rollouts (canary first) with
pre-upgrade backup, reboot-ride-out, version verification, halt-on-failure, and
scheduling; live per-device progress + cancel.

Platform & automation: scoped API tokens (mtm_, read/write, hashed at rest,
Bearer auth in requireAuth); outbound webhooks (12 events, HMAC-signed) fired
from the alert pipeline + firmware orchestrator; scheduled email reports.

api-ssl: RouterOSClient negotiates TLS on port 8729 and accepts RouterOS's
default self-signed certs (rejectUnauthorized:false), so SSL-secured API devices
connect without manual cert trust. Fixes #57.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 21:58:02 -07:00
2GT-RichandClaude Opus 4.8 6cfca387d8 feat(ops): operations insights engine + working quick actions; fix global search (v0.16.2-beta)
Global search:
- Clicking/Enter on a client result now opens that client's detail page
  (/clients/<mac>) instead of dumping to the clients list.

Operations dashboard (new backend route /api/operations):
- GET /insights: server-side attention engine (offline, updates, CPU/memory
  pressure, missing backups, recent outages, weak WiFi clients, co-channel
  overlap, high TX retries, error events) + per-device capacity + merged
  activity feed (config changes, audit actions, alerts; login noise filtered).
- POST /backup-all and /sync-all: fleet-wide actions over online devices.
- Quick Actions now execute: Run discovery, Backup all, Sync config, and
  Open terminal (device picker -> live SSH TerminalModal); inline status.
- New cards: Capacity & health meters, Security posture rollup (reuses
  per-device posture, cached), Recent activity feed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 23:12:16 -07:00
2GT-Rich 4e6c9f481e feat(wireless+ports): RF Health panels + physical per-port clients (v0.16.1-beta)
Wireless RF Health (fleet Wireless page + per-AP Radios tab):
- Channel usage map across 2.4/5/6 GHz with co-channel overlap; operating
  channel resolved live from /interface/wifi/monitor on the wifi package
  (auto-channel radios report no frequency in /print).
- AP deployment density: client RSSI distribution on the -90..-30 dBm scale
  with a coverage-gap warning.
- AP radio TX retries histogram (0%->35%+) with band selector, derived from
  per-client CCQ (new wireless_radio_quality InfluxDB series).
- WiFi connectivity success funnel (Association/Auth/DHCP) derived from logs.

Per-port connected clients (Ports tab):
- New card lists clients physically connected to a selected port (host/MAC/
  IP/VLAN/connection time, linked to client pages).
- Distinguishes physical clients from the raw MAC table: uplink/trunk ports
  are auto-detected (topology neighbor, multi-VLAN MAC spread, or high MAC
  count) and show an uplink explainer + "view MAC table" disclosure instead
  of every reachable MAC.
- Added clients.first_seen ("connected since"); set once, preserved across polls.
2026-06-25 15:37:08 -07:00
2GT-RichandClaude Opus 4.8 1be161e67a feat(ui): modern clients pagination + unified syslog page (v0.16.0-beta)
Clients:
- Replace Previous/Next buttons with a "Show N entries" dropdown
  (25/50/100/200, persisted to localStorage) and numbered page selection
  with prev/next chevrons and ellipses for long ranges.

Syslog (Network Services):
- Drop the Single Device / All Devices mode toggle; always show the
  fleet-aggregated view with coverage badges.
- Add a per-section device dropdown + "Add to device" button beside
  "Add to All Devices" for targeting a single device (direct save).
- Edit / enable-disable / remove remain coverage-scoped, so single-device
  management is preserved without the separate mode.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 08:53:19 -07:00
2GT-RichandClaude Opus 4.8 6e56048f2f chore(deps): bump axios, react-query, lucide-react, pg (v0.15.1-beta)
Validated dependency updates (Dependabot #41, #42, #43, #48):
- axios 1.16.0 → 1.16.1
- @tanstack/react-query 5.95.2 → 5.101.0
- lucide-react 1.16.0 → 1.17.0
- pg 8.20.0 → 8.21.0

Holding ioredis at 5.10.1: 5.11.1 (#45) breaks the backend build via a
type mismatch with BullMQ's bundled ioredis copy; leave until BullMQ
bumps its pinned ioredis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 16:44:30 -07:00
2GT-RichandClaude Opus 4.8 b1dd62bd1f feat(traffic): protocol breakdown layout + inbound packets chart + flow source health (v0.15.0-beta)
- Traffic by Application: donut + legend side-by-side, larger donut with
  center total label, percentage in tooltip; card now sizes to its content
- New Inbound Packets area chart below the throughput chart (packets field
  now summed per direction in /traffic/timeseries)
- New Flow Sources & Data Health card: collector listening state, packets
  received, flows attributed, attribution rate, per-exporter flow/packet
  counts and last-seen; low-attribution hint for NAT-in-path exporters
- /traffic/apps now returns per-app packets alongside bytes
- Restructured bottom row: Top Talkers (left) | Application + Data Health
  stacked (right) for alignment
- Tightened Top Talkers row spacing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 16:32:17 -07:00
2GT-RichandClaude Opus 4.8 d79eb13119 feat(ui): theme-aware logo, dashboard bar graph, server-side client sorting (v0.14.1-beta)
UI/UX refinements on top of v0.14.0-beta, all validated on the test server:

- Logo: new theme-aware compass iconmark (light/dark SVGs swapped via the
  dark class), sized to 45px; favicon updated to match. Wordmark casing
  corrected to "MikroTik Manager" (font size unchanged).
- Navigation icons enlarged 15 -> 17px.
- Dashboard: "Connected clients" line chart converted to a bar chart with a
  category axis + light downsampling so bars stay readably thick across ranges.
- Clients: sorting is now server-side across the whole dataset (was sorting
  only the current page, so Type/others appeared to do nothing on a uniform
  page); table uses a fixed column layout + keepPreviousData so columns no
  longer jump or blank out when sorting/paging. Backend clients route gains
  whitelisted sort/dir params (safe numeric IP sort, deterministic tiebreaker).
- Connections tab: surfaces the live /ip/firewall/connection/tracking state
  (on/auto/off pill) and clearer empty-state copy explaining auto-mode.

Lint/typecheck/build/jest green in both workspaces; npm audit --audit-level=high
clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 13:37:11 -07:00
2GT-RichandClaude Opus 4.8 ee9c9ff9f7 feat(security): Security Center — firewall, NAT, bandwidth, posture, connections (v0.14.0-beta)
A dedicated top-level Security section plus a Meraki/UniFi-grade firewall built
on the full RouterOS feature set.

Security Center (new /security page)
- Fleet hardening scores, per-device posture list, and a "Common Findings"
  rollup aggregating identical issues across the fleet
- "Manage" deep-links into the device's Security tab (?tab= support added)

Firewall & NAT (per device + in Security Center)
- Friendly rule builder: Allow/Drop/Reject chips, Any/Address/Address-List
  pickers, port presets, connection-state chips, logging, live plain-English
  preview
- Address lists as reusable objects, referenced from rules
- Rule reordering (/ip/firewall/{filter,nat}/move); per-rule hit counters
  (print stats) with dead-rule highlighting + reset
- NAT wizards: Port Forward / Masquerade / 1:1 NAT + Custom
- Safe-apply lockout guard: backend 409 on an unscoped input drop/reject that
  would sever management; UI confirms before forcing (detectLockoutRisk, tested)

Access & security
- Security posture audit: graduated, de-duplicated scoring that never proposes
  disabling the management service the platform connects through (no self-
  lockout); switch-aware input-firewall severity; service hardening table
- Bandwidth: simple-queue CRUD + one-click "Limit this client" on client detail
- Active connections viewer

These L3 features are available on all managed RouterOS devices (routers,
switches, APs), not gated by device type.

Backend: DeviceCollector address-list/move/stats/connections/queues/service
methods; device routes for all of the above; firewallSafety + firewallSummary
utils with unit tests (19 new).

Security: bump nodemailer 8 -> 9.0.1 to clear GHSA-p6gq-j5cr-w38f (our
createTransport/sendMail usage is unaffected by the advisory's raw-option path).

Verified live against RouterOS devices; lint/typecheck/build/jest green in both
workspaces; npm audit --audit-level=high clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 09:24:22 -07:00
2GT-RichandClaude Opus 4.8 623e54120d chore(deps): clear high-severity npm audit findings (v0.13.3-beta)
CI Security Audit (npm audit --audit-level=high) was failing. Resolved all
high-severity advisories via non-breaking transitive bumps (npm audit fix,
no --force, no direct-dependency or source changes):

- frontend: form-data, ws (via socket.io-client), @babel/core,
  react-router-dom, js-yaml — now 0 vulnerabilities
- backend: form-data, ws (via socket.io) — 0 high-severity remaining

Only package-lock.json files changed plus the version bump. Verified both
workspaces: npm ci, lint, type-check, build, and backend jest (73 tests)
all pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 19:51:45 -07:00
2GT-RichandClaude Fable 5 b841eb6e7b feat: NetFlow/IPFIX traffic analytics — per-client usage, app breakdown, built-in collector (v0.13.0-beta)
Adds Meraki-style traffic analytics powered by MikroTik Traffic Flow:

Backend
- Built-in NetFlow v9 + IPFIX collector (UDP 2055) with hand-rolled decoder,
  template caching, enterprise-field and IPv6 support
- Flow attribution: client IP → MAC via the clients table, upload/download
  direction, NAT-duplicate records dropped
- App classification by protocol/port (~25 categories: HTTPS, QUIC, DNS,
  SSH, Email, WireGuard, ...)
- Deduplication: per-client best-exporter-per-window so flows crossing two
  managed routers are never double-counted
- NAT-tolerant ingest: flows from sources matching no managed device (NAT /
  Tailscale subnet routers in path) are accepted as per-source unidentified
  exporters instead of silently dropped (netflow_accept_unknown setting)
- Storage: InfluxDB client_traffic time-series (bounded cardinality via
  top-N fold) + Postgres client_traffic_daily rollups; daily retention purge
- One-toggle device config push via RouterOS API (/ip traffic-flow + target)
- New /api/traffic/* analytics endpoints + /api/network-services/netflow
- docker-compose: NETFLOW_PORT (default 2055/udp) published on the backend

Frontend
- New Traffic page: fleet up/down chart, top talkers with client
  click-through, app-category donut, 1h–30d ranges
- New NetFlow config page: collector settings, live ingest stats,
  per-device export toggles with health badges, NAT-source banner
- Client detail: App Traffic card (auto-hides without data)
- Clients page: sortable "Data (today)" column
- Settings: NetFlow retention controls

Includes 17 unit tests (decoder fixtures, dedup, attribution, classifier);
verified end-to-end against live RouterOS devices.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 10:58:41 -07:00
2GT-Rich bc555fee2f Merge pull request #25 from 2GT-Media-Group-LLC/dependabot/npm_and_yarn/backend/multi-d4eba38f0e
chore(deps-dev): bump jest and @types/jest in /backend
2026-05-25 16:05:21 -07:00
2GT-Rich 5d1d730e0f Merge pull request #22 from 2GT-Media-Group-LLC/dependabot/npm_and_yarn/backend/helmet-8.1.0
Bump helmet from 7.2.0 to 8.1.0 in /backend
2026-05-25 16:05:15 -07:00
dependabot[bot] 7da2089445 chore(deps-dev): bump jest and @types/jest in /backend
Bumps [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest) and [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest). These dependencies needed to be updated together.

Updates `jest` from 29.7.0 to 30.4.2
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.4.2/packages/jest)

Updates `@types/jest` from 29.5.14 to 30.0.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: "@types/jest"
  dependency-version: 30.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
- dependency-name: jest
  dependency-version: 30.3.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-16 23:59:09 +00:00
2GT-RichandClaude Sonnet 4.6 a1ca4d0a44 feat: 2FA/TOTP, config templates (v0.11.4 Beta)
- 2FA: TOTP setup wizard in Settings, QR code enrollment, login second-step, password-confirmed disable
- Config templates: reusable DNS/NTP/syslog config sets pushed to selected devices via RouterOS API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 15:44:23 -07:00
2GT-Rich 68d88d0306 feat: RouterBOOT upgrade support, update UI overhaul, discovery fixes (v0.10.6 Beta)
RouterOS vs RouterBOOT distinction:
- Rename "Firmware Updates" → "RouterOS Updates" everywhere (Config tab,
  dashboard banner, devices list tooltip) to accurately reflect what is
  being updated
- Add RouterBOOT bootloader upgrade support as a distinct operation:
  new DeviceCollector methods checkRouterboardUpgrade() and
  installRouterboardUpgrade() using /system/routerboard/print and
  /system/routerboard/upgrade
- New API endpoints: POST /api/devices/:id/check-routerboard and
  POST /api/devices/:id/install-routerboard
- Daily poller now also checks RouterBOOT upgrade status while already
  connected during firmware check cycle, with first-discovery alerts

Config tab update panel:
- Combine RouterOS and RouterBOOT into a single "Software & Firmware
  Updates" card with two subsections separated by a divider
- Pre-populate both sections from stored DB state on load — no longer
  requires a manual "Check" click to see a known pending update
- Enforce update order: when both are pending, show a blue info banner
  explaining RouterOS must be installed first, and disable the
  RouterBOOT "Upgrade & Reboot" button until the RouterOS update clears
- Fix GET /api/devices/:id to include firmware_update_available,
  latest_ros_version, routerboard_upgrade_available, upgrade_firmware_version
  (these were missing from the detail endpoint)

Dashboard & devices list:
- Combined amber banner now shows two distinct rows: RouterOS (N) with
  device links and RouterBOOT (N) with device links — one dismiss for both
- Devices list: amber ArrowUpCircle = RouterOS update, blue Cpu icon =
  RouterBOOT upgrade, each with distinct tooltips
- Fix GET /api/devices (list) to include routerboard_upgrade_available and
  upgrade_firmware_version (these were missing, causing RouterBOOT
  notifications to never appear on the dashboard)

DB migration:
- Add routerboard_upgrade_available BOOLEAN DEFAULT FALSE
- Add upgrade_firmware_version VARCHAR(20)

Discovery system fixes:
- Fix duplicate entries: replace single-key (mac || ip || identity) dedup
  with three cross-referenced indexes so a neighbor seen via LLDP by one
  device and via MNDP by another always merges into one row
- Fix offline devices persisting: handleDeviceFailure now deletes
  topology_links for the offline device (same pattern as clients)
- Add periodic stale-link sweep every 15 min that removes topology_links
  rows older than 20 min as a safety net for devices that go offline
  without cleanly triggering handleDeviceFailure
2026-04-23 13:46:20 -07:00
DenisandCursor Agent a12f52ebc7 feat: non-blocking bulk-add, CORS hardening, credential preset access control (#31)
* devices: hide discovered neighbors that are already managed

Discovered Devices showed every unresolved MikroTik neighbor, even when
the neighbor was obviously the same device a managed node is reporting
through a different link / MAC / alias. Since we already know every
managed device interface MAC, primary IP, and system identity, we can
flag those rows.

- /api/devices/discovered now annotates each row with duplicate_of_device_id
  and duplicate_of_device_name when the neighbor matches a managed device
  by interface MAC, primary IP, or system identity.
- Add a Hide duplicates of managed devices toggle (default on) above the
  table, with a count of how many matches were found. When enabled, the
  list hides matched rows; when disabled, matches stay visible but are
  dimmed and tagged Already managed so the origin is clear.
- Suppress the Add to Manager action for rows that are already a
  managed device, since adding them would create a second record for the
  same hardware.

Co-authored-by: Denis <denis-ev@users.noreply.github.com>

* devices: safer duplicate handling, try-all safeguards, and timezone/firmware fixes

Co-authored-by: Denis <denis-ev@users.noreply.github.com>

* Non-blocking follow-ups: parsePort util, tests, bulk-add queue, preset rate limit

Co-authored-by: Denis <denis-ev@users.noreply.github.com>

* fix(security): tighten CORS, Redis rate limits, and preset access controls

Require explicit CORS origins in production, align Socket.IO CORS with HTTP,
default Docker Compose to local HTTPS origins, and remove the in-memory
mutation limiter in favor of Redis. Also add operator-use flags for credential
presets in the UI and harden bulk-add job access and client error messages.

Co-authored-by: Denis <denis-ev@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-04-21 19:54:35 -07:00
dependabot[bot] ea58aaef5f Bump helmet from 7.2.0 to 8.1.0 in /backend
Bumps [helmet](https://github.com/helmetjs/helmet) from 7.2.0 to 8.1.0.
- [Changelog](https://github.com/helmetjs/helmet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/helmetjs/helmet/compare/v7.2.0...v8.1.0)

---
updated-dependencies:
- dependency-name: helmet
  dependency-version: 8.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-20 12:46:29 +00:00
2GT-Rich 5d96503832 Add Jest unit test infrastructure and initial test suite
Sets up Jest + ts-jest for the backend and adds 47 tests across 5
suites covering crypto utilities, OUI vendor lookup, auth middleware,
AlertService dispatch/cooldown logic, and DeviceCollector uptime parsing.
2026-04-19 10:21:14 -07:00
2GT-Rich 9511927a05 Merge pull request #14 from 2GT-Media-Group-LLC/dependabot/npm_and_yarn/backend/dotenv-17.4.2
Bump dotenv from 16.6.1 to 17.4.2 in /backend
2026-04-19 09:46:50 -07:00
2GT-Rich bd85f988da Fix all backend lint errors and security vulnerabilities
Backend lint (4 errors fixed):
- auth.ts: suppress @typescript-eslint/no-namespace on Express global
  augmentation (legitimate TS pattern for extending Request type)
- clients.ts: remove unnecessary \. escape in regex character class
- devices.ts: remove unnecessary \- escape by moving hyphen to front [-:]
- PollerService.ts: add comment to empty catch block

Security audit (high/critical CVEs fixed):
- frontend: bump axios (critical SSRF), lodash (high injection),
  follow-redirects (moderate) via npm audit fix
- backend: bump nodemailer 6.x → 8.0.5 (fixes 4 SMTP injection CVEs)
2026-04-16 11:08:42 -07:00
dependabot[bot] c1eb857fd0 Bump dotenv from 16.6.1 to 17.4.2 in /backend
Bumps [dotenv](https://github.com/motdotla/dotenv) from 16.6.1 to 17.4.2.
- [Changelog](https://github.com/motdotla/dotenv/blob/master/CHANGELOG.md)
- [Commits](https://github.com/motdotla/dotenv/compare/v16.6.1...v17.4.2)

---
updated-dependencies:
- dependency-name: dotenv
  dependency-version: 17.4.2
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-04-16 16:57:24 +00:00
2GT-Rich e43b80a9a2 Add security standards and CI infrastructure
- SECURITY.md with vulnerability disclosure policy and self-hosting guidance
- Dependabot config for weekly dependency updates (npm, Docker, Actions)
- ESLint v9 flat config for frontend and backend, with eslint-plugin-security
- GitHub Actions CI: lint, typecheck, build, and npm audit on every push/PR
- CodeQL workflow for automated security scanning (runs on push and weekly)
2026-04-16 09:55:53 -07:00