# Version 3.0.6 — TextBee smsId Automated Inbound Dedupe

This release removes the manual **Pull TextBee Replies** admin-dashboard button and returns TextBee reply capture to an automated backend-only flow.

## What changed

- Removed the admin dashboard **Pull TextBee Replies** button.
- Removed the manual `/admin/api/textbee/process-received` route.
- TextBee inbound webhooks and polling now normalize a stable `messageProviderSid` for every inbound SMS.
- The primary TextBee dedupe key is now `smsId`, matching TextBee's `MESSAGE_RECEIVED` webhook payload.
- The normalizer now also detects nested/provider IDs such as `_id`, `id`, `messageId`, `message_id`, `uuid`, and array-wrapped received SMS records.
- If TextBee does not provide a real ID, the app falls back to a stable fingerprint using device, SIM, sender, text, and timestamp.
- Inbound duplicate suppression now prefers provider IDs. Body-level duplicate suppression is only used when there is no strong provider message ID.

## Expected behavior

1. Missed call sends the first SMS.
2. Customer replies.
3. TextBee webhook should POST to `/sms/incoming` immediately.
4. If webhook delivery is delayed or unavailable, the background poller checks TextBee automatically.
5. The same TextBee SMS is processed once because webhook and poller resolve to the same `textbee:<smsId>` provider key.

## Minimum files to upload

- `src/textbeeClient.js`
- `src/textbeeInboundProcessor.js`
- `src/routesSms.js`
- `src/routesAdmin.js`
- `src/leadService.js`
- `public/admin.html`
- `package.json`

Do not overwrite `.env` or `pestlead.sqlite`.
