Recon Service Migration Spec
Status
Approved
Date
2026-04-22
Goal
Migrate the SMS automation and reconciliation capability from servers/middle_server
into servers_v2 as a dedicated owned domain, while keeping back-office behavior
and external-facing admin compatibility stable.
Scope
In scope:
- Pushbullet device management
- SMS phone whitelist management
- recharge SMS template management
- AI-assisted regex generation for templates
- SMS ingestion and task progression
- missing-SMS backfill
- Telegram SMS ingestion
- manual SMS review APIs
- automatic order matching
- admin top-info integration for SMS pending counts
- admin compatibility routes and legacy auth compatibility
- dedicated worker loops and production-grade health checks
Out of scope:
- direct money mutation inside recon
- unifying admin traffic under gateway in this phase
- redesigning all old shooter data into a new schema before compatibility is proven
- a dedicated autonomous retry/compensation worker loop beyond the current manual SMS reset flow
Background
middle_server is currently mixing:
- back-office account compatibility
- content/config support
- SMS reconciliation workflows
- websocket top-info aggregation
- catch-all forwarding behavior
The SMS reconciliation block is large enough to become its own owned domain in servers_v2.
Compatibility Requirements
The following back-office paths must remain externally stable during migration:
/api/admin/pushbullet/list/api/admin/pushbullet/add_device/api/admin/pushbullet/delete/api/admin/shooter/template/recharge/list/api/admin/shooter/template/recharge/add/api/admin/shooter/template/recharge/delete/api/admin/shooter/phone/list/api/admin/shooter/phone/add/api/admin/shooter/phone/delete/api/admin/shooter/sms/list/api/admin/shooter/sms/get/api/admin/shooter/sms/reset/api/admin/shooter/sms/check/api/admin/shooter/device/list/api/admin/shooter/device/trust/api/admin/shooter/device/delete
Compatibility behaviors that must be preserved:
bo/admincontinues to calladmin_service, notrecon_service- legacy admin token and session checks remain enforced at
admin_service - successful legacy responses continue to refresh the
Authorizationresponse header - old
status/msg/dataenvelopes remain stable for compatibility routes sms_need_check_cntremains available in back-office top-infoShooterDevicesViewcompatibility is absorbed by v2 even though the menu is currently dormant
Ownership
admin_service- back-office edge
- legacy auth/session compatibility
- compatibility adapters for
/api/admin/shooter/*and/api/admin/pushbullet/* - top-info aggregation
recon_service- owned HTTP API for reconciliation domain state
- domain data reads and writes
- template, whitelist, message, and review state transitions
recon_worker- Pushbullet listeners
- Telegram ingestion
- missing-message sync
- parse and match loops
- secure admin top-info refresh signaling
wallet_service- final money writes only
Data Strategy
Phase 1 should preserve compatibility by reusing existing shooter-oriented tables or their exact semantics:
shooter_pushbulletshooter_smsshooter_phoneshooter_template_rechargeshooter_device
Schema cleanup or renaming can happen after the compatibility cutover is proven.
The audited legacy inventory and hidden compatibility dependencies are documented in:
docs/reference/recon/middle-server-recon-inventory.mddocs/reference/recon/recon-service-v2-surface.md
Admin and Approval Flow
/api/admin/shooter/sms/check should continue to behave like a reconciliation review action:
- persist
checker - optionally persist matched
order_id - update review/task state
It should not directly perform the final money mutation.
Final approval remains a wallet-owned flow through admin_service and wallet_service.
Worker Health Requirements
recon_worker must not report healthy only because the process is still alive.
Each critical loop must publish freshness from successful progress, not just heartbeat ticks:
- Pushbullet listener progress
- missing-SMS sync
- Telegram ingestion
- SMS ID sync
- whitelist validation
- template parsing
- order matching
If a critical loop keeps failing without fresh success beyond its defined TTL, the worker must become unhealthy.
Observability
Required signals:
- per-loop last-success timestamp
- per-loop consecutive failure count
- top-info pending SMS count
- unmatched SMS count
- duplicate SMS count
- parse failure count
- match failure count
Required logging:
- structured error logs including loop name and message id or device id
- warnings when compatibility routes cannot reach
recon_service - explicit alerts when worker freshness thresholds are exceeded
Implemented v2 Surface
The implemented v2 route mapping, compose topology, env contract, worker loops, and verification commands are documented in:
docs/reference/recon/recon-service-v2-surface.md
Device Compatibility Decision
/shooter/device/* is classified as recon compatibility scope.
Even though the route family is not mounted in legacy middle_server, the bo/admin
codebase still contains the dependency. servers_v2 must therefore implement device
compatibility endpoints through admin_service and recon_service so the dormant UI
cannot become a hidden regression during or after cutover.
Acceptance Criteria
bo/admincan keep using existing shooter/pushbullet paths without directly callingrecon_service- legacy admin auth and response-header refresh still work on compatibility routes
- recon worker health goes red when critical loops stall through repeated failures
sms_need_check_cntappears in admin top-info after integration- manual review writes review state without bypassing wallet ownership
- device compatibility routes are served and contract-tested
- compatibility contract tests, worker health tests, and compose tests all pass
Required Tests
admin_servicecompatibility route contract tests- legacy auth/session tests on recon compatibility endpoints
recon_clienttimeout/retry/circuit-breaker testsrecon_servicetemplate/whitelist/message API testsrecon_workerfreshness health tests- admin top-info aggregation tests
- compose healthcheck and dependency tests for
recon_serviceandrecon_worker