Commit Graph

498 Commits

Author SHA1 Message Date
Jason Staack
ad75a19f5d feat(16-04): update Scheduler to dispatch by device_type via collectors
- Add collectors map[string]Collector field to Scheduler struct
- Register RouterOSCollector for "routeros" inside NewScheduler
- Replace direct PollDevice call with collector dispatch by dev.DeviceType
- Default empty DeviceType to "routeros" for backward compatibility
- Log error and exit device loop for unknown device types
- Circuit breaker logic unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:34:27 -05:00
Jason Staack
1b89b122ee feat(16-04): add Collector interface and RouterOSCollector
- Define Collector interface with Collect(ctx, dev, pub) error signature
- Implement RouterOSCollector as thin wrapper delegating to PollDevice
- Add compile-time interface assertion for RouterOSCollector

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:32:58 -05:00
Jason Staack
89d904505d feat(16-03): add GetRawCredentials with 4-source fallback, wrap GetCredentials
- GetRawCredentials resolves credentials: device transit, device legacy, profile transit, profile legacy
- Cache key includes source (device/profile) to prevent cross-source poisoning
- GetCredentials is now a backward-compatible wrapper calling GetRawCredentials + ParseRouterOSCredentials
- Add DecryptRaw to device package for raw byte decryption without JSON parsing
- Invalidate clears both parsed and raw cache entries
- All existing callers (PollDevice, CmdResponder, TunnelResponder, BackupResponder, SSHRelay) unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:28:56 -05:00
Jason Staack
b3dbd1e6b9 feat(16-03): add credential type parsers for RouterOS and SNMP
- SNMPCredential struct with v1/v2c/v3 field support
- ParseRouterOSCredentials handles typed and legacy no-type-field JSON
- ParseSNMPCredentials handles snmp_v1, snmp_v2c, snmp_v3 types
- credentialEnvelope for type-agnostic type field peeking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:27:09 -05:00
Jason Staack
d3084abbb9 test(16-02): verify new Device fields in integration test
- Assert DeviceType defaults to "routeros" via COALESCE
- Assert SNMPPort defaults to 161 via COALESCE
- Assert SNMPVersion, SNMPProfileID, CredentialProfileID are nil for
  existing RouterOS devices without profile links
- Assert ProfileEncryptedCredentials and ProfileEncryptedCredentialsTransit
  are nil when no credential profile is linked
- Update test schema with device_type, snmp_port, snmp_version,
  snmp_profile_id, credential_profile_id columns
- Add credential_profiles table to test schema for LEFT JOIN

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:26:53 -05:00
Jason Staack
c1eb9ca41a feat(16-02): extend Device struct and queries for SNMP and credential profiles
- Add 7 new fields to store.Device: DeviceType, SNMPPort, SNMPVersion,
  SNMPProfileID, CredentialProfileID, ProfileEncryptedCredentials,
  ProfileEncryptedCredentialsTransit
- Update FetchDevices query with LEFT JOIN credential_profiles and
  expanded WHERE clause (credential_profile_id IS NOT NULL)
- Update GetDevice query with same JOIN and new columns
- COALESCE defaults: device_type='routeros', snmp_port=161

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:26:03 -05:00
Jason Staack
70c3d8ac7a test(16-03): add failing tests for credential type parsers
- ParseRouterOSCredentials: typed, legacy no-type-field, SNMP rejection, edge cases
- ParseSNMPCredentials: v1, v2c, v3 auth_priv, RouterOS rejection, legacy rejection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:25:59 -05:00
Jason Staack
37ed0242f4 feat(16-01): add devices SNMP columns and snmp_metrics hypertable
- devices table: device_type (default 'routeros'), snmp_port (default 161),
  snmp_version, snmp_profile_id FK -> snmp_profiles, credential_profile_id
  FK -> credential_profiles, with lock_timeout = 3s for safe ALTER
- snmp_metrics: hypertable with 90-day retention, composite index on
  (device_id, metric_name, time DESC), RLS with tenant isolation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:22:27 -05:00
