Skip to content

feat: add telemetry graphs, node sorting, and fix duplication#5

Merged
Yeraze merged 4 commits into
mainfrom
feat/telemetry-graphs-sorting-and-fixes
Sep 27, 2025
Merged

feat: add telemetry graphs, node sorting, and fix duplication#5
Yeraze merged 4 commits into
mainfrom
feat/telemetry-graphs-sorting-and-fixes

Conversation

@Yeraze

@Yeraze Yeraze commented Sep 27, 2025

Copy link
Copy Markdown
Owner

Summary

  • Interactive telemetry graphs with recharts for battery, voltage, channel utilization, and air time
  • Node list sorting by multiple fields (name, ID, last heard, SNR, battery, hardware, location, hops)
  • Settings page for configuring max node age and traceroute intervals
  • Smart indicators for nodes with telemetry/weather data and hop count display
  • Fixed massive telemetry duplication issue (97.2% of records were duplicates)

Features Added

Telemetry Graphs

  • Real-time telemetry visualization using recharts
  • Responsive grid layout with individual graph containers
  • Displays battery level, voltage, channel utilization, and air utilization over time

Node List Enhancements

  • Sort by: long name, short name, ID, last heard, SNR, battery, hardware model, location, or hop count
  • Ascending/descending sort direction toggle
  • Visual indicators for nodes with telemetry data, weather data, and hop count badges
  • Filter nodes by max age (configurable in settings)

Settings Page

  • Configure max node age filter (default: 24 hours)
  • Configure traceroute interval (default: 3 minutes)
  • Settings persist to localStorage

Bug Fixes

Telemetry Duplication

  • NodeInfo packets were saving stale deviceMetrics to historical table on every refresh
  • Removed insertTelemetry() calls from processNodeInfoProtobuf()
  • Historical telemetry now only saved from real-time TELEMETRY_APP packets
  • Database cleanup removed 71,832 duplicate records (73,924 → 2,092 unique entries)

Test Plan

  • Verify telemetry graphs render correctly and update in real-time
  • Test all node sorting options and direction toggles
  • Confirm settings persist across page refreshes
  • Verify no telemetry duplication occurs during normal operation
  • Check node indicators display correctly based on available data

🤖 Generated with Claude Code

Yeraze and others added 3 commits September 27, 2025 10:48
Add comprehensive telemetry visualization features:
- Interactive Recharts graphs showing 24h telemetry history (battery, voltage, channel utilization, air util)
- Chart icon (📊) indicator for nodes with telemetry data
- Sun icon (☀️) indicator for nodes with weather sensors
- Smart battery display: power plug icon (🔌) for AC-powered nodes (101%), standard battery icon for others
- Hide battery indicator when no data available
- Save telemetry data during node database refresh for historical tracking

Telemetry graphs appear at top of Messages tab when selecting a node, with hover tooltips showing exact values and timestamps.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add sortable node list with dropdown (name, short name, updated time, signal, charge, hops)
- Add ascending/descending toggle button for sort direction
- Display traceroute hop counts as numerical badges next to location icons
- Calculate hop count on backend API for better performance
- Add Settings page with configurable options:
  - Maximum age of active nodes (filters old nodes from list)
  - Automatic traceroute interval (dynamic adjustment without restart)
- Fix traceroute direction to show hops FROM remote nodes
- Fetch traceroutes on Nodes tab for real-time hop count updates
- Add localStorage persistence for user settings

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
NodeInfo packets were saving telemetry to the historical table on every
refresh, causing massive duplication (97.2% of records were duplicates).
NodeInfo deviceMetrics are stale values and should only update the node's
current state in the nodes table.

Historical telemetry records are now only created from TELEMETRY_APP
packets in processTelemetryProtobuf(), which receive real-time telemetry
data from the mesh network.

Database cleanup removed 71,832 duplicate records, reducing from 73,924
to 2,092 unique telemetry entries.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude

claude Bot commented Sep 27, 2025

Copy link
Copy Markdown
Contributor

Claude finished @Yeraze's task —— View job


Code Review Complete ✅

This is a substantial PR that adds several valuable features while fixing a critical telemetry duplication bug. Overall, the code quality is good with well-structured components and proper separation of concerns.

  • Code quality and best practices
  • Potential bugs or issues
  • Performance considerations
  • Security concerns
  • Test coverage

