Skip to content

feat: recover match salts via Steam Game Coordinator#85

Open
raimannma wants to merge 1 commit into
masterfrom
feat/steam-gc-salt-recovery
Open

feat: recover match salts via Steam Game Coordinator#85
raimannma wants to merge 1 commit into
masterfrom
feat/steam-gc-salt-recovery

Conversation

@raimannma

Copy link
Copy Markdown
Member

What

Adds a src/gc/ module that logs into remembered Steam accounts through the user's own session and recovers match salts via the GC GetMatchMetaData message — independently of the existing httpcache scraper — POSTing them to the same /v1/matches/salts endpoint (tagged ingest-tool:{steam_id3}). Ported from the mod-manager feat/match-data-sharing branch.

How it works

  • Source: pulls the global /v1/matches/to-fetch list and picks up to the remaining quota (newest-first, deduped across accounts within a pass). Not the player's own matches.
  • Rate limit: 40 fetches per account per 24h, enforced by a persisted rolling-window quota (~/.local/share/deadlock-api-ingest/gc-quota.json) so the cap survives restarts. Requests are throttled 2 min apart (Steam rate-limits the GC per account).
  • Multi-account: iterates every account whose refresh token can be decrypted from local.vdf (AES on Linux/macOS, DPAPI on Windows), each with its own quota bucket.
  • Accounts that can't do requests: undecryptable accounts are skipped at recovery; an account whose GC handshake fails (e.g. doesn't own Deadlock) is backed off for 24h and the batch moves on; Steam rate-limiting exhausts only that account's window.
  • Safety: never runs while Deadlock is running (Steam routes GC traffic to the game's own pipe), re-checked mid-pass. Refresh tokens are in-memory only with a redacted Debug impl — never logged, persisted, or sent.

Wiring

  • Runs one pass in --once mode, a 30-min background worker in watch mode, and is skipped in game-wrapper mode (game is running).
  • New --no-gc flag mirrors --no-statlocker.

Module layout

auth (session recovery) · client (async steam-vent GC session) · api (to-fetch + post, blocking ureq) · quota (pure rolling window, unit-tested) · store (persisted quota + backoff) · mod (orchestration).

Notes

  • The 40/24h cap is per-account (matching the source and Valve's per-account GC rate limit). With N usable accounts that's up to N×40/day — easy to switch to a single global budget if preferred.
  • Adds git deps steam-vent and valveprotos (same revs as the mod-manager branch). Cargo.lock regenerated from master's baseline; the Nix build is naersk/Cargo.lock-driven, so no cargoHash bump needed.

Builds clean, passes clippy under the crate's pedantic/correctness denies, and the test suite is green.

🤖 Generated with Claude Code

Add a `gc` module that logs into remembered Steam accounts through the
user's own session and recovers match salts via the GC GetMatchMetaData
message, independently of the httpcache scraper. Salts are POSTed to the
same /v1/matches/salts endpoint, tagged `ingest-tool:{steam_id3}`.

- Picks up to 40 matches per account per 24h from the global to-fetch
  list (persisted rolling-window quota survives restarts).
- Multi-account: iterates every decryptable account, each with its own
  quota bucket; undecryptable accounts and accounts that can't reach the
  GC (e.g. don't own the game) are skipped/backed off for a day.
- Never runs while Deadlock is running (Steam routes GC to the game),
  re-checked mid-pass. Refresh tokens stay in-memory only, never logged.
- Runs one pass in --once mode and a 30-min background worker in watch
  mode; skipped in game-wrapper mode. New --no-gc flag to opt out.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@raimannma raimannma self-assigned this Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant