Phase 12: bridge completeness — expanded mapper, request replay, full shaper coverage

Mapper (src/mapper.rs):
- Restructured into ExactRoute + PrefixRoute tables (was a flat match list)
- 38 exact mappings (up from 18): SBC, Draft, FUT Champs, Division Rivals,
  Card Upgrades, Notifications, Settings, Trade pile, Club update, Stats, etc.
- 7 prefix-matched routes for path-param endpoints:
  /ut/game/fut/draft/{id}[/pick|/abandon]  → /draft/sessions/:id[/pick|/abandon]
  /ut/game/fut/champs/{id}/result|claim    → /fut-champs/:id/result|claim
  /ut/game/fut/store/pack/{id}/open        → /packs/open/:id
  /ut/game/fut/item/{id} DELETE            → /collection/:id (quick-sell)
  /ut/game/fut/trade/{id} DELETE           → /market/listings/:id (cancel)
  /ut/game/fut/sbc/set/{id}/submission     → /sbc/submit
- map_to_core_with_method() public helper preserves HTTP method for prefix routes
- 19 mapper unit tests (up from 6)

Replay (src/routes/admin.rs):
- POST /_bridge/captures/:id/replay — loads a capture from disk, re-runs it
  against Core with original headers+body, returns original vs new response
  plus a structured JSON diff for iterative shaper/handler development

Shaper (src/shaper.rs):
- 14 new shaper functions covering every mapped Core path:
  collection, cards, objectives, notifications, division, statistics,
  sbc, pack-open, draft, fut-champs, chemistry-styles, my-listings
- Prefix dispatch for /packs/open/, /draft/sessions/, /fut-champs/ paths
- All 25 unit tests pass, clippy clean

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-25 17:11:06 -07:00
parent 00839f5f1b
commit b7da8b6e83
5 changed files with 710 additions and 192 deletions
+13 -2
View File
@@ -122,13 +122,13 @@ pub async fn catch_all_handler(
match forward_to_core(
&state,
mapping.method,
mapping.core_path,
&mapping.core_path,
body_str.as_deref(),
&headers,
)
.await
{
Ok((body, status)) => (shape_response(mapping.core_path, body), status),
Ok((body, status)) => (shape_response(&mapping.core_path, body), status),
Err(e) => {
tracing::error!("Core request failed: {e}");
(serde_json::json!({ "error": e.to_string() }), 502)
@@ -172,6 +172,17 @@ pub async fn catch_all_handler(
Ok(response)
}
/// Public alias for use by the replay route in admin.rs.
pub async fn forward_to_core_pub(
state: &ProxyState,
method: &str,
path: &str,
body: Option<&str>,
headers: &[(String, String)],
) -> anyhow::Result<(Value, u16)> {
forward_to_core(state, method, path, body, headers).await
}
async fn forward_to_core(
state: &ProxyState,
method: &str,