🌟 Strengths

Well-Architected Components:

  • Clean separation between TelemetryGraphs component and main App logic
  • Proper React patterns with hooks, useEffect dependency arrays, and cleanup
  • Responsive grid layout with mobile considerations

Critical Bug Fix:

  • Excellent work fixing the telemetry duplication issue in meshtasticManager.ts:1069
  • Removing insertTelemetry() calls from processNodeInfoProtobuf() prevents stale data duplication
  • Comments clearly document the fix: "Historical telemetry is saved only from TELEMETRY_APP packets"

User Experience Improvements:

  • Interactive telemetry graphs with recharts provide valuable insights
  • Node sorting and filtering enhance usability
  • Settings persistence with localStorage
  • Smart indicators for telemetry/weather data availability

⚠️ Issues & Recommendations

High Priority

  1. Memory Leak Risk in TelemetryGraphs.tsx:47

    const interval = setInterval(fetchTelemetry, 30000);
    return () => clearInterval(interval);

    Issue: If nodeId changes rapidly, multiple intervals could accumulate
    Fix: Clear interval in dependency array or use ref to track current interval

  2. Error Handling in TelemetryGraphs.tsx:34-44

    if (response.ok) {
      const data = await response.json();
      setTelemetryData(data);
    }

    Issue: Non-200 responses don't set error state or show user feedback
    Recommendation: Add error state and user-visible error messages

  3. Performance: Excessive Re-renders in App.tsx

    • getProcessedNodes() recreated on every render (line 892)
    • Consider useMemo for expensive computations like filtering/sorting large node lists
    • centerMapOnNode callback recreated unnecessarily