Jason Staack
ad26335300 feat(16-01): add credential_profiles and snmp_profiles tables
- credential_profiles: UUID PK, tenant_id FK with CASCADE, credential_type,
  encrypted credential fields, unique(tenant_id, name), RLS, poller_user GRANT
- snmp_profiles: UUID PK, nullable tenant_id for system profiles, profile_data
  JSONB, partial unique indexes for tenant vs system name uniqueness, RLS with
  system profile visibility to all tenants, poller_user GRANT
- 6 system seed profiles: generic-snmp, network-switch, network-router,
  wireless-ap, ups-device, mikrotik-snmp with full OID collection definitions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 18:21:22 -05:00
Jason Staack
9c5cf552d9 fix(ui): SSH terminal expanded mode respects sidebar width
Expanded SSH now uses left: var(--sidebar-width) instead of inset-4,
so it fills the content area without covering the sidebar or header.
Styled header/buttons to match Warm Precision.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 16:42:44 -05:00
Jason Staack
55266a9188 fix(setup): add sslmode=disable to poller DB URL, add --no-https flag
Go Postgres driver defaults to requiring TLS. Container-to-container
Postgres doesn't have TLS configured. Without sslmode=disable the
poller crashes in a restart loop on fresh installs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 16:38:51 -05:00
Jason Staack
cb2a311a1f feat(setup): add --no-https flag, ask about HTTPS during domain setup
The wizard previously hardcoded https:// for APP_BASE_URL and
CORS_ORIGINS. LAN and dev deployments without TLS need http:// or
browsers silently drop Secure cookies, causing login to fail.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 16:30:34 -05:00
Jason Staack
ddb4ce2512 docs: update documentation for v9.7.2 — setup CLI, navigation, UI scale
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 16:19:21 -05:00
Jason Staack
958571c26a feat(setup): add CLI switches for non-interactive setup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 16:12:15 -05:00
Jason Staack
dbc8c45914 fix(lint): remove unused imports and variables from redesign
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 16:05:31 -05:00
Jason Staack
106aa0f708 fix(test): update login test to expect MikroTik instead of MSP
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:53:46 -05:00
Jason Staack
6e874505eb chore: bump version to 9.7.2 · plain
Warm Precision UI redesign, task-based navigation, interaction system,
website and docs restyled. 30+ commits on warm-precision-redesign
branch, merged to main.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:50:29 -05:00
Jason Staack
1a7c790515 fix(blog): dial back image filter — lighter sepia, higher opacity 2026-03-21 15:43:56 -05:00
Jason Staack
cb1de32269 fix(blog): blend lawyer image into warm precision palette with sepia/multiply 2026-03-21 15:41:43 -05:00
Jason Staack
f45236857f fix(website): restore hover/click screenshots, widen setup box, remove hint text 2026-03-21 15:39:48 -05:00
Jason Staack
3b5e2cad01 fix(website): simplify screenshots — plain images with captions, no interactivity 2026-03-21 15:38:15 -05:00
Jason Staack
e8151845ed fix(website): fix dark nav header on blog, add interactive screenshots
- Remove site-nav--dark class from all pages (blog, homepage)
- Add nav color overrides to all blog pages (light background, dark text)
- Homepage: hover screenshots to swap dark/light, click to expand both
  side by side in overlay

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:36:08 -05:00
Jason Staack
5b78cd9869 docs(website): apply Warm Precision styling to all blog pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:32:59 -05:00
Jason Staack
28035eb5dd docs(website): apply Warm Precision styling to docs page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:29:38 -05:00
Jason Staack
18a176c89a fix(website): fix code block wrapping in setup section 2026-03-21 15:29:02 -05:00
Jason Staack
ce894505dc fix(website): show both light and dark mode screenshots side by side 2026-03-21 15:27:00 -05:00
Jason Staack
c13d7f0f7c docs(website): rewrite homepage per Warm Precision redesign direction
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:23:07 -05:00
Jason Staack
a3b49620e7 feat: Warm Precision UI redesign — new design system, task-based navigation, interaction system
30 commits delivering:
- Warm Precision token system (warm olive/stone palette, no blue)
- Task-based sidebar (Operate/Act replacing Fleet/Config/Admin)
- ContextStrip removed, features moved to sidebar
- Device workspace header with breadcrumb and metadata
- 50ms interaction system (hover/focus/active/press states)
- Skeleton loaders replaced with honest loading states
- Needs Attention dashboard panel with device links
- Joined metrics strip
- UI scale selector (100%/110%/125%)
- All hardcoded colors tokenized
- 143 files changed, net -34 lines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:10:37 -05:00
Jason Staack
43309e19ca fix(ui): final cleanup — signal chart hex, checkbox/select tokens
- SignalHistoryChart: #3b82f6 → hsl(var(--accent))
- Checkbox: opacity-50 disabled → text-muted/border-subtle, proper
  focus ring, bg-panel surface, checked text-background
