feat(deck-builder): /deck_code mint + /deck resolve with 3-min in-memory TTL
Adds the portal pair (shadowverse-portal.com deck-builder endpoints) as anonymous routes on the app server. The translation middleware learns a new [NoWireEncryption] attribute that skips both AES calls but keeps the rest of the msgpack + base64 + envelope pipeline intact, matching prod's portal wire profile observed in data_dumps/traffic_prod_deckcode.ndjson. Storage is a 3-minute IMemoryCache — codes are anonymous-global, 4-char lowercase alphanumeric (matches the shortest prod sample). Foil bit is stripped on mint to match prod's normalize-on-encode behaviour. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
using MessagePack;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.DeckBuilder;
|
||||
|
||||
/// <summary>
|
||||
/// Covers all three client-side overloads of <c>GenerateDeckCodeTask.SetParameter</c>:
|
||||
/// standard, crossover (sub_clan present), and my-rotation (rotation_id present, no phantom).
|
||||
/// Optional fields stay null on shapes that don't carry them.
|
||||
///
|
||||
/// Deliberately does NOT inherit from <see cref="BaseRequest"/>: portal endpoints are anonymous
|
||||
/// (the server ignores viewer_id / steam_id / steam_session_ticket on the wire — see the
|
||||
/// data_headers in the prod traffic dump where they're all zeroed). The fields still arrive on
|
||||
/// the wire from the client; System.Text.Json silently drops unknown JSON properties.
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public class GenerateDeckCodeRequest
|
||||
{
|
||||
[JsonPropertyName("clan")]
|
||||
[Key("clan")]
|
||||
public int Clan { get; set; }
|
||||
|
||||
[JsonPropertyName("sub_clan")]
|
||||
[Key("sub_clan")]
|
||||
public int? SubClan { get; set; }
|
||||
|
||||
[JsonPropertyName("deck_format")]
|
||||
[Key("deck_format")]
|
||||
public int DeckFormat { get; set; }
|
||||
|
||||
[JsonPropertyName("card_id")]
|
||||
[Key("card_id")]
|
||||
public List<long> CardID { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("phantom_card_id")]
|
||||
[Key("phantom_card_id")]
|
||||
public List<long>? PhantomCardID { get; set; }
|
||||
|
||||
[JsonPropertyName("rotation_id")]
|
||||
[Key("rotation_id")]
|
||||
public string? RotationId { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using MessagePack;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos.Requests.DeckBuilder;
|
||||
|
||||
/// <summary>
|
||||
/// Portal resolve-by-code request. Anonymous on the wire — does not extend
|
||||
/// <see cref="BaseRequest"/>; see <see cref="GenerateDeckCodeRequest"/> for the rationale.
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public class GetDeckFromCodeRequest
|
||||
{
|
||||
[JsonPropertyName("deck_code")]
|
||||
[Key("deck_code")]
|
||||
public string DeckCode { get; set; } = "";
|
||||
}
|
||||
Reference in New Issue
Block a user