Update CLAUDEs

This commit is contained in:
Jack Kingsman
2026-01-13 14:48:32 -08:00
parent b705f89a09
commit 888dd0f1a8
3 changed files with 78 additions and 4 deletions
+5
View File
@@ -92,6 +92,7 @@ A web interface for MeshCore mesh radio networks. The backend connects to a Mesh
│ │ ├── useWebSocket.ts # WebSocket hook
│ │ └── components/
│ │ ├── CrackerPanel.tsx # WebGPU key cracking
│ │ ├── MapView.tsx # Leaflet map showing node locations
│ │ └── ...
│ └── vite.config.ts
├── references/meshcore_py/ # MeshCore Python library
@@ -206,6 +207,10 @@ All endpoints are prefixed with `/api` (e.g., `/api/health`).
| POST | `/api/messages/direct` | Send direct message |
| POST | `/api/messages/channel` | Send channel message |
| POST | `/api/packets/decrypt/historical` | Decrypt stored packets |
| GET | `/api/packets/decrypt/progress` | Get historical decryption progress |
| POST | `/api/packets/maintenance` | Delete old packets (cleanup) |
| POST | `/api/packets/dedup` | Remove duplicate raw packets |
| GET | `/api/packets/dedup/progress` | Get deduplication progress |
| POST | `/api/contacts/{key}/mark-read` | Mark contact conversation as read |
| POST | `/api/channels/{key}/mark-read` | Mark channel as read |
| POST | `/api/read-state/mark-all-read` | Mark all conversations as read |
+44
View File
@@ -331,6 +331,50 @@ KeyStore.clear_private_key()
- Never logged
- Lost on server restart (must re-export from radio)
## Advertisement Parsing (`decoder.py`)
Advertisement packets contain contact information including optional GPS coordinates.
### Packet Structure
```
Bytes 0-31: Public key (32 bytes)
Bytes 32-35: Timestamp (4 bytes, little-endian Unix timestamp)
Bytes 36-99: Signature (64 bytes)
Byte 100: App flags
Bytes 101+: Optional fields (location, name) based on flags
```
### App Flags (byte 100)
- Bits 0-3: Device role (1=Chat, 2=Repeater, 3=Room, 4=Sensor)
- Bit 4: Has location (lat/lon follow)
- Bit 5: Has feature 1
- Bit 6: Has feature 2
- Bit 7: Has name (null-terminated string at end)
### GPS Extraction
When bit 4 is set, latitude and longitude follow as signed int32 little-endian values,
divided by 1,000,000 to get decimal degrees:
```python
from app.decoder import parse_advertisement
advert = parse_advertisement(payload_bytes)
if advert:
print(f"Device role: {advert.device_role}") # 1=Chat, 2=Repeater
if advert.lat and advert.lon:
print(f"Location: {advert.lat}, {advert.lon}")
```
### Data Flow
1. `event_handlers.py` receives ADVERTISEMENT event
2. `packet_processor.py` calls `parse_advertisement()` to extract data
3. Contact is upserted with location data (`lat`, `lon`) and `device_role` as `type`
4. Frontend MapView displays contacts with GPS coordinates
## ACK and Repeat Detection
The `acked` field is an integer count, not a boolean:
+29 -4
View File
@@ -12,6 +12,7 @@ This document provides context for AI assistants and developers working on the R
- **shadcn/ui components** - Sheet, Tabs, Button (in `components/ui/`)
- **meshcore-hashtag-cracker** - WebGPU-accelerated channel key bruteforcing
- **nosleep.js** - Prevents device sleep during cracking
- **leaflet / react-leaflet** - Interactive map for node locations
## Directory Structure
@@ -41,9 +42,11 @@ frontend/
│ │ ├── MessageInput.tsx # Text input with imperative handle
│ │ ├── ContactAvatar.tsx # Contact profile image component
│ │ ├── RawPacketList.tsx # Raw packet feed display
│ │ ├── CrackerPanel.tsx # WebGPU channel key cracker
│ │ ├── MapView.tsx # Leaflet map showing node locations
│ │ ├── CrackerPanel.tsx # WebGPU channel key cracker (lazy-loads wordlist)
│ │ ├── NewMessageModal.tsx
│ │ ── ConfigModal.tsx # Radio config + app settings
│ │ ── ConfigModal.tsx # Radio config + app settings
│ │ └── MaintenanceModal.tsx # Database maintenance (cleanup, dedup)
│ └── test/
│ ├── setup.ts # Test setup (jsdom, matchers)
│ ├── messageParser.test.ts
@@ -204,8 +207,8 @@ interface Message {
}
interface Conversation {
type: 'contact' | 'channel' | 'raw';
id: string; // PublicKey for contacts, ChannelKey for channels
type: 'contact' | 'channel' | 'raw' | 'map';
id: string; // PublicKey for contacts, ChannelKey for channels, 'raw'/'map' for special views
name: string;
}
@@ -566,6 +569,7 @@ Deep linking to conversations via URL hash:
- `#channel/RoomName` - Opens a channel (leading `#` stripped from name for cleaner URLs)
- `#contact/ContactName` - Opens a DM
- `#raw` - Opens the raw packet feed
- `#map` - Opens the node map
```typescript
// Parse hash on initial load
@@ -604,6 +608,27 @@ const maxLengthRef = useRef(6);
Progress reporting shows rate in Mkeys/s or Gkeys/s depending on speed.
## MapView
The `MapView` component displays contacts with GPS coordinates on an interactive Leaflet map.
### Features
- **Location filtering**: Only shows contacts with lat/lon that were heard within the last 7 days
- **Freshness coloring**: Markers colored by how recently the contact was heard:
- Bright green (`#22c55e`) - less than 1 hour ago
- Light green (`#4ade80`) - less than 1 day ago
- Yellow-green (`#a3e635`) - less than 3 days ago
- Gray (`#9ca3af`) - older (up to 7 days)
- **Node/repeater distinction**: Regular nodes have black outlines, repeaters are larger with no outline
- **Geolocation**: Tries browser geolocation first, falls back to fitting all markers in view
- **Popups**: Click a marker to see contact name, last heard time, and coordinates
### Data Source
Contact location data (`lat`, `lon`) is extracted from advertisement packets in the backend (`decoder.py`).
The `last_seen` timestamp determines marker freshness.
## Sidebar Features
- **Sort toggle**: Default is 'recent' (most recent message first), can toggle to alphabetical