- Select: opacity-50 disabled → text-muted/border-subtle, proper
  focus ring, radius-control, bg-panel, text-xs

Zero old token names, zero blue hex, zero opacity-disabled remaining.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:04:43 -05:00
Jason Staack
04af5536c2 feat(ui): add UI scale selector (100% / 110% / 125%)
Three-level zoom control in sidebar footer. Uses CSS zoom property,
persisted to localStorage via Zustand store. Applied on mount via
AppLayout useEffect.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:57:04 -05:00
Jason Staack
a3b5fd1848 feat(ui): Needs Attention items link to device, show map icon
- Hostname is now a Link to the device detail page
- MapPin icon shown for devices with coordinates, links to /map
- Hover accent color on both links
- Also fixes tenant-switch query bug and VPN tab colors

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:49:20 -05:00
Jason Staack
5c9915d175 fix(ui): Needs Attention updates on tenant switch, VPN colors tokenized
- Dashboard fleet query now uses selected tenant ID for super_admin
  instead of always fetching all tenants. Needs Attention, metrics
  strip, and all widgets update when switching tenants.
- VPN tab: replace hardcoded purple/blue/green hex with token colors
- Add Certificates and VPN back to sidebar low-frequency section

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:42:49 -05:00
Jason Staack
2da9fe0373 feat(ui): add Certificates and VPN back to sidebar low-frequency section
These were removed during the Operate/Act restructure but are
standalone management pages that need direct nav access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:41:11 -05:00
Jason Staack
4c3b95857a feat(ui): add Needs Attention panel and metrics strip to dashboard
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:30:33 -05:00
Jason Staack
86cff80c97 fix(ui): replace hardcoded interface type colors and diff viewer colors
InterfacesPanel: replace Tailwind palette hex (#3B82F6 blue, #8B5CF6
purple, etc.) with token references (accent, info, warning, success,
error). No more blue or purple interface badges.

DiffViewer: replace raw blue/green/red Tailwind classes with token
classes (info, success, error).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 14:00:03 -05:00
Jason Staack
0313909d93 fix(ui): scroll to top when switching device sidebar tabs
Wraps setActiveTab to also scroll #main-content to top. Prevents
stale scroll position when navigating from a long tab (e.g. Firewall)
to a short one (e.g. SNMP).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:54:09 -05:00
Jason Staack
91eea99aca chore(ui): Stage 4 cleanup — delete ContextStrip, fix transition-all,
replace chart hex colors

- Delete ContextStrip.tsx (no longer imported)
- Sidebar: transition-all → transition-[width]
- Charts: replace #38BDF8/#94a3b8/#334155 with token references
- EmergencyKitDialog hex preserved (print template)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:46:09 -05:00
Jason Staack
b8d8abde32 fix(ui): replace hardcoded chart hex colors with Warm Precision tokens
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:45:52 -05:00
Jason Staack
72c09d95bb feat(ui): add error/empty state classes, update toast styling
- Toast: bg-elevated surface, border-default, radius-control, remove
  richColors (use token colors instead of Sonner defaults)