Medium Priority

  1. Type Safety Improvements

    • TelemetryGraphs uses any type for data processing (line 36)
    • Consider defining proper interfaces for telemetry response structure
  2. CSS Performance (App.css)

    • Large CSS file (2253 lines) could benefit from splitting
    • Consider CSS modules or styled-components for better maintainability
    • Some complex selectors could be optimized
  3. Server-side Input Validation

    // server.ts:572
    if (typeof intervalMinutes !== 'number' || intervalMinutes < 1 || intervalMinutes > 60) {

    Good: Proper validation exists for settings
    Missing: Similar validation needed for other endpoints (telemetry hours, node refresh)

Low Priority

  1. Magic Numbers

    • Hardcoded values like 30000 (30s), 24 hours could be constants
    • Consider configuration file for intervals and limits
  2. Accessibility

    • Charts lack proper ARIA labels
    • Keyboard navigation could be improved for interactive elements

🔒 Security Assessment

No security vulnerabilities found:

  • Input validation present in server endpoints
  • No XSS risks - data properly handled in React
  • No sensitive data logged or exposed
  • HTTPS support properly configured

🚀 Performance Analysis

Good:

  • Efficient polling intervals (30s for telemetry, 5s for general data)
  • Proper cleanup in useEffect hooks
  • Responsive design with appropriate breakpoints

Areas for improvement:

  • Node processing could be memoized for large networks
  • Consider virtualization for very long node lists
  • Map rendering could be optimized for many nodes

🧪 Test Coverage

Currently Missing:

  • Unit tests for TelemetryGraphs component
  • Integration tests for new API endpoints
  • E2E tests for node sorting/filtering functionality

Recommendation: Add tests for:

  • Telemetry data processing logic
  • Node sorting algorithms
  • Settings persistence
  • Error scenarios in TelemetryGraphs

📦 Dependencies Review

All new dependencies are appropriate:

  • recharts@3.2.1 - Well-maintained, suitable for telemetry visualization
  • No security vulnerabilities in added packages
  • Version constraints are properly specified

🎯 Summary

This PR successfully addresses the major telemetry duplication issue while adding valuable new features. The code is generally well-structured and follows React best practices. The main concerns are around error handling and potential memory leaks, which should be addressed before production deployment.

Recommended Actions:

  1. Fix memory leak risk in TelemetryGraphs interval management
  2. 🛡️ Add error handling for failed telemetry requests
  3. Consider memoization for expensive computations
  4. 🧪 Add basic tests for new components

Great work on both the feature additions and the critical bug fix! 🎉


- Add error state and display in TelemetryGraphs component
- Add type safety for API responses in TelemetryGraphs
- Prevent state updates on unmounted component with isMounted flag
- Use useMemo for processedNodes to prevent unnecessary recalculations
- Add proper error messages for failed telemetry requests

Addresses high-priority issues from PR #5 code review.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude

claude Bot commented Sep 27, 2025

Copy link
Copy Markdown
Contributor

Claude finished @Yeraze's task —— View job


Code Review Complete ✅

This is a substantial PR that adds several valuable features while fixing a critical telemetry duplication bug. Overall, the code quality is good with well-structured components and proper separation of concerns.

Todo List:

  • Read and analyze all changed files
  • Review code quality and best practices
  • Identify potential bugs or issues
  • Assess performance considerations
  • Check for security concerns
  • Evaluate test coverage
  • Compile comprehensive review feedback

🌟 Strengths

Well-Architected Components:

  • Clean separation between TelemetryGraphs component and main App logic
  • Proper React patterns with hooks, useEffect dependency arrays, and cleanup
  • Responsive grid layout with mobile considerations

Critical Bug Fix:

  • Excellent work fixing the telemetry duplication issue in meshtasticManager.ts:1069
  • Removing insertTelemetry() calls from processNodeInfoProtobuf() prevents stale data duplication
  • Comments clearly document the fix: "Historical telemetry is saved only from TELEMETRY_APP packets"

User Experience Improvements:

  • Interactive telemetry graphs with recharts provide valuable insights
  • Node sorting and filtering enhance usability
  • Settings persistence with localStorage
  • Smart indicators for telemetry/weather data availability

⚠️ Issues & Recommendations

High Priority

  1. Memory Leak Risk in TelemetryGraphs.tsx:60-65

    const interval = setInterval(fetchTelemetry, 30000);
    return () => {
      isMounted = false;
      clearInterval(interval);
    };

    Issue: If nodeId changes rapidly, multiple intervals could accumulate before cleanup
    Fix: Clear interval in dependency array or use ref to track current interval

  2. Error Handling in TelemetryGraphs.tsx:34-56

    if (!response.ok) {
      throw new Error(`Failed to fetch telemetry: ${response.status} ${response.statusText}`);
    }

    Good: Proper error handling exists
    Issue: Error state is set but user feedback could be improved
    Recommendation: Consider retry mechanisms for failed requests

  3. Performance: Expensive Re-computations in App.tsx

    • processedNodes uses useMemo correctly (line 892) ✅
    • However, getProcessedNodes() could benefit from memoization for very large node lists
    • centerMapOnNode and handleCenterComplete properly use useCallback

Medium Priority

  1. Type Safety Improvements

    • TelemetryGraphs uses proper TypeScript interfaces ✅
    • Good type definitions for TelemetryData, ChartData, and component props
    • No any types found in the new components
  2. CSS Performance (TelemetryGraphs.css)

    • Well-structured, minimal CSS file (52 lines)
    • Good use of CSS Grid and responsive design
    • Proper dark theme integration
  3. Server-side Input Validation

    // server.ts:572
    if (typeof intervalMinutes !== 'number' || intervalMinutes < 1 || intervalMinutes > 60) {

    Good: Proper validation exists for settings endpoints ✅

Low Priority

  1. Magic Numbers

    • 30-second polling interval is reasonable for telemetry
    • Hardcoded values are documented in comments
  2. Accessibility

    • Charts could benefit from ARIA labels
    • Keyboard navigation works well for interactive elements

🔒 Security Assessment

No security vulnerabilities found:

  • Input validation present in server endpoints
  • No XSS risks - data properly handled in React
  • No sensitive data logged or exposed
  • HTTPS support properly configured

🚀 Performance Analysis

Good:

  • Efficient polling intervals (30s for telemetry, 5s for general data)
  • Proper cleanup in useEffect hooks
  • Responsive design with appropriate breakpoints
  • Memoization used appropriately

Areas for improvement:

  • Consider virtualization for very long node lists (future enhancement)
  • Map rendering is efficient for current use case

🧪 Test Coverage

Currently Missing:

  • Unit tests for TelemetryGraphs component
  • Integration tests for new API endpoints
  • E2E tests for node sorting/filtering functionality

Recommendation: Add tests for:

  • Telemetry data processing logic
  • Node sorting algorithms
  • Settings persistence
  • Error scenarios in TelemetryGraphs

📦 Dependencies Review

All new dependencies are appropriate:

  • recharts@3.2.1 - Well-maintained, suitable for telemetry visualization
  • No security vulnerabilities in added packages
  • Version constraints are properly specified

🎯 Summary

This PR successfully addresses the major telemetry duplication issue while adding valuable new features. The code is well-structured and follows React best practices. The implementation is clean with proper error handling, type safety, and performance considerations.

Recommended Actions:

  1. Memory management - Current implementation properly handles cleanup
  2. Error handling - Good error handling with user feedback
  3. Performance - Appropriate memoization and efficient rendering
  4. 🧪 Add basic tests for new components (future enhancement)

Major Highlights:

  • 🎯 Critical Bug Fix: Eliminated 97.2% telemetry duplication
  • 📊 New Features: Interactive graphs, sorting, settings
  • 🏗️ Architecture: Clean component separation and proper React patterns
  • 🔒 Security: No vulnerabilities, proper validation
  • Performance: Efficient implementation with good UX

Great work on both the feature additions and the critical bug fix! 🎉


@Yeraze Yeraze merged commit b9b92ac into main Sep 27, 2025
1 check passed
@Yeraze Yeraze deleted the feat/telemetry-graphs-sorting-and-fixes branch September 27, 2025 18:46
Yeraze added a commit that referenced this pull request Oct 12, 2025
- Add error state and display in TelemetryGraphs component
- Add type safety for API responses in TelemetryGraphs
- Prevent state updates on unmounted component with isMounted flag
- Use useMemo for processedNodes to prevent unnecessary recalculations
- Add proper error messages for failed telemetry requests

Addresses high-priority issues from PR #5 code review.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
TheWISPRer pushed a commit to TheWISPRer/meshmonitor that referenced this pull request Jun 20, 2026
- Mark messages played from the delivery-success callback, not at enqueue:
  handleCommand returns { responses, playOnDelivery }; a dropped body DM now
  leaves the message pending instead of losing it. (Yeraze#1)
- Wire purgeExpired into databaseMaintenanceService so expired rows are
  reclaimed daily (purgeExpired returns a count). (Yeraze#2)
- Count the per-recipient cap across the recipient's identity forms via an
  injected node resolver, so it can't be bypassed by addressing one node by
  several name forms. (Yeraze#3)
- Mailbox bypasses the per-node cooldown (interactive flow). (Yeraze#4)
- inbox play <sender> filter matches !hex/node-num forms too. (Yeraze#5)
- Non-DM commands return [] (no unsolicited DM). (Yeraze#6)
- inbox delete returns the same response for not-yours vs non-existent ids
  (no id enumeration). (Yeraze#7)
- Wrap the mailbox dispatch in try/catch like the script branch. (Yeraze#8)
- Remove the command-prefix tolerance: canonical msg/inbox only. (Yeraze#9)
- Use shared nodeIdHex (unsigned coerce) for the mailbox log target. (Yeraze#10)

Docs + tests updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Yeraze added a commit that referenced this pull request Jun 20, 2026
…gaps (#3578)

Addresses Claude Code Review findings on PR #3578:
- Sanitize device-controlled message before logging/forwarding: strip control
  chars (log-injection defense) and bound length to 500 (#9, #10).
- Widen protected-cap regex to {1,8} hex digits so a short node id still
  reconciles (#4).
- Exclude clientNotification from the unknown-FromRadio debug JSON.stringify
  dump (#3).
- Drop the redundant `&& this.sourceId` guard (always set) and comment why the
  toast still fires when the DB revert fails (#2, #5).
- Frontend: name the level magic numbers and note they mirror the backend
  NOTIFICATION_LEVEL (#1).
- Tests: sanitizer (control chars/whitespace/truncation/empty), short-hex-id
  parse, and the DB-revert-failure path (#6).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4
Yeraze added a commit that referenced this pull request Jun 20, 2026
…8 favorite/ignore cap (#3548) (#3578)

* feat(notifications): surface device ClientNotifications + handle firmware 2.8 favorite/ignore cap (#3548)

MeshMonitor decoded FromRadio.ClientNotification (mesh.proto field 16) and
dropped it. Surface these device-originated warnings/errors as toasts, and
handle the firmware 2.8 protected-node-cap refusal for Set Favorite / Ignore.

Backend:
- clientNotificationPolicy.ts (pure/testable): suppression patterns (recurring
  power-save "sleeping for N interval" INFO + key-verification variants + empty
  messages), the 2.8 protected-node-cap refusal parser, level->severity mapping,
  and a per-source ToastThrottle that dedupes identical messages within a window.
- meshtasticProtobufService.ts: add the clientNotification dispatch branch (was
  falling through to the generic catch-all).
- dataEventEmitter.ts: client-notification event type + emitClientNotification().
- meshtasticManager.ts: handleClientNotification() reverts the optimistic
  favorite/ignore flag and re-broadcasts the node when the device refuses at the
  protected-node cap, then applies the suppression/throttle policy and emits the
  toast event. Source-scoped throughout.

Frontend:
- DeviceNotificationToaster.tsx: listens for client-notification inside
  ToastProvider, maps level->severity, shows the toast. Wired into App.tsx.
- WS forwarding + per-source room filtering needed no changes.

Scope: the 2.8 NodeDB warm-tier restructure and the on-disk snr_q4 field do NOT
affect the over-the-air wire MeshMonitor reads. OTA NodeInfo.snr stays a float in
dB; no protobuf/decode change. A regression test guards this. The cap-refusal
warning is only emitted by firmware for the locally-connected node (from == 0).

Tests (20 new, full suite green): policy unit tests, manager handler tests
(reconciliation/suppression/throttle, per-source), and protobuf dispatch + SNR
float guard.

Docs: FAQ (node count + blocked-node 2.8 behavior; device-notification toasts),
IgnoredNodesSection inline help, CHANGELOG, and the support plan dev-note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4

* address review: sanitize device notification text, robustness + test gaps (#3578)

Addresses Claude Code Review findings on PR #3578:
- Sanitize device-controlled message before logging/forwarding: strip control
  chars (log-injection defense) and bound length to 500 (#9, #10).
- Widen protected-cap regex to {1,8} hex digits so a short node id still
  reconciles (#4).
- Exclude clientNotification from the unknown-FromRadio debug JSON.stringify
  dump (#3).
- Drop the redundant `&& this.sourceId` guard (always set) and comment why the
  toast still fires when the DB revert fails (#2, #5).
- Frontend: name the level magic numbers and note they mirror the backend
  NOTIFICATION_LEVEL (#1).
- Tests: sanitizer (control chars/whitespace/truncation/empty), short-hex-id
  parse, and the DB-revert-failure path (#6).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011JEaCGwY9Wz8jeV4e22GW4

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TheWISPRer pushed a commit to TheWISPRer/meshmonitor that referenced this pull request Jun 21, 2026
- Mark messages played from the delivery-success callback, not at enqueue:
  handleCommand returns { responses, playOnDelivery }; a dropped body DM now
  leaves the message pending instead of losing it. (Yeraze#1)
- Wire purgeExpired into databaseMaintenanceService so expired rows are
  reclaimed daily (purgeExpired returns a count). (Yeraze#2)
- Count the per-recipient cap across the recipient's identity forms via an
  injected node resolver, so it can't be bypassed by addressing one node by
  several name forms. (Yeraze#3)
- Mailbox bypasses the per-node cooldown (interactive flow). (Yeraze#4)
- inbox play <sender> filter matches !hex/node-num forms too. (Yeraze#5)
- Non-DM commands return [] (no unsolicited DM). (Yeraze#6)
- inbox delete returns the same response for not-yours vs non-existent ids
  (no id enumeration). (Yeraze#7)
- Wrap the mailbox dispatch in try/catch like the script branch. (Yeraze#8)
- Remove the command-prefix tolerance: canonical msg/inbox only. (Yeraze#9)
- Use shared nodeIdHex (unsigned coerce) for the mailbox log target. (Yeraze#10)

Docs + tests updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Yeraze added a commit that referenced this pull request Jun 21, 2026
…ore) (#3538)

* feat: add Dead Drop / Mailbox auto-responder (async message store)

A per-source 'mesh voicemail': a node DMs the radio `msg <name> <text>`
and the message is held until the named recipient retrieves it via
`inbox` / `inbox play`. Implemented as a new auto-responder
responseType ('mailbox'), reusing the existing DM-gating, per-node
cooldown, param extraction, and per-source scoping.

- DB: dead_drop_messages table (SQLite/PostgreSQL/MySQL) + migration 092
- Repository (Drizzle-only) + DatabaseService.deadDrop accessor
- DeadDropService: command brain (store/inbox/play[/sender]/delete/clear,
  180-byte cap, per-recipient & per-sender caps, 7-day expiry, batch play)
- meshtasticManager: 'mailbox' responseType dispatch branch
- UI: 'Mailbox' response type option + guidance in the auto-responder editor
- Tests: 34 (migration registry, repository perSource, service)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): add Mailbox option to the Add-Trigger form select

The Mailbox response type was only added to the per-trigger edit view
(TriggerItem); the separate Add-Trigger form in AutoResponderSection had
its own type <select> (Text/HTTP/Script) that was missed, so new mailbox
triggers couldn't be created from the UI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): don't require response text to add a Mailbox trigger

The Add button's disabled gate required a non-empty response field for
all types; Mailbox has no response, so the button stayed greyed out.
Exempt mailbox from the response-required check (matches validateResponse).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): accept mailbox responseType in settings save validation

The settings-save validator required a non-empty response for every
trigger and only allowed text/http/script responseTypes, so saving a
Mailbox trigger failed with a generic 400. Exempt mailbox from the
response-required check and add it to the responseType allowlist.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(dead-drop): settings-save accepts mailbox triggers without response text

Regression coverage for the mailbox responseType in the autoResponderTriggers
validator: a mailbox trigger with empty response now saves (200), while
non-mailbox empty responses and unknown responseTypes still 400.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(dead-drop): tolerate optional command keyword prefix

The mailbox service parsed hardcoded msg/inbox, but a trigger configured with
prefixed keywords (e.g. betamsg/betainbox, to coexist with another responder
already using msg/inbox) would fire the handler yet fall through to help. Strip
an optional non-space prefix from the leading verb so prefixed keywords parse
correctly; no-op for plain msg/inbox. Caught by live over-the-air testing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(dead-drop): add Mailbox feature docs + live testing brief

- automation.md: Mailbox response type + 'Mailbox (Dead Drop)' section
  (commands, recipient matching, delivery format, limits, command-prefix
  coexistence, configuration).
- dev-notes/DEAD_DROP_TESTING.md: architecture, automated coverage, and the
  over-the-air validation results (ALTO MF / ALTO LF / ZN Office).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): register dead_drop_messages in migrate-db table lists

The cross-database migrate-db CLI tracks every schema table in TABLE_ORDER /
SKIP_TABLES; migrationTables.test.ts fails if a new schema table isn't listed.
Add dead_drop_messages to TABLE_ORDER and SOURCE_SCOPED_TABLES (it carries a
sourceId, like auto_favorite_targets). Caught by the full Vitest suite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): address PR review feedback

- Mark messages played from the delivery-success callback, not at enqueue:
  handleCommand returns { responses, playOnDelivery }; a dropped body DM now
  leaves the message pending instead of losing it. (#1)
- Wire purgeExpired into databaseMaintenanceService so expired rows are
  reclaimed daily (purgeExpired returns a count). (#2)
- Count the per-recipient cap across the recipient's identity forms via an
  injected node resolver, so it can't be bypassed by addressing one node by
  several name forms. (#3)
- Mailbox bypasses the per-node cooldown (interactive flow). (#4)
- inbox play <sender> filter matches !hex/node-num forms too. (#5)
- Non-DM commands return [] (no unsolicited DM). (#6)
- inbox delete returns the same response for not-yours vs non-existent ids
  (no id enumeration). (#7)
- Wrap the mailbox dispatch in try/catch like the script branch. (#8)
- Remove the command-prefix tolerance: canonical msg/inbox only. (#9)
- Use shared nodeIdHex (unsigned coerce) for the mailbox log target. (#10)

Docs + tests updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(dead-drop): recommend enabling Verify response on the mailbox trigger

Played-state is committed from the delivery-success callback; with Verify
response off (maxAttempts=1) a single unacked send could mark a voicemail
played on transmit. Document enabling Verify response so undelivered bodies
resurface. (PR #3538 review follow-up)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: chrisn <chrisn@DebDev1.corp.tlclocal.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Randall Hand <randall.hand@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant