Commit graph

21 commits

Author SHA1 Message Date
ca041fe5aa feat: add Accept: text/markdown content negotiation for agent compatibility
Intercepts requests with Accept: text/markdown at endpoint level (before
the router's :accepts plug rejects them) and returns hardcoded markdown
representations for /, /privacy, and /terms.
2026-04-17 14:14:31 -05:00
0fa1fa800b fix/suppress-health-check-logs (#47)
Reviewed-on: graham/towerops-web#47
2026-03-16 15:22:12 -05:00
7251930404
add mobile app websocket channel and improve QR linking UX
- add MobileSocket for token-authenticated mobile WebSocket connections
- add MobileChannel with org-level and device-level real-time events
- add /mobile/socket endpoint for iOS app connections
- add "Link Mobile App" to user dropdown menu for discoverability
- improve QR code page with numbered steps and clearer instructions
- add socket/channel tests (17 total)
2026-03-13 17:28:36 -05:00
72f81c572d
add real-time GraphQL API with time-series queries and subscriptions
- add absinthe_phoenix for WebSocket subscription support
- create GraphQL WebSocket socket with API token auth at /socket/graphql
- add time-series queries: deviceSensors, sensorReadings, interfaceTraffic, checkResults
- add subscriptions: deviceStatusChanged, alertEvent, sensorReadingsUpdated
- wire subscription triggers into agent_channel and alerts contexts
- add org-scoped access control for sensors/interfaces via join queries
- add 17 tests covering queries, org isolation, empty data edge cases, and auth
- update GraphQL API docs page with time-series and subscription sections
2026-03-12 10:24:39 -05:00
b0fcfb800f
fix(logs): add Plug.Telemetry metadata filter to suppress health check logs
The FilterNoisyLogs plug wasn't completely preventing logs in Phoenix 1.8.
Added metadata_filter to Plug.Telemetry to explicitly skip logging for:
- GET /health
- GET /health/time
- HEAD /

This works at the Telemetry level before logs are emitted.
2026-03-05 19:23:23 -06:00
9a12de7526
fix: remove duplicate dashboard alert tests and add SQL Sandbox plug
- Remove 2 duplicate tests that were covered by existing alert feed test
- Add Phoenix.Ecto.SQL.Sandbox plug to endpoint for test mode
- Enables LiveView processes to access SQL Sandbox connections in tests
- All 7,422 tests now passing (100% pass rate)
2026-03-05 14:19:36 -06:00
ec03a03cf5
fix: completely silence logs for noisy health check endpoints
Created FilterNoisyLogs plug that disables Phoenix logging for both
request and response logs by setting conn.private.phoenix_log to false.

This prevents both:
- Initial request log (Plug.Telemetry)
- Response log (Phoenix.Logger "Sent 200 in Xms")

Filters:
- GET /health (Kubernetes probes)
- HEAD / (external uptime monitors)
2026-03-05 08:23:12 -06:00
01ebb8968d
chore: filter out external uptime monitor HEAD requests from logs 2026-03-04 16:48:59 -06:00
998bdf39b8
update 2026-02-18 10:19:56 -06:00
9ecd01dc8f Security hardening: remaining audit fixes
- Encrypt session cookies (add encryption_salt to endpoint)
- X-Frame-Options: SAMEORIGIN → DENY (match CSP frame-ancestors 'none')
- Remove unsafe-eval from CSP script-src
- Apply security headers in all environments (not just prod)
- Add GraphQL query complexity limit (max 500) via Absinthe.Plug
- GraphQL introspection already blocked in prod via plug

Closes audit items #6, #7, #12, #13, #14, #16
2026-02-15 12:54:38 -06:00
bad1590fed
add gaiia webhook listener with per-org signature verification
Stage 3 of Gaiia integration: webhook event processing for real-time
incremental updates from Gaiia. HMAC-SHA256 signature verification
using per-organization secrets stored in integration credentials.
Handles account, billing subscription, and inventory item events.
2026-02-13 10:40:49 -06:00
4d73e77f3a
Add 404-based brute force protection system
Implements automated detection and blocking of IPs exhibiting scanning behavior (5+ unique 404s within 1 minute).

Key features:
- Progressive ban escalation (5 min → 1 hour → permanent)
- CIDR range and exact IP whitelisting
- Redis-backed 404 path tracking with 60s TTL
- Cloudflare WAF integration for permanent bans
- Admin UI for whitelist and blocked IP management
- Oban cron jobs for cleanup (expired bans, stale violations)
- ETS caching for whitelist performance

Components:
- Plug: ToweropsWeb.Plugs.BruteForceProtection
- Context: Towerops.Security.BruteForce
- Schemas: IpBlock, IpWhitelist
- Workers: CloudflareBanWorker, ExpiredBanCleanupWorker, StaleViolationCleanupWorker
- Admin UI: /admin/security (superuser only)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 16:31:48 -06:00
38eeb1c7b8
fix: improve agent polling and SNMP testing
Changes:
- Fix traffic graph to handle nil interface octets gracefully
- Add comprehensive tests for nil octets scenarios
- Fix agent polling query to support devices assigned directly to org (left join on sites)
- Fix test SNMP connection to inherit credentials from site/org
- Refactor agent_channel process_polling_result to reduce nesting (Credo)
- Add alias for JobCleanupTask in application.ex (Credo)

This fixes crashes when interface stats have nil octets and ensures
devices without a site assignment can be polled by agents.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-05 12:34:28 -06:00
77e62df9da
Move CaptureTimezone plug to browser pipeline
The plug was incorrectly placed in the endpoint, causing it to run on
all requests including APIs. Moved to :browser pipeline where it belongs,
and removed redundant fetch_session call since the pipeline handles it.
2026-02-01 11:15:51 -06:00
d05c493943
Add CaptureTimezone plug to browser pipeline 2026-02-01 11:10:34 -06:00
e0552ac97d add security headers 2026-01-29 10:33:24 -06:00
756a6b4cd4
poller agent fix and trigger device rediscovery 2026-01-26 14:51:32 -06:00
eb91798729
agent improvements and agent config 2026-01-16 17:26:51 -06:00
ae521d2108
Fix protobuf body parsing causing 400 errors on agent heartbeat
Plug.Parsers was trying to parse protobuf bodies as JSON, failing with
400 errors before the request reached the controller.

Changes:
- Added custom BodyReader to endpoint that skips parsing for protobuf
- When Content-Type is application/x-protobuf, return empty body to parser
- Controller reads the raw body directly for protobuf requests
- Added error handling for protobuf decode failures in heartbeat endpoint

This fixes the 400 errors agents were seeing on heartbeat requests.
2026-01-14 18:35:20 -06:00
fd317770fe
Fix health check logging with dynamic log level in endpoint
Use Plug.Telemetry's dynamic log level feature to disable logging for
/health requests. This is the proper Phoenix way to exclude specific
endpoints from request logs.

- Add log_level/1 function to endpoint that returns false for /health
- Configure Plug.Telemetry to use dynamic log level
- Remove log: false from router (handled by endpoint now)

This prevents Kubernetes health probe spam in application logs.
2026-01-06 13:57:32 -06:00
ba463dc5a2
init 2025-12-21 11:10:43 -06:00