Skip to main content

Recon Service v2 Surface

Status

Implemented

Date

2026-04-22

Purpose

Document the implemented servers_v2 reconciliation surface so future changes can stay document-driven and compatibility-safe.

This document captures the actual v2 shape after implementation, not just the intended target state.

Service Topology

Runtime services:

  • admin_service
    • external compatibility edge for bo/admin
    • legacy auth and Authorization header refresh
    • websocket top-info aggregation
  • recon_service
    • internal HTTP owner of recon state
    • route prefix: /internal/recon/*
  • recon_worker
    • background ingestion, parsing, matching, and retry loops
  • wallet_service
    • final money writer for auto-approved deposits

Local compose ports:

  • admin_service: 8016
  • recon_service: 8017

External Compatibility Mapping

bo/admin continues to call admin_service.

Implemented compatibility routes in servers_v2/admin_service/app/api/routes/legacy_recon.py:

  • /api/admin/pushbullet/list -> /internal/recon/pushbullet/list
  • /api/admin/pushbullet/add_device -> /internal/recon/pushbullet/add_device
  • /api/admin/pushbullet/delete -> /internal/recon/pushbullet/delete
  • /api/admin/shooter/template/recharge/list -> /internal/recon/shooter/template/recharge/list
  • /api/admin/shooter/template/recharge/add -> /internal/recon/shooter/template/recharge/add
  • /api/admin/shooter/template/recharge/delete -> /internal/recon/shooter/template/recharge/delete
  • /api/admin/shooter/phone/list -> /internal/recon/shooter/phone/list
  • /api/admin/shooter/phone/add -> /internal/recon/shooter/phone/add
  • /api/admin/shooter/phone/delete -> /internal/recon/shooter/phone/delete
  • /api/admin/shooter/sms/list -> /internal/recon/shooter/sms/list
  • /api/admin/shooter/sms/get -> /internal/recon/shooter/sms/get
  • /api/admin/shooter/sms/reset -> /internal/recon/shooter/sms/reset
  • /api/admin/shooter/sms/check -> /internal/recon/shooter/sms/check
  • /api/admin/shooter/device/list -> /internal/recon/shooter/device/list
  • /api/admin/shooter/device/trust -> /internal/recon/shooter/device/trust
  • /api/admin/shooter/device/delete -> /internal/recon/shooter/device/delete
  • /shooter/device/list -> /internal/recon/shooter/device/list
  • /shooter/device/trust -> /internal/recon/shooter/device/trust
  • /shooter/device/delete -> /internal/recon/shooter/device/delete

Compatibility guarantees implemented at the admin edge:

  • legacy admin token/session validation
  • successful response Authorization refresh
  • preserved status/msg/data envelope
  • preserved lowercase recon success message: success

Internal Recon Routes

Implemented in servers_v2/recon_service/app/api/routes/*:

  • POST /internal/recon/pushbullet/list
  • POST /internal/recon/pushbullet/add_device
  • POST /internal/recon/pushbullet/delete
  • POST /internal/recon/shooter/template/recharge/list
  • POST /internal/recon/shooter/template/recharge/add
  • POST /internal/recon/shooter/template/recharge/delete
  • POST /internal/recon/shooter/phone/list
  • POST /internal/recon/shooter/phone/add
  • POST /internal/recon/shooter/phone/delete
  • POST /internal/recon/shooter/sms/list
  • POST /internal/recon/shooter/sms/get
  • POST /internal/recon/shooter/sms/reset
  • POST /internal/recon/shooter/sms/check
  • POST /internal/recon/shooter/device/list
  • POST /internal/recon/shooter/device/trust
  • POST /internal/recon/shooter/device/delete
  • POST /internal/recon/stats/top-info
  • GET /health

Protection model:

  • all /internal/recon/* routes require X-Internal-Service-Token
  • admin_service is the intended caller for back-office compatibility traffic
  • GET /health stays public for local and orchestration health probes

Worker Loops

Implemented in servers_v2/recon_service/app/tasks/worker_loops.py:

  • pushbullet_listener_supervisor
  • missing_sms_sync_loop
  • sms_id_sync_loop
  • phone_whitelist_loop
  • parse_loop
  • order_match_loop
  • telegram_poll_loop

Freshness windows implemented in servers_v2/recon_service/app/tasks/loop_health.py:

  • pushbullet_listener_supervisor: 20s
  • missing_sms_sync_loop: 90s
  • sms_id_sync_loop: 30s
  • phone_whitelist_loop: 30s
  • parse_loop: 30s
  • order_match_loop: 90s
  • telegram_poll_loop: 60s

Worker health behavior:

  • task exit still fails the worker immediately
  • readiness now also fails when a critical loop stops reporting fresh success within its TTL
  • container health is backed by the worker heartbeat file

Data and Approval Contract

Shared migration introduced:

  • servers_v2/shared/rgb_db/migrations/versions/0017_add_recon_tables.py

Tables added for v2 compatibility:

  • shooter_device
  • shooter_phone
  • shooter_pushbullet
  • shooter_sms
  • shooter_template_recharge

Approval boundary:

  • recon_worker matches pending deposits by from_bank_owner + amount
  • duplicate-name players are still routed to manual review with task_status=6
  • final auto-approval flows through wallet_service
  • wallet_service /internal/wallet/deposit/agree now accepts optional sms_id
  • approved deposit rows can now persist the linked shooter SMS id for idempotent replay parity

Admin Top-Info

admin_service top-info aggregation now merges recon-owned counters from POST /internal/recon/stats/top-info:

  • sms_need_check_cnt
  • parse_fail_cnt
  • unmatched_sms_cnt
  • duplicate_sms_cnt

Immediate refresh path implemented for worker-driven manual-review changes:

  • recon_worker -> POST /internal/meta/ws/sync on admin_service with X-Internal-Service-Token
  • used when order matching promotes rows into manual-review state task_status=6

Compose and Environment

Compose services added:

  • recon_service
  • recon_worker

Compose env keys added or required for the recon path:

  • RECON_SERVICE_URL on admin_service
  • RGB_INTERNAL_SERVICE_TOKEN_ADMIN on internal-service consumers that accept calls from admin_service
  • RGB_INTERNAL_SERVICE_TOKEN_RECON on internal-service consumers that accept calls from recon_worker
  • RGB_PER_CALLER_TOKEN_REQUIRED=on after the Stage C hard flip
  • RGB_INTERNAL_SERVICE_TOKEN only during Stage A/B migration fallback; it must be empty or absent once RGB_PER_CALLER_TOKEN_REQUIRED=on
  • RGB_RECON_OPENROUTER_API_KEY
  • RGB_RECON_OPENROUTER_MODEL
  • RGB_RECON_TELEGRAM_BOT_TOKEN

Optional integrations:

  • OpenRouter is only required when template rule is omitted and AI regex generation is desired
  • Telegram bot token is only required when Telegram ingestion is enabled
  • disabled Telegram mode still refreshes worker freshness so the worker stays healthy without that optional integration

Test Coverage

Implemented regression coverage:

  • servers_v2/admin_service/tests/test_admin_integration.py
    • legacy recon proxy path
    • hidden /shooter/device/* compatibility path
    • top-info aggregation
  • servers_v2/admin_service/tests/test_client_urls.py
    • ReconClient base URL and circuit-breaker behavior
  • servers_v2/recon_service/tests/test_recon_routes.py
    • template validation compatibility
    • missing SMS compatibility
    • top-info counters
    • Pushbullet delete behavior
  • servers_v2/recon_service/tests/test_worker_health.py
    • loop freshness behavior
  • servers_v2/rolling_service/tests/test_events_health.py
    • rolling worker freshness and unhealthy escalation behavior
  • servers_v2/tests/test_compose_contract.py
    • compose service, healthcheck, and dependency contract

Verification Commands

  • cd servers_v2/admin_service && uv run pytest
  • cd servers_v2/recon_service && uv run pytest
  • cd servers_v2/rolling_service && uv run pytest
  • cd servers_v2/wallet_service && uv run pytest
  • cd servers_v2 && uv run pytest tests/test_compose_contract.py