mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-03-28 17:43:05 +01:00
5.5 KiB
5.5 KiB
Backend AGENTS.md
This document is the backend working guide for agents and developers.
Keep it aligned with app/ source files and router behavior.
Stack
- FastAPI
- aiosqlite
- Pydantic
- MeshCore Python library (
references/meshcore_py) - PyCryptodome
Backend Map
app/
├── main.py # App startup/lifespan, router registration, static frontend mounting
├── config.py # Env-driven runtime settings
├── database.py # SQLite connection + base schema + migration runner
├── migrations.py # Schema migrations (SQLite user_version)
├── models.py # Pydantic request/response models
├── repository.py # Data access layer
├── radio.py # RadioManager + auto-reconnect monitor
├── radio_sync.py # Polling, sync, periodic advertisement loop
├── decoder.py # Packet parsing/decryption
├── packet_processor.py # Raw packet pipeline, dedup, path handling
├── event_handlers.py # MeshCore event subscriptions and ACK tracking
├── websocket.py # WS manager + broadcast helpers
├── bot.py # Bot execution and outbound bot sends
├── dependencies.py # Shared FastAPI dependency providers
├── frontend_static.py # Mount/serve built frontend (production)
└── routers/
├── health.py
├── radio.py
├── contacts.py
├── channels.py
├── messages.py
├── packets.py
├── read_state.py
├── settings.py
└── ws.py
Core Runtime Flows
Incoming data
- Radio emits events.
on_rx_log_datastores raw packet and tries decrypt/pipeline handling.- Decrypted messages are inserted into
messagesand broadcast over WS. CONTACT_MSG_RECVis a fallback DM path when packet pipeline cannot decrypt.
Outgoing messages
- Send endpoints in
routers/messages.pycall MeshCore commands. - Message is persisted as outgoing.
- Endpoint broadcasts WS
messageevent so all live clients update. - ACK/repeat updates arrive later as
message_ackedevents.
Connection lifecycle
RadioManager.start_connection_monitor()checks health every 5s.- On reconnect, monitor runs
post_connect_setup()before broadcasting healthy state. - Setup includes handler registration, key export, time sync, contact/channel sync, polling/advert tasks.
Important Behaviors
Read/unread state
- Server is source of truth (
contacts.last_read_at,channels.last_read_at). GET /api/read-state/unreadsreturns counts, mention flags, andlast_message_times.
Echo/repeat dedup
- Message uniqueness:
(type, conversation_key, text, sender_timestamp). - Duplicate insert is treated as an echo/repeat; ACK count/path list is updated.
Periodic advertisement
- Controlled by
app_settings.advert_interval(seconds). 0means disabled.- Last send time tracked in
app_settings.last_advert_time.
API Surface (all under /api)
Health
GET /health
Radio
GET /radio/configPATCH /radio/configPUT /radio/private-keyPOST /radio/advertisePOST /radio/rebootPOST /radio/reconnect
Contacts
GET /contactsGET /contacts/{public_key}POST /contactsDELETE /contacts/{public_key}POST /contacts/syncPOST /contacts/{public_key}/add-to-radioPOST /contacts/{public_key}/remove-from-radioPOST /contacts/{public_key}/mark-readPOST /contacts/{public_key}/telemetryPOST /contacts/{public_key}/commandPOST /contacts/{public_key}/trace
Channels
GET /channelsGET /channels/{key}POST /channelsDELETE /channels/{key}POST /channels/syncPOST /channels/{key}/mark-read
Messages
GET /messagesPOST /messages/directPOST /messages/channel
Packets
GET /packets/undecrypted/countPOST /packets/decrypt/historicalPOST /packets/maintenance
Read state
GET /read-state/unreadsPOST /read-state/mark-all-read
Settings
GET /settingsPATCH /settingsPOST /settings/favorites/togglePOST /settings/migrate
WebSocket
WS /ws
WebSocket Events
healthcontactschannelscontactmessagemessage_ackedraw_packeterrorsuccess
Initial WS connect sends health only. Contacts/channels are loaded by REST.
Data Model Notes
Main tables:
contactschannelsmessagesraw_packetsapp_settings
app_settings fields in active model:
max_radio_contactsexperimental_channel_double_sendfavoritesauto_decrypt_dm_on_advertsidebar_sort_orderlast_message_timespreferences_migratedadvert_intervallast_advert_timebots
Security Posture (intentional)
- No authn/authz.
- No CORS restriction (
*). - Bot code executes user-provided Python via
exec().
These are product decisions for trusted-network deployments; do not flag as accidental vulnerabilities.
Testing
Run backend tests:
PYTHONPATH=. uv run pytest tests/ -v
High-signal suites:
tests/test_packet_pipeline.pytests/test_event_handlers.pytests/test_send_messages.pytests/test_radio.pytests/test_api.pytests/test_migrations.py
Editing Checklist
When changing backend behavior:
- Update/add router and repository tests.
- Confirm WS event contracts when payload shape changes.
- Run
PYTHONPATH=. uv run pytest tests/ -v. - If API contract changed, update frontend types and AGENTS docs.