v3.4.2 Release Test Plan
Scope: 90 commits since v3.4.1 (84 files, +14,931 / -1,005)
Categories: 19 perf, 19 feat, 18 fix, 15 docs, 3 chore, 1 test, 1 refactor, 1 ci
Date: 2026-04-08
A. Automated Tests — Verify All Pass
Go Backend
Test files (27 total):
| File |
Tests For |
cmd/server/decoder_test.go |
Hash size zero-hop, TRACE hopsCompleted, transport direct |
cmd/server/backfill_async_test.go |
NEW — Async chunked backfill |
cmd/server/eviction_test.go |
Memory eviction with runtime heap stats |
cmd/server/apikey_security_test.go |
NEW — Weak/default API key rejection |
cmd/server/openapi_test.go |
NEW — OpenAPI spec generation |
cmd/server/routes_test.go |
Batch observations endpoint, subpaths-bulk, expand=observations |
cmd/server/cache_invalidation_test.go |
cacheTTL config wiring |
cmd/server/config_knobs_test.go |
cacheTTLSec helper |
cmd/server/helpers_test.go |
constantTimeEqual, IsWeakAPIKey |
cmd/server/obs_dedup_test.go |
UniqueObserverCount tracking |
cmd/server/neighbor_*.go (4 files) |
Neighbor graph, affinity, persistence |
cmd/server/perfstats_race_test.go |
Perf stats concurrency |
cmd/server/resolve_context_test.go |
Resolved path filtering |
cmd/server/advert_pubkey_test.go |
Advert pubkey tracking |
cmd/server/db_test.go |
SQLite operations |
cmd/server/config_test.go |
Config loading |
cmd/server/coverage_test.go |
Coverage helpers |
cmd/server/parity_test.go |
Go/JS decoder parity |
cmd/server/websocket_test.go |
WebSocket broadcast |
cmd/ingestor/decoder_test.go |
Ingestor decoder (hash size zero-hop) |
cmd/ingestor/db_test.go |
Ingestor DB writes |
cmd/ingestor/config_test.go |
Ingestor config |
cmd/ingestor/main_test.go |
Ingestor entry |
cmd/ingestor/coverage_boost_test.go |
Coverage helpers |
Frontend Unit Tests
E2E / Playwright
Expected: All existing tests pass + new tests added for sortable tables, deep linking, collapsible panels.
B. Manual Browser Verification
B1. HIGH RISK — Data Correctness
| # |
Feature |
Page |
What to Check |
| 1 |
Hash size zero-hop |
Packets detail |
Find a direct (route_type=0) packet → hash_size should show 0, not a bogus computed value |
| 2 |
TRACE hopsCompleted |
Packets detail / Live map |
Find a TRACE packet → verify hopsCompleted shows in decoded JSON, live map shows real path length vs intended |
| 3 |
Transport direct hash size |
Packets detail |
Find route_type=RouteTransportDirect packet → hash_size=0 |
| 4 |
resolved_path filtering |
Node detail → Paths tab |
Verify path-hop candidates use resolved_path, no prefix collision false positives |
| 5 |
Hash stats repeater filter |
Analytics → Hash Issues |
"By Repeaters" should only show nodes with repeater role, not companions/sensors |
| 6 |
Async chunked backfill |
Server startup |
Start server with large DB → verify HTTP serves within 2 minutes, X-CoreScope-Status: backfilling header present, then transitions to ready |
| 7 |
Memory eviction (heap stats) |
Admin/stats |
Verify /api/stats shows realistic memory numbers from runtime heap, not the old estimation |
| 8 |
Distance/subpath/path-hop indexes |
Analytics → Distances, Subpaths |
Verify analytics data matches v3.4.1 output (no missing or extra entries) |
| 9 |
cacheTTL config wiring |
Config |
Set cacheTTL.analyticsHashSizes: 300 in config → verify collision cache respects it |
B2. MEDIUM RISK — User-Facing Features
| # |
Feature |
Page |
What to Check |
| 10 |
Distance unit preference |
Nodes detail, Map |
Toggle km/mi/auto in settings → distances update throughout UI |
| 11 |
Panel corner toggle |
Live page |
Click corner toggle → panel moves to opposite corner, persists on reload |
| 12 |
Noise floor column chart |
Analytics → RF |
Verify column chart renders with color-coded thresholds, hover shows values |
| 13 |
Deep linking UI states |
All pages |
Navigate to #/nodes?tab=neighbors, #/packets?observer=X, #/channels?node=Y → correct state loads. Copy URL, open in new tab → same state |
| 14 |
Sortable tables |
Nodes list, Neighbors, Observers |
Click column headers → sort asc/desc, indicator arrow shows, persists correctly |
| 15 |
Channel color highlighting |
Channels, Live feed |
Assign color to channel → feed rows show that color, persists on reload |
| 16 |
Mobile accessibility |
All pages (phone viewport) |
Touch targets ≥44px, ARIA labels present, small viewport doesn't overflow |
| 17 |
Collapsible panels |
Live map |
Collapse/expand panels, medium breakpoint auto-collapses, state persists |
| 18 |
Byte-size map filter |
Map page |
Filter by byte size → markers update correctly |
| 19 |
OpenAPI/Swagger |
/api/spec, /api/docs |
Spec loads valid JSON, Swagger UI renders and all endpoints are documented |
| 20 |
API key rejection |
Protected endpoints |
Send weak key (e.g. "changeme", "test123") → 403 forbidden |
| 21 |
Channel color picker mobile |
Channels (phone viewport) |
Color picker usable on touch, doesn't overflow |
| 22 |
RF Health dashboard |
Analytics → RF Health |
Observer metrics grid, airtime charts, battery charts, error rate, region filter |
| 23 |
Prefix Tool tab |
Analytics → Prefix Tool |
Renders correctly, collision data consistent with Hash Issues |
| 24 |
View Route on Map |
Packet detail page |
Button works and shows route on map |
B3. LOWER RISK — Performance (Verify No Regressions)
| # |
Feature |
Page |
What to Check |
| 25 |
Incremental DOM diff |
Packets (30K+) |
Virtual scroll renders smoothly, no visible flicker |
| 26 |
Coalesced WS renders |
Live page |
Rapid packets don't cause frame drops (rAF coalescing) |
| 27 |
Marker reposition on zoom |
Map |
Zoom/resize → markers move smoothly, no full rebuild flash |
| 28 |
Parallel replay fetches |
Live → VCR |
Replay loads quickly (parallel observation fetches) |
| 29 |
Batch observations API |
Packets page (sort change) |
Changing sort fetches observations in batch (network tab: 1 POST not N GETs) |
| 30 |
Client-side network status |
Analytics |
No separate API call for network status |
| 31 |
og-image compression |
/og-image.png |
Verify loads, ~235KB not ~1.1MB |
C. API Regression Tests
Run against a local server with test-fixture DB:
Expected response shape changes from v3.4.1:
/api/stats now includes backfilling (bool) and backfillProgress (float 0-1)
/api/packets no longer strips observations by default (lazy via ExpandObservations flag) — verify observations key absent without expand=observations
- Decoded packets with route_type=direct now have
hashSize: 0
- TRACE packets now have
path.hopsCompleted field
D. Performance Regression Tests
D1. Server Startup Time
D2. Go Benchmarks
Key benchmarks to compare with v3.4.1 baseline:
BenchmarkQueryPackets — should not regress with new indexes
BenchmarkEvictStale — batch removal from secondary indexes
BenchmarkGetStoreStats — 2 concurrent queries vs 5 sequential
BenchmarkIngestNew — additional index maintenance overhead
D3. Frontend Performance
- Open Packets page with 30K+ packets → measure initial render time (DevTools Performance tab)
- Scroll rapidly through virtual scroll → should maintain 60fps
- Switch sort column on packets → single batch POST, not N+1 GETs
- Open Analytics page → no redundant API calls in network tab
D4. Memory Usage
- After loading 30K packets, check
/api/stats memory figure
- Compare with v3.4.1 baseline (prefix map cap at 8 chars should reduce ~10x)
- Verify eviction triggers at correct memory threshold using runtime heap stats
E. Infrastructure / Deployment Tests
E1. Docker Build
E2. GHCR Publish (CI)
- Verify CI publishes to
ghcr.io/kpa-clawbot/corescope
- Verify tags:
edge (master), vX.Y.Z (release)
E3. Staging Deploy
E4. DISABLE_CADDY
E5. CI Pipeline
- Verify consolidated pipeline: build → publish GHCR → deploy staging
- Verify runs on
meshcore-runner-2
F. Edge Cases & Integration Tests
F1. Cross-Feature Interactions
| Scenario |
Risk |
| Deep link to sorted table → sort state matches URL params |
Medium |
| Channel color + deep link → color persists in linked URL |
Medium |
| Panel corner toggle + collapsible panels → both states persist independently |
Low |
| Distance unit pref + neighbor table sort by distance → sort uses correct unit |
Medium |
| Noise floor chart + region filter → chart respects filter |
Medium |
| Byte-size map filter + channel color highlighting → both active simultaneously |
Low |
F2. Data Correctness Edge Cases
| Scenario |
Risk |
| Zero-hop TRACE packet (should NOT reset hashSize — TRACE exemption) |
High |
| Packet with all hops having same 2-char prefix → resolved_path filtering prevents false match |
High |
| Node that switches role (repeater → companion) → hash stats updates |
Medium |
| Backfill interrupted mid-chunk (server restart) → resumes or completes on next start |
Medium |
| Empty DB startup → no errors, backfill completes instantly |
Low |
| DB with 100K+ packets → async backfill doesn't OOM, progress reported |
High |
F3. Concurrency / Race Conditions
| Scenario |
Risk |
| Concurrent API requests during backfill → no deadlock (lock ordering documented) |
High |
| Eviction running while analytics query in progress → no stale pointer panic |
High |
| Multiple WebSocket clients during high ingest rate → coalesced broadcasts don't drop |
Medium |
time.NewTicker cleanup on graceful shutdown (replaced time.Tick) |
Low |
F4. API Key Security
| Scenario |
Expected |
| No API key configured → write endpoints disabled |
403 "write endpoints disabled" |
| Weak key "changeme" → rejected even if configured |
403 "forbidden" |
| Timing-safe comparison → no timing oracle |
Constant-time via crypto/subtle |
| Empty string key → rejected |
401 "unauthorized" |
F5. Browser Compatibility
- Test on Chrome, Firefox, Safari (latest)
- Test on iOS Safari, Android Chrome
- Verify touch targets on mobile (44px minimum)
- Verify ARIA labels with screen reader
G. Test Coverage Gaps — Action Items
| Gap |
Priority |
Action |
| No automated test for distance unit preference rendering |
Medium |
Add Playwright test |
| No automated test for noise floor column chart |
Medium |
Add Playwright test |
| No automated test for deep link state restoration |
High |
Add Playwright tests for each deep-linkable state |
| No automated test for channel color persistence |
Medium |
test-channel-colors.js covers model; need Playwright for UI |
| No automated test for mobile viewport behavior |
Medium |
Add Playwright test with mobile viewport |
| No automated test for backfill progress header |
Low |
Add to routes_test.go |
No automated test for time.NewTicker cleanup |
Low |
Add to graceful shutdown test |
| Observer metrics endpoints not covered in route tests |
Medium |
Add to routes_test.go |
| Subpaths-bulk endpoint needs test |
Medium |
Add to routes_test.go |
| No load test for batch observations endpoint (200 hash limit) |
Low |
Add boundary test |
H. Release Checklist