Skip to main content

Middle Server Recon Inventory

Status

Audited

Date

2026-04-22

Purpose

Capture the legacy middle_server reconciliation behavior that must be preserved or explicitly redesigned during the recon_service migration.

This document is the source inventory used by:

  • docs/adr/ADR-002-recon-service-boundary.md
  • docs/specs/recon/2026-04-22-recon-service-migration.md
  • docs/plans/recon/2026-04-22-recon-service-implementation.md
  • docs/runbooks/recon/recon-service-cutover.md

Audited Source Files

  • servers/middle_server/app/api/routes/pushbullet.py
  • servers/middle_server/app/api/routes/shooter.py
  • servers/middle_server/app/api/routes/ws.py
  • servers/middle_server/app/core/events.py
  • servers/middle_server/app/core/telegram_bot_mgr.py
  • servers/middle_server/app/tasks/pushbullet.py
  • servers/middle_server/app/services/pushbullet/pushbullet_manager.py
  • servers/middle_server/app/services/openrouter.py
  • servers/middle_server/app/models/db/models.py
  • servers/middle_server/app/models/schemas/pushbullet.py
  • servers/middle_server/app/models/schemas/shooter.py
  • servers/middle_server/app/resources/errors.py
  • servers/admin_server/app/api/routes/player/deposit.py
  • servers/wallet_server/app/api/routes/deposit.py
  • bo/admin/src/ui/views/desktop/ShooterPushBullet/ShooterPushBulletView.vue
  • bo/admin/src/ui/views/desktop/ShooterSms/ShooterSmsView.vue
  • bo/admin/src/ui/views/desktop/ShooterDevices/ShooterDevicesView.vue
  • bo/admin/src/router/asyncRoutes.js

Legacy Route Inventory

Documented route families that are part of the reconciliation domain:

  • /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

Compatibility-only route family still referenced by bo/admin code:

  • /api/admin/shooter/device/list
  • /api/admin/shooter/device/trust
  • /api/admin/shooter/device/delete

The device route family is not currently mounted in legacy middle_server, but it is implemented in the admin frontend and must be treated as part of the migration compatibility baseline so that v2 can absorb the hidden dependency safely.

Response and Auth Contract

Legacy recon-facing admin routes use the old back-office contract:

  • admin requests enter through back-office auth with legacy token and session checks
  • successful responses use the legacy envelope status/msg/data
  • successful responses refresh the Authorization response header
  • successful generic messages use lowercase success

Legacy shooter-specific business error codes:

  • 41: rule match error
  • 42: bank name mismatch
  • 43: bank number mismatch
  • 44: amount mismatch
  • 45: new balance mismatch
  • 46: sender mismatch
  • 47: SMS not found
  • 48: AI regex generation failed
  • 49: unsupported SMS
  • 50: template already exists

Data Model Inventory

Legacy reconciliation state is persisted in these tables:

  • shooter_pushbullet
  • shooter_sms
  • shooter_phone
  • shooter_template_recharge
  • shooter_device

These names and field semantics must be preserved in phase 1 so that compatibility is proven before any schema cleanup.

shooter_pushbullet

Represents one Pushbullet-linked device/account pair used for SMS ingestion.

Important fields:

  • device identity and account metadata
  • api_access_token
  • iden
  • status
  • version
  • create_ts
  • update_ts

shooter_sms

Represents one captured SMS item across Pushbullet or Telegram ingestion.

Important fields:

  • source identity: p_iden, p_thread_id, sms_channel, sms_id
  • sender info: phone, sender
  • message content: sms
  • parsed business fields: bank_name, bank_num, amount, new_value
  • matching fields: order_id, checker
  • lifecycle fields: task, task_status, create_ts, update_ts

shooter_phone

Whitelist of phone numbers allowed into automatic SMS handling.

Important fields:

  • phone
  • status
  • create_ts
  • update_ts

shooter_template_recharge

Recharge SMS template definitions used during parsing.

Important fields:

  • rule
  • sms
  • bank_name
  • bank_num
  • amount
  • sender
  • new_value
  • status
  • create_ts
  • update_ts

