Commit graph

1582 commits

Author SHA1 Message Date
4e92bbfc9f
docs: supervision tree ownership map, naming issues documented
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
- Mapped 18 top-level children + 2 nested supervisors in application.ex
- Ownership: Is->PacketPipelineSupervisor (ingestion), PartitionManager (retention),
  SpatialPubSub (broadcast), CleanupScheduler+PacketCleanupWorker (bad-packet cleanup)
- Removed Exq comment fossil from application.ex:72
- Known naming issues: PacketCleanupWorker only handles bad_packets,
  PostgresNotifier scope narrower than name, PacketConsumer is 776-line multi-concern
- Handoff document: marked maintainability #2 as done
2026-07-26 14:59:55 -05:00
a4991c1401
docs: callsign naming distinction, test coverage review, handoff updates
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
- Aprsme.Callsign: enhanced @moduledoc with explicit AX.25 vs transport-safe
  identifier distinction, four validation layers documented
- Test coverage review: confirmed no gaps from deleted packet_pipeline_integration_test
  All ingestion scenarios covered across 5 test files; 2491 passed, 0 failures
- Handoff document: marked maintainability #4 (callsign naming), #6 (test coverage) as done
2026-07-26 14:57:42 -05:00
9ba4dac53a
maintainability: obsolete config cleanup, focused migration tests
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
- Removed stale .dialyzer_ignore.exs entry for deleted packet_replay_test.exs
- Removed orphaned :initialize_replay_delay config key from test.exs
- Updated CLAUDE.md: StreamingPacketsPubSub -> SpatialPubSub
- Added migration_validation_test.exs: 12 tests covering geometry GiST indexes,
  counter reconciliation, and partition boundary cutoff behavior
