diff --git a/AGENTS.md b/AGENTS.md index bb276b0..e0c6e27 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,7 +10,7 @@ If instructed to "run all tests" or "get ready for a commit" or other summative, ./scripts/all_quality.sh ``` -This runs all linting, formatting, type checking, tests, and builds for both backend and frontend sequentially. All checks must pass green. +This is the repo's end-to-end quality gate. It runs backend/frontend autofixers first, then type checking, tests, and the standard frontend build. All checks must pass green, and the script may leave formatting/lint edits behind. ## Overview @@ -193,8 +193,8 @@ This message-layer echo/path handling is independent of raw-packet storage dedup │ │ ├── MapView.tsx # Leaflet map showing node locations │ │ └── ... │ └── vite.config.ts -├── scripts/ -│ ├── all_quality.sh # Run all lint, format, typecheck, tests, and the standard frontend build +├── scripts/ # Quality / release helpers (listing below is representative, not exhaustive) +│ ├── all_quality.sh # Repo-standard autofix + validate gate │ ├── collect_licenses.sh # Gather third-party license attributions │ ├── e2e.sh # End-to-end test runner │ └── publish.sh # Version bump, changelog, docker build & push @@ -282,7 +282,7 @@ npm run test:run ### Before Completing Changes -**Always run `./scripts/all_quality.sh` before finishing any changes that have modified code or tests.** This runs all linting, formatting, type checking, tests, and the standard frontend build sequentially, catching type mismatches, breaking changes, and compilation errors. This is not necessary for docs-only changes. +**Always run `./scripts/all_quality.sh` before finishing any changes that have modified code or tests.** It is the standard repo gate: autofix first, then type checks, tests, and the standard frontend build. This is not necessary for docs-only changes. ## API Summary diff --git a/app/AGENTS.md b/app/AGENTS.md index a5f00d0..bff1faf 100644 --- a/app/AGENTS.md +++ b/app/AGENTS.md @@ -32,6 +32,7 @@ app/ ├── services/ # Shared orchestration/domain services │ ├── messages.py # Shared message creation, dedup, ACK application │ ├── message_send.py # Direct send, channel send, resend workflows +│ ├── dm_ingest.py # Shared direct-message ingest / dedup seam for packet + fallback paths │ ├── dm_ack_tracker.py # Pending DM ACK state │ ├── contact_reconciliation.py # Prefix-claim, sender-key backfill, name-history wiring │ ├── radio_lifecycle.py # Post-connect setup and reconnect/setup helpers @@ -74,7 +75,7 @@ app/ 1. Radio emits events. 2. `on_rx_log_data` stores raw packet and tries decrypt/pipeline handling. 3. Shared message-domain services create/update `messages` and shape WS payloads. -4. `CONTACT_MSG_RECV` is a fallback DM path when packet pipeline cannot decrypt. +4. Direct-message storage is centralized in `services/dm_ingest.py`; packet-processor DMs and `CONTACT_MSG_RECV` fallback events both route through that seam. ### Outgoing messages @@ -112,6 +113,12 @@ app/ - 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`. +### DM ingest + ACKs + +- `services/dm_ingest.py` is the one place that should decide fallback-context resolution, DM dedup/reconciliation, and packet-linked vs. content-based storage behavior. +- `CONTACT_MSG_RECV` is a fallback path, not a parallel source of truth. If you change DM storage behavior, trace both `event_handlers.py` and `packet_processor.py`. +- DM ACK tracking is an in-memory pending/buffered map in `services/dm_ack_tracker.py`, with periodic expiry from `radio_sync.py`. + ### Echo/repeat dedup - Message uniqueness: `(type, conversation_key, text, sender_timestamp)`. @@ -278,7 +285,7 @@ Note: MQTT, community MQTT, and bot configs were migrated to the `fanout_configs ## Security Posture (intentional) -- No authn/authz. +- No per-user authn/authz model; optionally, operators may enable app-wide HTTP Basic auth for both HTTP and WS entrypoints. - No CORS restriction (`*`). - Bot code executes user-provided Python via `exec()`. diff --git a/frontend/AGENTS.md b/frontend/AGENTS.md index 08a6bf6..9b02bcb 100644 --- a/frontend/AGENTS.md +++ b/frontend/AGENTS.md @@ -35,7 +35,6 @@ frontend/src/ ├── types.ts # Shared TS contracts ├── useWebSocket.ts # WS lifecycle + event dispatch ├── wsEvents.ts # Typed WS event parsing / discriminated union -├── messageCache.ts # Conversation-scoped cache ├── prefetch.ts # Consumes prefetched API promises started in index.html ├── index.css # Global styles/utilities ├── styles.css # Additional global app styles @@ -201,7 +200,7 @@ High-level state is delegated to hooks: - `useConversationRouter`: URL hash → active conversation routing - `useConversationNavigation`: search target, conversation selection reset, and info-pane state - `useConversationActions`: send/resend/trace/block handlers and channel override updates -- `useConversationMessages`: conversation switch loading, cache restore, jump-target loading, pagination, dedup/update helpers, and pending ACK buffering +- `useConversationMessages`: conversation switch loading, embedded conversation-scoped cache, jump-target loading, pagination, dedup/update helpers, reconnect reconciliation, and pending ACK buffering - `useUnreadCounts`: unread counters, mention tracking, recent-sort timestamps - `useRealtimeAppState`: typed WS event application, reconnect recovery, cache/unread coordination - `useRepeaterDashboard`: repeater dashboard state (login, pane data/retries, console, actions) @@ -233,6 +232,8 @@ High-level state is delegated to hooks: - Backend also emits WS `message` for outgoing sends so other clients stay in sync. - ACK/repeat updates arrive as `message_acked` events. - Outgoing channel messages show a 30-second resend control; resend calls `POST /api/messages/channel/{message_id}/resend`. +- Conversation-scoped message caching now lives inside `useConversationMessages.ts` rather than a standalone `messageCache.ts` module. If you touch message timeline restore/dedup/reconnect behavior, start there. +- `contact_resolved` is a real-time identity migration event, not just a contact-list update. Changes in that area need to consider active conversation state, cached messages, unread state keys, and reconnect reconciliation together. ### Visualizer behavior