Files
Remote-Terminal-for-MeshCore/app/AGENTS.md

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

  1. Radio emits events.
  2. on_rx_log_data stores raw packet and tries decrypt/pipeline handling.
  3. Decrypted messages are inserted into messages and broadcast over WS.
  4. CONTACT_MSG_RECV is a fallback DM path when packet pipeline cannot decrypt.

Outgoing messages

  1. Send endpoints in routers/messages.py call MeshCore commands.
  2. Message is persisted as outgoing.
  3. Endpoint broadcasts WS message event so all live clients update.
  4. ACK/repeat updates arrive later as message_acked events.

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/unreads returns counts, mention flags, and last_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).
  • 0 means disabled.
  • Last send time tracked in app_settings.last_advert_time.

API Surface (all under /api)

Health

  • GET /health

Radio

  • GET /radio/config
  • PATCH /radio/config
  • PUT /radio/private-key
  • POST /radio/advertise
  • POST /radio/reboot
  • POST /radio/reconnect

Contacts

  • GET /contacts
  • GET /contacts/{public_key}
  • POST /contacts
  • DELETE /contacts/{public_key}
  • POST /contacts/sync
  • POST /contacts/{public_key}/add-to-radio
  • POST /contacts/{public_key}/remove-from-radio
  • POST /contacts/{public_key}/mark-read
  • POST /contacts/{public_key}/telemetry
  • POST /contacts/{public_key}/command
  • POST /contacts/{public_key}/trace

Channels

  • GET /channels
  • GET /channels/{key}
  • POST /channels
  • DELETE /channels/{key}
  • POST /channels/sync
  • POST /channels/{key}/mark-read

Messages

  • GET /messages
  • POST /messages/direct
  • POST /messages/channel

Packets

  • GET /packets/undecrypted/count
  • POST /packets/decrypt/historical
  • POST /packets/maintenance

Read state

  • GET /read-state/unreads
  • POST /read-state/mark-all-read

Settings

  • GET /settings
  • PATCH /settings
  • POST /settings/favorites/toggle
  • POST /settings/migrate

WebSocket

  • WS /ws

WebSocket Events

  • health
  • contacts
  • channels
  • contact
  • message
  • message_acked
  • raw_packet
  • error
  • success

Initial WS connect sends health only. Contacts/channels are loaded by REST.

Data Model Notes

Main tables:

  • contacts
  • channels
  • messages
  • raw_packets
  • app_settings

app_settings fields in active model:

  • max_radio_contacts
  • experimental_channel_double_send
  • favorites
  • auto_decrypt_dm_on_advert
  • sidebar_sort_order
  • last_message_times
  • preferences_migrated
  • advert_interval
  • last_advert_time
  • bots

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.py
  • tests/test_event_handlers.py
  • tests/test_send_messages.py
  • tests/test_radio.py
  • tests/test_api.py
  • tests/test_migrations.py

Editing Checklist

When changing backend behavior:

  1. Update/add router and repository tests.
  2. Confirm WS event contracts when payload shape changes.
  3. Run PYTHONPATH=. uv run pytest tests/ -v.
  4. If API contract changed, update frontend types and AGENTS docs.