- Updated handoff document: marked maintainability #3 and #5 as done
2026-07-26 14:15:39 -05:00
9f45937a82
security: sobelow triage, admin route review, k8s secrets hardening
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
- Admin route authorization: all routes verified with dual protection, negative tests exist
- Sobelow: regenerated .sobelow-skips (14 documented findings, no stale entries)
- k8s: moved APRS_PASSWORD to APRS_PASSCODE secretKeyRef in deployment
- Handoff document: marked remaining security items #4-6 as done
2026-07-26 14:08:27 -05:00
0f2195ef9d
security: CSP nonces, RemoteIp CIDR gating, rate limiting, NetworkPolicies, deadlock fixes
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
- Content-Security-Policy: nonce-based per-request plug replacing unsafe-inline scripts
- RemoteIp: CIDR-based trust gating via InetCidr, skips forwarded headers from untrusted peers
- Rate limiting: auth pipeline (20/min), LiveView event handlers, existing mobile channel limits
- NetworkPolicy: 4 k8s policies (web ingress, cluster, metrics, egress) for least-privilege networking
- PartitionManager: deadlock retry with exponential backoff in drop_partition
- Tests: reduced parallelism (max_cases 4), packets_test async:false to prevent trigger contention
- k8s: APRS_PASSWORD -> APRS_PASSCODE secretRef, vendor/aprs submodule hardened
2026-07-26 14:04:56 -05:00
b0832e5a9c
refactor: harden packet delivery and operations
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
2026-07-26 13:11:26 -05:00
101dcf4005
bugfixes
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
2026-07-25 15:39:46 -05:00
edeb8402db
replace codeberg.org references with git.mcintire.me
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
2026-07-25 09:29:16 -05:00
8271015a16
Migrate k8s images from codeberg.org to git.mcintire.me
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 2s
2026-07-24 14:39:01 -05:00
52dcb23f57 Use Kaniko for Docker builds
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 1s
2026-07-24 14:36:03 -05:00
08262024d7 Migrate from codeberg.org to git.mcintire.me
All checks were successful
Build and Push / Build and Push Docker Image (push) Successful in 2m10s
2026-07-24 14:23:22 -05:00
7e1498bf4e
perf: batch high-frequency LiveView updates via socket.private
Some checks failed
Build and Push / Build and Push Docker Image (push) Failing after 50s
Buffer incoming packets in socket.private (no rerender) and flush to
assigns/stream on a 150ms timer, preventing client-side morphdom from
being overwhelmed during traffic bursts. Applies to the global packet
feed (stream) and per-callsign detail view (assigns).
2026-07-22 11:23:09 -05:00
Graham McInitre
0e322a2403 docs: add structured documentation covering architecture, contexts, web, infra, and dev setup 2026-07-21 11:01:27 -05:00
Graham McInitre
1006fdaefc refactor: remove dead code, duplication, and over-abstractions
- Delete dead config keys and test file (typo'd aprsme_is_*, vacuous disable test)
- Remove duplicate function clauses and identical function pairs
- Rename misleading one_hour_ago variable to one_day_ago
- Strip stale Oban comment
- Remove TestHelpers time function duplicates
- Inline Aprsme.Schema module (only 1 caller)
- Deduplicate prod esbuild config
- Thin SymbolRenderer delegations, inline TimeUtils wrappers
- Remove redundant DeploymentNotifier GenServer polling
- Replace random fallback in get_callsign_key with sentinel
2026-07-21 10:36:49 -05:00
Graham McInitre
243a98df77 fix: security hardening and query performance improvements
- Session cookie: add encryption_salt and secure flag to endpoint
- CSP: remove unsafe-eval from script-src directive
- /metrics: wrap PromEx endpoint behind rate-limited pipeline
- LiveView signing_salt: move to env var in production config
- LiveView performance: defer heavy aggregation queries past initial mount
- SQL: replace correlated subquery with DISTINCT ON in get_heard_by_stations
2026-07-21 10:13:30 -05:00
Graham McInitre
b88eb9e584 chore: update mix deps (circular_buffer, elixir_make, lazy_html) 2026-07-21 08:55:42 -05:00
Graham McInitre
bb73c17ce6 chore: commit shared .envrc, gitignore .envrc.local for secrets 2026-07-21 08:53:35 -05:00
77d2a6ca30
updat edeps 2026-07-17 16:42:53 -05:00
281aef095c
fix: resolve all credo warnings and pre-existing dialyzer errors
- Move require Logger to module top level in SpatialPubSub
- Replace weak is_list assertions with stronger checks
- Remove redundant 'is a list' test in PromEx tests
- Replace apply/3 with direct function call in packet_replay test
- Fix unmatched_return in weather_cache.ex and callsign_view.ex
2026-07-17 16:41:15 -05:00
7bdf21fb53
deps: ecto_sql 3.13→3.14, prom_ex 1.11→1.12, decimal 2.4→3.1, ecto 3.13→3.14; bump test pool for sandbox 2026-07-08 10:46:05 -05:00
62bbeaadb3
deps: update phoenix 1.8.8→1.8.9, swoosh 1.26.2→1.26.3; cleanup test assertions 2026-07-08 10:28:18 -05:00
088fd20711
refactor: FP patterns in packets_live/callsign_view
- mount: extract subscribe_if_connected/2, split assign_valid/assign_invalid
  to eliminate inline if/else for validation + subscription logic.

- enrich_packet_with_device_identifier: extract resolve_canonical_identifier/1
  as multi-clause function (binary guard + catch-all) instead of nested if.

- update_packet_lists: cond → multi-clause do_update/4 with guards.
  Three explicit paths: at-cap no-stored, at-cap with-stored, under-cap.

- get_timestamp_microseconds: case → multi-clause (%DateTime{}, binary,
  catch-all) for cleaner dispatch.
2026-07-01 18:08:56 -05:00
80983e6223
fix: repair all 60 failing tests after refactor and dep updates
- IS GenServer: add missing :failure_started_at to test build_state/1 map
- IS GenServer: fix stale status server assertion and reconnection test
- IS GenServer: set Logger level to :debug for dispatch parse-error tests
- PacketReplay: remove conflicting Registry start_supervised! from setup
- PacketReplay: update assertion from {:continue_replay} to :start_replay
- Doctests: fix float precision, stale sprite coords, quoting escapes
- API controllers: use string keys for JSON error/postion details
- PacketUtils: fix operator precedence (not is_nil(result).field)
- ThemeManager: update expected dark theme text color
- StatusLive: remove/update stale :loading assign assertions
- Movement: remove {:ok, _v} wrapper from render_hook/3 (returns HTML)
- AprsIsMock: update packet_stats assertion for populated default shape
2026-07-01 09:41:10 -05:00
01ecf3d6bc
refactor: apply functional programming patterns across codebase
- accounts.ex: replace validate_user_password (if-based) with with-chain;
  drop unnecessary try/rescue around Repo.get_by. Extract transaction_unwrap
  helper to eliminate 3 copies of the Multi result-unwrap case block.

- packets.ex: deduplicate store_bad_packet by extracting raw_packet_string,
  extract_error_type, and extract_error_message into composable helpers.
  Normalize find_coordinate_value — collapse 12 clauses into a generic
  deep_get/direct_get that handles atom/string keys and nested maps uniformly.

- data_builder.ex: split build_simple_popup into separate data-construction
  (build_simple_popup_data) and rendering (render_popup) phases, eliminating
  duplicated PopupComponent/Safe/IO pipelines.

- param_utils.ex: unify parse_float_in_range and parse_int_in_range via a
  shared parse_in_range that accepts Float.parse/Integer.parse as a function
  parameter — functions-as-values pattern.
2026-07-01 08:45:19 -05:00
bc60fec98c
deps: update all dependencies and fix doctests for Elixir 1.20
- Update 9 Hex packages (bandit, credo, finch, phoenix, phoenix_live_view,
  plug, req, swoosh, tidewave)
- Load bad_packets data unconditionally in mount/3 so crawlers and link
  previews see content instead of an empty page
- Fix Accounts doctests: use concrete values instead of unbound variables,
  disable illustrative doctests broken by Elixir 1.20.2 strictness
2026-07-01 08:40:17 -05:00
07cb40f0c2
elixir bump 2026-06-23 09:39:57 -05:00
6eda1c0290
fix: resolve 19 bugs across Elixir, JS/TS, and config
Critical:
- Remove :protected from WeatherCache ETS (conflicted with :public)
- Register Aprsme.ReplayRegistry in supervision tree
- Route :continue_replay dead message to :start_replay handler
- Add 5000ms timeout to unbounded :rpc.call calls
- Fix falsy lat/lng check rejecting valid 0 coordinates

Medium:
- Fix live_reload pattern (temp_web -> aprsme_web)
- Remove duplicate ecto_repos config
- Make DB SSL configurable via DB_SSL env var
- Track sizeCheckTimeout on self for cleanup in destroyed()
- Wrap pushEvent calls in try/catch
- Remove unused size variable in marker cluster icon
- Capture touch coords at touchstart instead of stale TouchEvent
- Demote console.log to console.debug in production code
- Add catch-all to normalize_bounds preventing GenServer crash

Style:
- Add missing @impl true annotations in is.ex
- Improve migration failure error message
- Use textContent instead of innerHTML for error messages
- Use proper type for longPressTimer instead of any
2026-06-21 11:47:07 -05:00
b86153cd27
Fix all mix credo --strict warnings (188 → 0)
- Replace apply/2 with direct fully-qualified calls in movement_test
- Fix assert_receive timeouts < 1000ms across 8 test files
- Move nested import statements to module-level scope
- Fix tests with no assertions and add missing doctest
- Replace weak type assertions with specific value checks
- Fix conditional assertions and length/1 expensive patterns
- Disable inappropriate Jump.CredoChecks.AvoidSocketAssignsInTest
- Fix tests not calling application code with credo:disable
- Add various credo:disable comments for legitimate patterns
2026-06-12 16:27:20 -05:00
17838f05d3
Add Plausible Analytics server-side tracking and API Prometheus metrics 2026-06-04 19:37:54 -05:00
0c90a47f9a
update stuff 2026-06-04 18:00:03 -05:00
274af1ce93
Add W5ISP attribution and QRZ link to about page 2026-06-04 17:30:56 -05:00
32fca73d3a
Fix JSON punctuation highlighting inside string values 2026-06-04 17:01:36 -05:00
0a4f921fd9
Format JSON examples with proper indentation and syntax highlighting 2026-06-04 16:53:22 -05:00
2dc42a6cb7
update robots.txt 2026-06-04 16:34:49 -05:00
1ef9e00a05
update robots.txt 2026-06-04 16:33:12 -05:00
f2c8f7020c
update robots.txt 2026-06-04 16:29:53 -05:00
2e0529ee75
update robots.txt 2026-06-04 16:26:13 -05:00
5569d8e2a0
Add user-agent to request logging metadata 2026-06-04 16:19:47 -05:00
6d190bc98e
cleanup todo 2026-06-04 16:14:40 -05:00
c3921e9277
Add Plausible analytics snippet to root layout 2026-06-04 16:05:24 -05:00
1eceb3664d
fix: install libsctp1 to silence Erlang 29 SCTP warning 2026-06-04 15:39:40 -05:00
a4b140beaf
chore: update elixir/erlang versions, remove renovate forgejo task, update deps 2026-06-04 15:33:50 -05:00
e8d48f8058
speed up slow tests: remove Process.sleep, add batch fixture helper
- Replace Process.sleep(N) with explicit synchronization:
  render(view) to force LV mailbox drain, PubSub assert_receive for
  leader election, and render_hook sync guarantees
- Add batch_packet_fixtures/2 using Repo.insert_all for bulk test
  fixtures (200 inserts -> 1 round trip)
- Remove sleeps from historical_loading_test — tests query DB
  directly, don't need LV async processing
2026-06-02 15:02:07 -05:00
73c6703102
perf: debounce BadPacketsLive refresh, remove stale test cases
Coalesce rapid PubSub notifications into single 2-second delayed DB query. Remove tests for removed :update_time_display handler.

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-01 16:50:28 -05:00
3169abf0f0
perf: convert packets_live table to streams for efficient diffs
Replace full-list assign with stream_insert + phx-update=stream. Add DOM IDs to all packet rows. Skip deprecated phx-update=prepend.

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-01 16:50:09 -05:00
ff3a478bbd
perf: add LIMIT to unbounded DISTINCT ON, guard device table scan, add DB indexes
Bound batch DISTINCT ON queries by input count. Guard Repo.all(Devices) with exists? check. Add trigram GIN index on base_callsign and (has_weather, received_at DESC) partial index.

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-01 16:49:48 -05:00
7f814462ed
perf: reduce traversals, optimize packet field lookups, use has_weather boolean
Remove redundant in-memory sort (DB already orders), shortcut get_packet_field when field found at top level, use pre-computed has_weather boolean instead of field-by-field scan

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-01 16:49:28 -05:00
e02fafc8da
perf: optimize map LiveView hot paths
Remove unused 30s timer, skip heatmap recluster on every single packet, trail dedup O(n^2)->O(n)

Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-01 16:49:08 -05:00
ae1194ebb0
perf: fix PacketBatcher O(n) length/1 to O(1) counter
Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-01 16:48:48 -05:00
21ab9fb20c
perf: add persistent ETS weather cache for N+1 prevention
Ultraworked with Sisyphus

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-06-01 16:48:28 -05:00