shooter_device

Manual device trust list exposed by bo/admin compatibility UI.

Important fields inferred from UI expectations:

  • tag
  • phone
  • keep_online_ts
  • is_trust
  • create_ts

SMS Lifecycle Inventory

Legacy task meanings:

  • 0: waiting for SMS ID sync
  • 1: waiting for whitelist validation
  • 2: waiting for template parse
  • 3: waiting for order match or manual review
  • 4: handled

Legacy task_status meanings:

  • 0: normal
  • 1: unknown Pushbullet device
  • 2: phone not in whitelist
  • 3: parse failed or no matching template
  • 4: matched multiple orders
  • 5: no order matched after timeout
  • 6: duplicate-name player requires manual review
  • 7: no SMS ID matched
  • 8: duplicate SMS

Legacy admin filter mapping in /api/admin/shooter/sms/list:

  • 0: task=0, task_status=0
  • 1: task=1, task_status=0
  • 2: task=2, task_status=0
  • 3: task=3, task_status=0
  • 4: task=4, task_status=0
  • 11: task=0, task_status=1
  • 12: task=1, task_status=2
  • 13: task=2, task_status=3
  • 14: task=3, task_status=4
  • 15: task=3, task_status=5
  • 16: task=3, task_status=6

Worker and Background Flow Inventory

Legacy startup behavior:

  • initialize Pushbullet listeners
  • initialize Telegram bot manager
  • start websocket top-info updater

Legacy scheduled jobs:

  • every 10s
    • SMS ID sync
    • whitelist validation
    • template parsing
  • every 30s
    • order matching
    • missing-SMS backfill

Pushbullet ingestion behavior:

  • websocket listener inserts live SMS with task=0, task_status=0
  • missing-SMS backfill inserts pulled SMS with task=1, task_status=0, sms_channel=2
  • SMS ID sync matches by device, thread, sender, body, and timestamp window

Telegram ingestion behavior:

  • listens to group, channel broadcast, and system message events
  • parses bank SMS-like messages containing 입금 or 잔액
  • supports messages beginning with 보낸사람 or [수신날짜]
  • stores imported rows as p_iden='tg-sync-bot', sms_id='tg-sync-bot', task=2

Template and Parsing Rules

Recharge template add behavior:

  • validates regex compatibility against submitted sample SMS
  • if rule is empty, calls OpenRouter to generate a regex candidate
  • generated regex must still be validated against submitted sample SMS
  • mismatch responses use the shooter-specific error codes above

Production requirement carried into v2:

  • malformed or unsupported samples must fail fast and explicitly
  • AI-generated regex is optional enhancement, not required for availability

Matching and Review Behavior

Automatic order matching currently calls:

  • admin_server compatibility path /player/deposit/shooter/agree
  • which forwards to wallet-owned matching behavior

Legacy match response items contain:

  • transaction_id
  • sms_id
  • is_same

Observed legacy outcomes:

  • one clear match can advance to handled state
  • duplicate-name player cases use admin list status 16
  • no-order timeouts move to task_status=5

Production hardening rule for v2:

  • if multiple candidate orders exist and no single safe match can be chosen, persist task_status=4 instead of reporting the loop as successful
  • if every per-item publish, parse, or settlement attempt fails within a loop cycle, the loop must report failure to worker health instead of silently remaining green

Top-Info and Admin Integration

Legacy websocket top-info includes:

  • sms_need_check_cnt

This value is derived from shooter_sms rows where:

  • task=3
  • task_status=6
  • checker IS NULL

bo/admin uses this value for:

  • dashboard badges
  • notification sound triggers
  • notification popups
  • user top-info subscriptions

This counter is therefore part of the external compatibility contract even though it is transported through websocket top-info rather than a shooter REST response.

Migration Decisions Locked By This Inventory

  • recon_service owns the reconciliation domain in servers_v2
  • admin_service remains the only back-office edge consumed by bo/admin
  • wallet_service remains the only money writer
  • compatibility covers both the mounted legacy routes and the hidden /shooter/device/* front-end dependency
  • phase 1 keeps shooter table names and lifecycle semantics stable