Add more warnings around radio config, stats loading, and packet decrypt (and remove accidentally committed script whoops)

This commit is contained in:
Jack Kingsman
2026-03-02 16:46:18 -08:00
parent 79db09bd15
commit d8294a8383
6 changed files with 43 additions and 46 deletions
+3 -2
View File
@@ -171,8 +171,9 @@ This message-layer echo/path handling is independent of raw-packet storage dedup
│ └── vite.config.ts │ └── vite.config.ts
├── scripts/ ├── scripts/
│ ├── all_quality.sh # Run all lint, format, typecheck, tests, build (parallelized) │ ├── all_quality.sh # Run all lint, format, typecheck, tests, build (parallelized)
│ ├── publish.sh # Version bump, changelog, docker build & push │ ├── collect_licenses.sh # Gather third-party license attributions
── deploy.sh # Deploy to production server ── e2e.sh # End-to-end test runner
│ └── publish.sh # Version bump, changelog, docker build & push
├── tests/ # Backend tests (pytest) ├── tests/ # Backend tests (pytest)
├── data/ # SQLite database (runtime) ├── data/ # SQLite database (runtime)
└── pyproject.toml # Python dependencies └── pyproject.toml # Python dependencies
-17
View File
@@ -153,23 +153,6 @@ Misc: Always flood advertisements
Misc: Better packet dupe handling Misc: Better packet dupe handling
Misc: Dead code cleanup, test improvements Misc: Dead code cleanup, test improvements
## [1.8.0] - 2026-02-07
Feature: Single hop ping
Feature: PWA viewport fixes(thanks @rgregg)
Feature (?): No frontend distribution; build it yourself ;P
Bugfix: Fix channel message send race condition (concurrent sends could corrupt shared radio slot)
Bugfix: Fix TOCTOU race in radio reconnect (duplicate connections under contention)
Bugfix: Better guarding around reconnection
Bugfix: Duplicate websocket connection fixes
Bugfix: Settings tab error cleanliness on tab swap
Bugfix: Fix path traversal vuln
UI: Swap visualizer legend ordering (yay prettier)
Misc: Perf and locking improvements
Misc: Always flood advertisements
Misc: Better packet dupe handling
Misc: Dead code cleanup, test improvements
## [1.7.1] - 2026-02-03 ## [1.7.1] - 2026-02-03
Feature: Clickable hyperlinks Feature: Clickable hyperlinks
+7
View File
@@ -518,6 +518,13 @@ async def process_raw_packet(
payload_type = packet_info.payload_type if packet_info else None payload_type = packet_info.payload_type if packet_info else None
payload_type_name = payload_type.name if payload_type else "Unknown" payload_type_name = payload_type.name if payload_type else "Unknown"
if packet_info is None and len(raw_bytes) > 2:
logger.warning(
"Failed to parse %d-byte packet (id=%d); stored undecrypted",
len(raw_bytes),
packet_id,
)
# Log packet arrival at debug level # Log packet arrival at debug level
path_hex = packet_info.path.hex() if packet_info and packet_info.path else "" path_hex = packet_info.path.hex() if packet_info and packet_info.path else ""
logger.debug( logger.debug(
@@ -103,18 +103,36 @@ export function SettingsRadioSection({
const handleSave = async () => { const handleSave = async () => {
setError(null); setError(null);
const parsedLat = parseFloat(lat);
const parsedLon = parseFloat(lon);
const parsedTxPower = parseInt(txPower, 10);
const parsedFreq = parseFloat(freq);
const parsedBw = parseFloat(bw);
const parsedSf = parseInt(sf, 10);
const parsedCr = parseInt(cr, 10);
if (
[parsedLat, parsedLon, parsedTxPower, parsedFreq, parsedBw, parsedSf, parsedCr].some(
(v) => isNaN(v)
)
) {
setError('All numeric fields must have valid values');
return;
}
setBusy(true); setBusy(true);
try { try {
const update: RadioConfigUpdate = { const update: RadioConfigUpdate = {
lat: parseFloat(lat), lat: parsedLat,
lon: parseFloat(lon), lon: parsedLon,
tx_power: parseInt(txPower, 10), tx_power: parsedTxPower,
radio: { radio: {
freq: parseFloat(freq), freq: parsedFreq,
bw: parseFloat(bw), bw: parsedBw,
sf: parseInt(sf, 10), sf: parsedSf,
cr: parseInt(cr, 10), cr: parsedCr,
}, },
}; };
await onSave(update); await onSave(update);
@@ -6,10 +6,12 @@ import type { StatisticsResponse } from '../../types';
export function SettingsStatisticsSection({ className }: { className?: string }) { export function SettingsStatisticsSection({ className }: { className?: string }) {
const [stats, setStats] = useState<StatisticsResponse | null>(null); const [stats, setStats] = useState<StatisticsResponse | null>(null);
const [statsLoading, setStatsLoading] = useState(false); const [statsLoading, setStatsLoading] = useState(false);
const [statsError, setStatsError] = useState(false);
useEffect(() => { useEffect(() => {
let cancelled = false; let cancelled = false;
setStatsLoading(true); setStatsLoading(true);
setStatsError(false);
api.getStatistics().then( api.getStatistics().then(
(data) => { (data) => {
if (!cancelled) { if (!cancelled) {
@@ -18,7 +20,10 @@ export function SettingsStatisticsSection({ className }: { className?: string })
} }
}, },
() => { () => {
if (!cancelled) setStatsLoading(false); if (!cancelled) {
setStatsError(true);
setStatsLoading(false);
}
} }
); );
return () => { return () => {
@@ -145,6 +150,8 @@ export function SettingsStatisticsSection({ className }: { className?: string })
</> </>
)} )}
</div> </div>
) : statsError ? (
<div className="py-8 text-center text-muted-foreground">Failed to load statistics.</div>
) : null} ) : null}
</div> </div>
); );
-19
View File
@@ -1,19 +0,0 @@
#!/bin/bash
set -e
# Colors for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${YELLOW}Deploying to production server...${NC}"
ssh jack@192.168.1.199 "\
cd /opt/remoteterm/ && \
sudo -u remoteterm git checkout main && \
sudo -u remoteterm git pull && \
cd frontend && \
sudo -u remoteterm bash -c 'source ~/.nvm/nvm.sh && npm install && npm run build' && \
sudo systemctl restart remoteterm && \
sudo journalctl -u remoteterm -f"
echo -e "${GREEN}=== Deploy complete! ===${NC}"