- Add .panel-empty and .panel-error CSS utility classes
- Available for Phase 4 page-level refinement

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:43:56 -05:00
Jason Staack
996ce37a19 feat(ui): add list-item-interactive class, update table row hover
- Add .list-item-interactive CSS class: 2px left border on hover/focus,
  bg-elevated on active press, 50ms transitions
- FleetTable: update hover to bg-elevated/30 with 50ms transition
- Class available for div-based list rows (alerts, events, nav items)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:42:54 -05:00
Jason Staack
17037e4936 feat(ui): replace skeleton loaders with honest loading states
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:40:58 -05:00
Jason Staack
0ee4416077 feat(ui): update Button, Input, Tabs with Warm Precision interaction system
Button: 50ms transitions, accent focus ring at 2px offset, active
brightness darkening, no opacity-based disabled, border-accent hover
on outline variant, gap-1.5 for icon+text, radius-control (4px)

Input: bg-panel surface, border-default, radius-control, 50ms border
transition, accent focus outline at 2px offset, text-xs, no opacity
disabled

Tabs: accent bottom-border + accent-soft wash on active, text-xs,
50ms transitions, text-secondary inactive with hover to primary

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:34:36 -05:00
Jason Staack
8a77e69aa9 fix: change MSP to MikroTik in login and about pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:27:35 -05:00
Jason Staack
9bb33f9c67 fix(ui): restore info/teal color for device actions in audit log 2026-03-21 13:22:45 -05:00
Jason Staack
814cf3b1e7 fix(ui): fix device header layout for narrow viewports
Two-row layout: top row is identity (breadcrumb › dot hostname status),
bottom row is metadata left + actions right. Hostname truncates instead
of wrapping. Metadata truncates. Actions stay on one line and push
against the right edge. No overlap at any width.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:18:32 -05:00
Jason Staack
2fd98fece0 fix(ui): increase info token saturation for readability 2026-03-21 13:14:28 -05:00
Jason Staack
357258d1c7 fix(ui): eliminate remaining blue — shift info token to warm teal
- --info light: 217 91% 50% (blue) → 180 20% 40% (desaturated warm teal)
- --info dark: 217 60% 60% (blue) → 180 20% 50% (warm teal)
- Audit log: device_ actions use accent instead of info, firmware uses
  warning instead of raw purple
- Fixes 40+ references to text-info/bg-info across the codebase
  without touching each file — token shift handles them all

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:08:50 -05:00
Jason Staack
8ca00b0301 fix(ui): replace TLS badge with icon-only indicator
Full-text badge ("Plain-Text (Insecure)") replaced with a colored
shield icon — green/yellow/red by TLS mode. Label available on
hover via title attribute. Universal lock convention, no label needed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:02:52 -05:00
Jason Staack
329e363b2f fix(ui): declutter device page header — compact tool buttons
- WinBox/RemoteWinBox/SSH: replace big accent CTAs with compact
  bordered tool buttons (text-[10px], h-3 icons, border-default)
- SimpleModeToggle: shrink from pill-button group to inline segmented
  control (text-[10px], accent-soft active state)
- Edit/Delete already icon-only ghost from previous commit
- All tool buttons now visually consistent — small, bordered, receding
- Result: header reads as a compact control strip, not a CTA row

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:55:02 -05:00
Jason Staack
f7b95adfd2 fix(ui): tighten device detail page for control surface feel
- Header: reduce padding, align items-center, dot+label status,
  truncating hostname, compact metadata, version prefixed with v
- Actions: ghost icon buttons for Edit/Delete, tighter gap, smaller icons
- InfoRow: py-2→py-1, text-sm→text-xs, label w-32→w-24, border-subtle
- Data panels: rounded-lg→rounded-sm, p-4→p-3, border-default
- StandardConfigSidebar: tighter rows py-1.5→py-[3px], w-48→w-44,
  accent-soft active bg, text-label section headers, 50ms transitions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:45:31 -05:00