diff --git a/app/AGENTS.md b/app/AGENTS.md index 24f5aab..2597baf 100644 --- a/app/AGENTS.md +++ b/app/AGENTS.md @@ -20,7 +20,7 @@ app/ ├── database.py # SQLite connection + base schema + migration runner ├── migrations.py # Schema migrations (SQLite user_version) ├── models.py # Pydantic request/response models -├── repository/ # Data access layer (contacts, channels, messages, raw_packets, settings) +├── repository/ # Data access layer (contacts, channels, messages, raw_packets, settings, fanout) ├── radio.py # RadioManager + auto-reconnect monitor ├── radio_sync.py # Polling, sync, periodic advertisement loop ├── decoder.py # Packet parsing/decryption @@ -29,6 +29,7 @@ app/ ├── websocket.py # WS manager + broadcast helpers ├── fanout/ # Fanout bus: MQTT, bots, webhooks, Apprise (see fanout/AGENTS_fanout.md) ├── dependencies.py # Shared FastAPI dependency providers +├── path_utils.py # Path hex rendering and hop-width helpers ├── keystore.py # Ephemeral private/public key storage for DM decryption ├── frontend_static.py # Mount/serve built frontend (production) └── routers/ @@ -296,6 +297,10 @@ tests/ ├── test_send_messages.py # Outgoing messages, bot triggers, concurrent sends ├── test_settings_router.py # Settings endpoints, advert validation ├── test_statistics.py # Statistics aggregation +├── test_channel_sender_backfill.py # Sender key backfill for channel messages +├── test_fanout_hitlist.py # Fanout-related hitlist regression tests +├── test_main_startup.py # App startup and lifespan +├── test_path_utils.py # Path hex rendering helpers ├── test_websocket.py # WS manager broadcast/cleanup └── test_websocket_route.py # WS endpoint lifecycle ``` diff --git a/app/routers/packets.py b/app/routers/packets.py index b08754b..8142e67 100644 --- a/app/routers/packets.py +++ b/app/routers/packets.py @@ -71,6 +71,7 @@ async def _run_historical_channel_decryption( timestamp=result.timestamp, received_at=packet_timestamp, path=path_hex, + path_len=packet_info.path_length if packet_info else None, realtime=False, # Historical decryption should not trigger fanout ) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index b6e3df0..6e8b9a9 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -694,7 +694,10 @@ export function App() { -
+
Raw Packet Feed -
+
diff --git a/frontend/src/components/RawPacketList.tsx b/frontend/src/components/RawPacketList.tsx index 823ff1a..4e90921 100644 --- a/frontend/src/components/RawPacketList.tsx +++ b/frontend/src/components/RawPacketList.tsx @@ -202,14 +202,14 @@ export function RawPacketList({ packets }: RawPacketListProps) { if (packets.length === 0) { return ( -
+
No packets received yet. Packets will appear here in real-time.
); } return ( -
+
{sortedPackets.map(({ packet, decoded }) => (