From 3efaaedf9c0c2efa3ead379265fd1d28dc6972e6 Mon Sep 17 00:00:00 2001 From: asultan Date: Sun, 24 May 2026 14:19:38 -0300 Subject: [PATCH 1/7] Claude init --- CLAUDE.md | 209 ++++++++++++++++++ .../appsettings.json | 2 +- src/Application/Raid.Toolkit/appsettings.json | 2 +- 3 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..cb31892c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,209 @@ +# CLAUDE.md — Raid Toolkit SDK + +This document covers architecture, build instructions, the account-dump JSON schema, and security audit findings for this fork (`asultan80/raid-toolkit-sdk`). + +## Orientation + +**What this is:** A Windows background service that attaches to the running RAID: Shadow Legends (Plarium Play) process and reads its IL2CPP memory. It exposes a local WebSocket API so tools can query the full account state — heroes, artifacts, great hall, arena, etc. — without having to deal with memory addresses or game updates themselves. + +**Current stable branch:** `release/v2.8` (latest tag `v2.8.22.23238`, last commit 2024-02-10) +**In-progress:** `main` targets v3.0-unstable. Structural restructuring, not production-ready. +**Platform:** Windows only (WinUI3, Win32 P/Invoke, IL2CPP tooling). Cannot build on macOS/Linux. + +## Project Map (`src/`) + +| Project | Role | +|---|---| +| `Application/Raid.Toolkit` | WinUI3 tray app — the main executable | +| `Application/Raid.Toolkit.Application.Core` | DI host, commands, WebSocket setup, update service | +| `Application/Launcher` | Tiny WinForms launcher that checks .NET prereqs then starts the main app | +| `Shared/Common` | Utilities: `RegistrySettings`, `HttpClientExtensions`, `GitHub/Updater` | +| `Shared/DataModel` | **Public DTOs, enums, WebSocket message format, API contracts** — key folder for schema | +| `Shared/Extensibility*` | Plugin/extension infra: account manager, persisted storage, WebSocket dispatcher | +| `Shared/Model` | IL2CPP-generated assembly glue; `ModelLoader.cs` and `PlariumPlayAdapter.cs` | +| `Extensions/Account` | Account data extraction extension — `AccountApi`, `Extractor.cs`, `StaticDataApi` | +| `Extensions/Realtime` | Live in-battle telemetry | +| `ClientSDK/DotNet` | `Raid.Client` NuGet package | +| `ClientSDK/Node` | `@raid-toolkit/webclient` npm package | +| `ClientSDK/Python` | `raidtoolkit` PyPI package | +| `Setup/` | WiX installer → `RaidToolkitSetup.exe` | + +## Build (Windows only) + +``` +# Requires Visual Studio 2019+ or .NET 6 SDK + WinAppSDK build tools +msbuild SDK.sln -t:"Build;Pack" -p:Configuration=Release -p:Platform=x64 +``` + +Or just download `RaidToolkitSetup.exe` from [GitHub Releases](https://github.com/raid-toolkit/raid-toolkit-sdk/releases) — that is the easiest path for end users. + +`buildext.bat` — brute-force clean + rebuild for extension development. + +## WebSocket API + +**Endpoint:** `ws://localhost:9090` (the README/NITTYGRITTY says `wss://` but the actual code uses plain `ws://`) + +**Wire format** (`src/Shared/DataModel/SocketMessage.cs`): JSON 3-element array `[scope, channel, message]` + +**Channels:** `call`, `get`, `sub`, `unsub` (client→server); `set-promise`, `send-event` (server→client) + +**Call message:** `{ promiseId, methodName, parameters: [...] }` + +### Key scopes and methods + +**`account-api`** (`IAccountApi.cs`): +- `getAccounts()` → `Account[]` +- `getAccountDump(accountId)` → `AccountDump` — **this is the main extraction endpoint** +- `getHeroes(accountId, snapshot=false)` → full hero DTOs (includes awaken/blessing, not in dump) +- `getArtifacts(accountId)` → full artifact DTOs (includes ascendLevel/ascendBonus, not in dump) +- `getArena(accountId)` → arena + great hall +- `getAllResources(accountId)` → shards, market + +**`static-data`**: champion data, skill data, set definitions, localized strings + +**`realtime-api`**: last battle response, current view + +## Account Dump JSON Schema (Legacy Format) + +This is what `getAccountDump(accountId)` returns. File: `src/Shared/DataModel/GameData/AccountDumpClient.cs`. + +### Top-level `AccountDump` + +```json +{ + "fileVersion": "1.3", + "id": "...", + "name": "PlayerName", + "lastUpdated": "2024-01-15T12:00:00.0000000Z", + "arenaLeague": "GoldIV", + "artifacts": [...], + "heroes": [...], + "greatHall": { "magic": { "health": 3 }, "force": { ... }, ... }, + "factionGuardians": { "BannerLords": { "Epic": 2 }, ... }, + "shards": { "Mystery": { "count": 12 }, ... }, + "stagePresets": { "1": [12345, 67890], ... } +} +``` + +Note: no clan data, no blessing data, no champion skin data in this format. + +### `Hero` fields + +`id` int, `typeId` int, `grade` string ("Stars6"), `level` int, `empowerLevel` int, `experience` int, `fullExperience` int, `locked` bool, `inStorage` bool (= in vault), `isGuardian` bool, `marker` string ("None"/"Food"/"Frequent"/"Max"), `artifacts` int[] (equipped artifact IDs), `fraction` string-enum, `rarity` string-enum, `role` string-enum, `element` string-enum, `awakenLevel` int (0–6), `name` string, base stats: `health` double (×15!), `accuracy`, `attack`, `defense`, `criticalChance`, `criticalDamage`, `criticalHeal`, `resistance`, `speed`, `masteries` int[] (MasteryKindId values), `assignedMasteryScrolls` / `unassignedMasteryScrolls` / `totalMasteryScrolls` `{string: int}`, `skills` `Skill[]`. + +**Warning:** `health` is raw (multiplied by 15 internally by Extractor.cs:111). Divide by 15 to get the stat you see in-game... actually the game stores it this way natively. The value in the dump IS the in-game HP shown. + +### `Skill` fields + +`id` int, `typeId` int, `level` int + +### `Artifact` fields + +`id` int, `sellPrice` int, `price` int, `level` int (0–16), `isActivated` bool, `kind` string (slot name), `rank` string ("One"…"Six"), `rarity` string, `setKind` string (e.g. "LifeSet", "OffenseSet", "BadenSet"), `isSeen` bool, `failedUpgrades` int, `requiredFraction` string (hero faction or "None"), `primaryBonus` ArtifactBonus, `secondaryBonuses` ArtifactBonus[] + +### `ArtifactBonus` fields + +`kind` string (stat name), `isAbsolute` bool (flat if true, % if false), `value` double, `enhancement` double (glyph bonus), `level` int (substat upgrade count, 0–4) + +### Enum values + +**Artifact slots (`kind`):** `Weapon`, `Helmet`, `Chest`, `Gloves`, `Boots`, `Shield`, `Ring`, `Cloak`, `Banner`, `UnknownArtifact`, `UnknownAccessory` + +**Stats (`kind` in bonuses):** `Health`, `Attack`, `Defense`, `Speed`, `Resistance`, `Accuracy`, `CriticalChance`, `CriticalDamage`, `CriticalHeal` + +**Elements:** `Magic`, `Force`, `Spirit`, `Void` + +**Factions:** `BannerLords`, `HighElves`, `SacredOrder`, `CovenOfMagi`, `OgrynTribes`, `LizardMen`, `Skinwalkers`, `Orcs`, `Demonspawn`, `UndeadHordes`, `DarkElves`, `KnightsRevenant`, `Barbarians`, `NyresanElves`, `Samurai`, `Dwarves` + +**Rarity:** `Common`, `Uncommon`, `Rare`, `Epic`, `Legendary`, `Mythic` + +**Artifact Rarity:** `Common`, `Uncommon`, `Rare`, `Epic`, `Legendary`, `Mythical` (note: Mythical for artifacts vs Mythic for heroes) + +**Artifact Rank:** `One`, `Two`, `Three`, `Four`, `Five`, `Six` + +## Triggering a Dump + +Once RTK is installed and running on Windows: + +1. **Tray → Accounts → Dump button** — prompts "Use legacy format?" → click Yes → Save dialog. Target: this JSON file. +2. **WebSocket programmatically** — connect to `ws://localhost:9090`, call `account-api.getAccountDump(accountId)`. See DEVELOPERS.md for Python/TS/C# examples. + +There is no auto-export to a fixed file. Persisted internal state lives in `%LOCALAPPDATA%\RaidToolkit\data\` but is in an opaque per-extension format — don't parse it directly. + +## How the IL2CPP auto-update works + +On startup, RTK reads `%PlariumPlay%\gamestorage.gsfn` to find the installed game version, then looks for a locally-cached compiled DLL (`//Raid.Toolkit.Interop.dll`). If the game version changed or the DLL is stale, it reads `GameAssembly.dll` + `global-metadata.dat` from the game installation and generates a new .NET assembly using Il2CppToolkit. This assembly is loaded with `Assembly.LoadFrom(dllPath)` — loading from local disk only, not downloaded. + +The *RTK application itself* auto-updates via GitHub Releases API (see Security section below). + +--- + +## Security Audit (release/v2.8, audited 2026-05-24) + +### 🔴 FINDING: WebSocket binds to ALL interfaces (`0.0.0.0:9090`) + +**File:** `src/Application/Raid.Toolkit.Application.Core/appsettings.json:22` +```json +"listeners": [{ "ip": "Any", "port": 9090 }] +``` + +The WebSocket server listens on **all network interfaces** — not just loopback. This means any device on your local network (home Wi-Fi, coffee shop, VPN peers) can connect to port 9090 and read your full account data, call any API method, and (via extensions) potentially trigger actions. + +**Fix:** Change `"ip": "Any"` to `"ip": "127.0.0.1"` in both `appsettings.json` files. There is **no auth token** on the WebSocket, so localhost binding is the only access control. + +This is a fork improvement opportunity — upstream has the same bug. A PR to upstream would benefit the whole community. + +### 🟡 FINDING: Auto-update has no cryptographic signature check + +**File:** `src/Shared/Extensibility.Host/Services/UpdateService.cs:101-125` + +The update flow: polls GitHub Releases API (HTTPS) → downloads `RaidToolkitSetup.exe` into `%TEMP%` → runs it with `Process.Start(tempDownload, "/update ...")`. There is no hash verification or code-signing check on the downloaded installer. + +The risk is mitigated by: HTTPS (no MITM without a trusted cert), GitHub's release infrastructure, and the update repo is configurable in registry (`HKCU\SOFTWARE\RaidToolkit\Repository`, defaults to `raid-toolkit/raid-toolkit-sdk`). If someone tampered with the registry setting they could redirect updates. + +**Improvement:** Verify the GitHub release asset SHA256 against a published checksum, or check the PE code-signing certificate on the downloaded exe before launching. + +### 🟢 Network calls — only GitHub API and raidtoolkit.com avatars + +All outbound calls: +- `https://api.github.com/repos/raid-toolkit/raid-toolkit-sdk/releases` — update check +- `https://raidtoolkit.com/img/avatars/.png` — avatar image URL embedded in AccountInfo (cosmetic only, fetched by the client UI) + +No telemetry, no analytics, no Plarium API calls, no game-side exfiltration. + +### 🟢 No credential or browser data access + +Grepped for `password`, `cookie`, `keychain`, `chrome`, `firefox`, `browser` — zero hits in functional code. The only `%APPDATA%` access is to `RaidToolkit`'s own data directory and Plarium Play's install path. + +### 🟢 Registry access is scoped + +Reads/writes only: +- `HKCU\SOFTWARE\RaidToolkit` — RTK's own settings +- `HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run` — startup registration (user-opt-in) +- `HKU\.DEFAULT\SOFTWARE\PlariumPlayInstaller` — reads Plarium Play install path only + +No access to credential stores, browser data, or other applications. + +### 🟢 Assembly loading is local-only + +`Assembly.LoadFrom(dllPath)` at `ModelLoader.cs:95` loads from a path derived from the local game installation. The DLL is built from the game's own IL2CPP metadata on the user's machine — not downloaded. No arbitrary remote code execution path exists here. + +### 🟢 Dependencies are clean + +NuGet: all Microsoft.*, CommunityToolkit.*, Newtonsoft.Json, SuperSocket (known), il2cpptoolkit (same org — open source at github.com/nickel-lang/il2cppToolkit), CommandLineParser, Karambolo (file logging). No typosquats or mystery packages. + +npm (`@raid-toolkit/webclient` deps): `@remote-ioc/runtime` and `@remote-ioc/ws-router` are maintained by `dnchattan@gmail.com` — the same author as the main package. Not a supply-chain risk. + +### 🟢 No obfuscation + +Source is straightforward C#/TypeScript. No base64 blobs, no encoded URLs, no P/Invoke into hooking APIs beyond what WinUI3 requires (user32.dll for window management, shell32.dll for file association — both standard). + +--- + +## Priority Improvements + +1. **Fix `"ip": "Any"` → `"ip": "127.0.0.1"`** in both appsettings.json files — security fix, high priority +2. **Add checksum verification** in UpdateService before running the downloaded installer +3. **Export command** — add a `--dump-account ` CLI flag so the tray UI isn't required +4. **Awaken/blessing in dump** — `Extractor.cs` doesn't populate `awakenRank`, `blessing`, or artifact `ascendLevel` even though the DTOs have the fields; fix for v2.8 parity with actual game data +5. **Claude.ai export script** — see `../` (the RAID-Helper parent project) for the Mac-side analysis tool diff --git a/src/Application/Raid.Toolkit.Application.Core/appsettings.json b/src/Application/Raid.Toolkit.Application.Core/appsettings.json index 3e1ae8f3..1dff26ff 100644 --- a/src/Application/Raid.Toolkit.Application.Core/appsettings.json +++ b/src/Application/Raid.Toolkit.Application.Core/appsettings.json @@ -29,7 +29,7 @@ "name": "raid-toolkit-service", "listeners": [ { - "ip": "Any", + "ip": "127.0.0.1", "port": 9090 } ] diff --git a/src/Application/Raid.Toolkit/appsettings.json b/src/Application/Raid.Toolkit/appsettings.json index 3e1ae8f3..1dff26ff 100644 --- a/src/Application/Raid.Toolkit/appsettings.json +++ b/src/Application/Raid.Toolkit/appsettings.json @@ -29,7 +29,7 @@ "name": "raid-toolkit-service", "listeners": [ { - "ip": "Any", + "ip": "127.0.0.1", "port": 9090 } ] From f942294ef094907b3a102bd16e1690a9c5f9e2d5 Mon Sep 17 00:00:00 2001 From: asultan Date: Sun, 24 May 2026 15:05:49 -0300 Subject: [PATCH 2/7] bump version to 2.9, remove NuGet publish step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fork diverges from upstream with security fix (localhost binding). Version bumped to 2.9 to distinguish from upstream 2.8.x releases. NuGet/npm/PyPI publish steps removed — this fork builds for personal use only; no package registry secrets configured. --- .github/workflows/app-publish.yml | 13 ------------- version.json | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/.github/workflows/app-publish.yml b/.github/workflows/app-publish.yml index 6aa5ccd2..b304d8e9 100644 --- a/.github/workflows/app-publish.yml +++ b/.github/workflows/app-publish.yml @@ -108,16 +108,3 @@ jobs: src/Template/vsix/bin/release/RTKExtensionTemplate.vsix ThirdPartyNotice.txt - # NuGet Push - - name: Push client package to Nuget registry - run: | - dotnet nuget push publish/nuget/Raid.Common.${{ steps.rtk_version.outputs.NuGetPackageVersion }}.nupkg -k $env:NUGET_PUBLISH_TOKEN -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push publish/nuget/Raid.Client.${{ steps.rtk_version.outputs.NuGetPackageVersion }}.nupkg -k $env:NUGET_PUBLISH_TOKEN -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push publish/nuget/Raid.Model.${{ steps.rtk_version.outputs.NuGetPackageVersion }}.nupkg -k $env:NUGET_PUBLISH_TOKEN -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push publish/nuget/Raid.Toolkit.DataModel.${{ steps.rtk_version.outputs.NuGetPackageVersion }}.nupkg -k $env:NUGET_PUBLISH_TOKEN -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push publish/nuget/Raid.Toolkit.Injection.${{ steps.rtk_version.outputs.NuGetPackageVersion }}.nupkg -k $env:NUGET_PUBLISH_TOKEN -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push publish/nuget/Raid.Toolkit.Extensibility.${{ steps.rtk_version.outputs.NuGetPackageVersion }}.nupkg -k $env:NUGET_PUBLISH_TOKEN -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push publish/nuget/Raid.Toolkit.Extensibility.Host.${{ steps.rtk_version.outputs.NuGetPackageVersion }}.nupkg -k $env:NUGET_PUBLISH_TOKEN -s https://api.nuget.org/v3/index.json --skip-duplicate - dotnet nuget push publish/nuget/Raid.Toolkit.Extensibility.Tasks.${{ steps.rtk_version.outputs.NuGetPackageVersion }}.nupkg -k $env:NUGET_PUBLISH_TOKEN -s https://api.nuget.org/v3/index.json --skip-duplicate - env: - NUGET_PUBLISH_TOKEN: ${{ secrets.NUGET_PUBLISH_TOKEN }} diff --git a/version.json b/version.json index 8f717f31..5a21c1c2 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "2.8", + "version": "2.9", "assemblyVersion": { "precision": "revision" }, From 411eaec82b2f969d2d4bce9aa7cc62cf9f29aeae Mon Sep 17 00:00:00 2001 From: asultan Date: Sun, 24 May 2026 15:07:52 -0300 Subject: [PATCH 3/7] remove defunct mickem/clean-after-action causing job setup failure --- .github/workflows/app-publish.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/app-publish.yml b/.github/workflows/app-publish.yml index b304d8e9..20f3b140 100644 --- a/.github/workflows/app-publish.yml +++ b/.github/workflows/app-publish.yml @@ -29,8 +29,6 @@ jobs: Client_csproj: src\ClientSDK\DotNet\Raid.Client.csproj steps: - - uses: mickem/clean-after-action@v1 - - name: Checkout uses: actions/checkout@v2 with: From a20b2dcb14dbc9f992924bf924d1bd2f23c39d52 Mon Sep 17 00:00:00 2001 From: asultan Date: Sun, 24 May 2026 15:11:23 -0300 Subject: [PATCH 4/7] modernise CI: update all actions to current versions, inline branch vars --- .github/workflows/app-publish.yml | 35 ++++++++++++++----------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/.github/workflows/app-publish.yml b/.github/workflows/app-publish.yml index 20f3b140..b60bb271 100644 --- a/.github/workflows/app-publish.yml +++ b/.github/workflows/app-publish.yml @@ -30,47 +30,45 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - name: Set branch-based environment variables - uses: iamtheyammer/branch-env-vars@v1.0.4 - with: - PRERELEASE: | - main:true - !default:false - PRERELEASEN: | - main:1 - !default:0 + shell: pwsh + run: | + if ("${{ github.ref_name }}" -eq "main") { + echo "PRERELEASE=true" >> $env:GITHUB_ENV + echo "PRERELEASEN=1" >> $env:GITHUB_ENV + } else { + echo "PRERELEASE=false" >> $env:GITHUB_ENV + echo "PRERELEASEN=0" >> $env:GITHUB_ENV + } - # Install the .NET Core workload - name: Install .NET Core - uses: actions/setup-dotnet@v1 + uses: actions/setup-dotnet@v4 with: dotnet-version: | 5.0.x 6.0.x - # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild - name: Setup MSBuild.exe - uses: microsoft/setup-msbuild@v1.0.2 + uses: microsoft/setup-msbuild@v2 - # Versions - - uses: dotnet/nbgv@master + - name: Set version with nbgv + uses: dotnet/nbgv@master id: rtk_version with: setAllVars: true - - uses: actions/cache@v1 + - uses: actions/cache@v4 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} restore-keys: | ${{ runner.os }}-nuget- - # Restore the application to populate the obj folder with RuntimeIdentifiers - name: Restore the application run: msbuild $env:Solution_Name /t:Restore /p:Configuration=Release @@ -94,7 +92,7 @@ jobs: BuildOutputDirectory: ..\Application\Raid.Toolkit\bin\x64\Release\net6.0-windows10.0.19041.0\win10-x64 - name: Create release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: tag_name: v${{ steps.rtk_version.outputs.Version }} prerelease: ${{ env.PRERELEASE }} @@ -105,4 +103,3 @@ jobs: src/Setup/out/RaidToolkitSetup.exe src/Template/vsix/bin/release/RTKExtensionTemplate.vsix ThirdPartyNotice.txt - From 29dc0288cc76462b2ace7eb8cb4056110cdced5e Mon Sep 17 00:00:00 2001 From: asultan Date: Sun, 24 May 2026 15:21:01 -0300 Subject: [PATCH 5/7] fix release: add contents:write permission, tolerate missing vsix --- .github/workflows/app-publish.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/app-publish.yml b/.github/workflows/app-publish.yml index b60bb271..55126a1f 100644 --- a/.github/workflows/app-publish.yml +++ b/.github/workflows/app-publish.yml @@ -20,6 +20,8 @@ on: jobs: build: runs-on: windows-latest + permissions: + contents: write env: IS_CI: true @@ -97,6 +99,7 @@ jobs: tag_name: v${{ steps.rtk_version.outputs.Version }} prerelease: ${{ env.PRERELEASE }} body_path: CHANGES.md + fail_on_unmatched_files: false files: | UPGRADE_2.0.md publish/RTK/Raid.Toolkit.exe From 98aa05039412907225d6308426d5c93f372199d3 Mon Sep 17 00:00:00 2001 From: asultan Date: Sun, 24 May 2026 16:22:10 -0300 Subject: [PATCH 6/7] add .claude skill and settings for Claude Code users --- .claude/commands/rtk.md | 53 +++++++++++++++++++++++++++++++++++++++++ .claude/settings.json | 12 ++++++++++ 2 files changed, 65 insertions(+) create mode 100644 .claude/commands/rtk.md create mode 100644 .claude/settings.json diff --git a/.claude/commands/rtk.md b/.claude/commands/rtk.md new file mode 100644 index 00000000..d23cff84 --- /dev/null +++ b/.claude/commands/rtk.md @@ -0,0 +1,53 @@ +# RTK — Raid Toolkit SDK + +Use this skill when working on the Raid Toolkit SDK source code. + +## Key facts + +- **Stable branch:** `release/v2.8` — build and ship from here +- **In progress:** `main` — v3.0 restructuring, not production-ready +- **Platform:** Windows only (WinUI3, Win32, IL2CPP). Cannot build on macOS/Linux. +- **Full docs:** See `CLAUDE.md` in the repo root — architecture, JSON schema, security audit, API reference + +## Project layout + +| Path | What it is | +|---|---| +| `src/Application/Raid.Toolkit/` | WinUI3 tray app — main entry point | +| `src/Application/Raid.Toolkit.Application.Core/` | DI host, WebSocket setup, update service | +| `src/Shared/DataModel/` | DTOs, enums, WebSocket message format, API contracts | +| `src/Shared/Model/` | IL2CPP glue — `ModelLoader.cs`, `PlariumPlayAdapter.cs` | +| `src/Extensions/Account/` | Account extraction — `AccountApi.cs`, `Extractor.cs` | +| `src/Shared/Common/GitHub/` | Auto-update logic | +| `src/Setup/` | WiX installer → `RaidToolkitSetup.exe` | + +## Build + +``` +msbuild SDK.sln -t:"Build;Pack" -p:Configuration=Release -p:Platform=x64 +``` + +CI: `.github/workflows/app-publish.yml` triggers on push to `release/**` or `main` when source paths change. Creates a GitHub Release with `RaidToolkitSetup.exe` automatically. + +## WebSocket API (`ws://localhost:9090`) + +Wire format: `[scope, channel, message]` (3-element JSON array). + +Key methods on `account-api` scope: +- `getAccounts()` → account list +- `getAccountDump(accountId)` → full legacy dump (the main extraction endpoint) +- `getHeroes(accountId)` / `getArtifacts(accountId)` → richer DTOs with awaken/blessing/ascend fields + +Full schema in `CLAUDE.md`. + +## Known issues / open improvements + +1. `Extractor.cs` does not populate `awakenRank`, `blessing`, or artifact `ascendLevel` in the legacy dump even though the DTOs have these fields +2. No `--dump-account ` CLI flag — requires the tray UI to export +3. Auto-update (`UpdateService.cs`) downloads and runs `RaidToolkitSetup.exe` without verifying a cryptographic signature + +## Security notes + +- WebSocket binds to `127.0.0.1` in this fork (fixed from upstream's `Any`/`0.0.0.0`) +- No telemetry, no credential access, no browser data access — verified in audit (see `CLAUDE.md`) +- IL2CPP assembly generation reads only local game files, no remote code loading diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..7b0bf11b --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,12 @@ +{ + "permissions": { + "allow": [ + "Bash(git *)", + "Bash(dotnet *)", + "Bash(msbuild *)", + "Bash(grep *)", + "Bash(find *)", + "Read(**)" + ] + } +} From 9d27ace6e90f16708794ea637d076c1afd315e36 Mon Sep 17 00:00:00 2001 From: asultan Date: Sun, 24 May 2026 19:27:34 -0300 Subject: [PATCH 7/7] docs: add CI/release process, install steps, and launch diagnostics to CLAUDE.md and skill --- .claude/commands/rtk.md | 56 +++++++++++++++++++++++++++- CLAUDE.md | 82 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 4 deletions(-) diff --git a/.claude/commands/rtk.md b/.claude/commands/rtk.md index d23cff84..3a01dddb 100644 --- a/.claude/commands/rtk.md +++ b/.claude/commands/rtk.md @@ -21,13 +21,65 @@ Use this skill when working on the Raid Toolkit SDK source code. | `src/Shared/Common/GitHub/` | Auto-update logic | | `src/Setup/` | WiX installer → `RaidToolkitSetup.exe` | -## Build +## Build (Windows only) ``` msbuild SDK.sln -t:"Build;Pack" -p:Configuration=Release -p:Platform=x64 ``` -CI: `.github/workflows/app-publish.yml` triggers on push to `release/**` or `main` when source paths change. Creates a GitHub Release with `RaidToolkitSetup.exe` automatically. +## CI / Releasing + +**No manual tags needed.** Version auto-calculated by Nerdbank.GitVersioning (`version.json` major.minor + commit count). + +To trigger a release: push any source change to `release/**` or `main`. Doc-only commits (`*.md`) are excluded from the trigger. + +To force a release with no other changes: bump `version.json`. + +CI workflow: `.github/workflows/app-publish.yml` +- Builds on `windows-latest` +- Produces `RaidToolkitSetup.exe` (WiX installer) + `Raid.Toolkit.exe` +- Creates a GitHub Release automatically +- NuGet/npm/PyPI publish steps removed (no secrets configured in this fork) + +### Key CI fixes in this fork (do not revert) + +| What | Why | +|---|---| +| Removed `mickem/clean-after-action@v1` | Repo deleted upstream — caused "Set up job" failure | +| Replaced `iamtheyammer/branch-env-vars@v1.0.4` | Personal repo action gone — now inline PowerShell | +| All actions bumped to current versions | v1/v2 deprecated and removed by GitHub | +| Added `permissions: contents: write` | Required for release creation — missing = 403 | +| Added `fail_on_unmatched_files: false` | VSIX not always present — without this, release step errors | + +## Installing the release on Windows + +Prerequisites: +- Windows 10 build 19041+ or Windows 11 +- .NET 6 Desktop Runtime: `winget install Microsoft.DotNet.DesktopRuntime.6` +- Windows App SDK 1.4: `winget install Microsoft.WindowsAppRuntime.1.4` +- Plarium Play + RAID installed + +Steps: +1. Download `RaidToolkitSetup.exe` from [releases](https://github.com/asultan80/raid-toolkit-sdk/releases/latest) +2. Right-click → **Run as administrator** +3. SmartScreen prompt → **More info → Run anyway** (build is unsigned) +4. Launch RAID via Plarium Play, wait for lobby +5. RTK tray icon should appear + +## Diagnosing launch failures — read logs first + +```powershell +# RTK log +Get-ChildItem "$env:LOCALAPPDATA\RaidToolkit\Logs" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 | Get-Content | Select-Object -Last 50 + +# Windows crash events +Get-WinEvent -LogName Application -MaxEvents 50 | Where-Object { $_.LevelDisplayName -eq "Error" } | Select-Object -First 5 | Format-List + +# Check prerequisites +Get-AppxPackage -Name "Microsoft.WindowsAppRuntime*" | Select-Object Name, Version +dotnet --list-runtimes | Select-String "Microsoft.WindowsDesktop" +Get-ItemProperty "Registry::HKEY_USERS\.DEFAULT\SOFTWARE\PlariumPlayInstaller" -ErrorAction SilentlyContinue +``` ## WebSocket API (`ws://localhost:9090`) diff --git a/CLAUDE.md b/CLAUDE.md index cb31892c..a4647c2d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -35,10 +35,88 @@ This document covers architecture, build instructions, the account-dump JSON sch msbuild SDK.sln -t:"Build;Pack" -p:Configuration=Release -p:Platform=x64 ``` -Or just download `RaidToolkitSetup.exe` from [GitHub Releases](https://github.com/raid-toolkit/raid-toolkit-sdk/releases) — that is the easiest path for end users. - `buildext.bat` — brute-force clean + rebuild for extension development. +## CI / Release Process + +Releases are built automatically by GitHub Actions on every push to `main` or `release/**` that touches source paths. **No manual tagging needed** — the version is calculated by Nerdbank.GitVersioning from `version.json` + commit count. + +### Workflow file + +`.github/workflows/app-publish.yml` — triggers on push to `main` or `release/**` when any of these paths change: +`version.json`, `Directory.Build.props`, `src/Application/**`, `src/Extensions/**`, `src/Shared/**`, `src/Setup/**`, `src/ClientSDK/DotNet/**`, `.github/workflows/app-publish.yml` + +`*.md` files are **excluded** — doc-only commits do not trigger a build. + +### To trigger a release + +Make any meaningful change to source and push to `release/v2.9` (or whatever the current release branch is). If you only have doc changes and need to force a release, touch `version.json` (e.g. bump the patch). + +### Release assets produced + +| File | What it is | +|---|---| +| `RaidToolkitSetup.exe` | WiX burn bundle installer — what end users install | +| `Raid.Toolkit.exe` | Standalone launcher exe | +| `RTKExtensionTemplate.vsix` | VS extension template (dev only) | +| `ThirdPartyNotice.txt` | OSS attribution | +| `UPGRADE_2.0.md` | Migration notes | + +### Version scheme + +`version.json` sets the major.minor (e.g. `"version": "2.9"`). The full tag is `v{major}.{minor}.{commitHeight}.{buildNumber}` — e.g. `v2.9.0.10716`. Bump `version.json` when you want a clean minor version boundary. + +### Known CI fixes applied to this fork (do not revert) + +These were broken in the upstream workflow and fixed here: + +| Fix | Reason | +|---|---| +| Removed `mickem/clean-after-action@v1` | Action repo was deleted; caused "Set up job" failure | +| Replaced `iamtheyammer/branch-env-vars@v1.0.4` with inline PowerShell | Personal repo action, gone; replaced with `echo "VAR=val" >> $env:GITHUB_ENV` | +| Updated all actions to current versions (`checkout@v4`, `setup-dotnet@v4`, `cache@v4`, `setup-msbuild@v2`, `action-gh-release@v2`) | v1/v2 versions deprecated and removed | +| Added `permissions: contents: write` to the job | Required for `softprops/action-gh-release` to create releases; missing caused release step to fail with 403 | +| Added `fail_on_unmatched_files: false` to release step | VSIX not always built; without this the release step errors on missing file | +| Removed NuGet/npm/PyPI publish steps | No registry secrets configured in this fork; steps would always fail | + +### Installing the release on Windows + +Prerequisites (check before installing): +1. Windows 10 build 19041+ or Windows 11 +2. .NET 6 Desktop Runtime (x64) — `winget install Microsoft.DotNet.DesktopRuntime.6` +3. Windows App SDK 1.4 runtime — `winget install Microsoft.WindowsAppRuntime.1.4` +4. Plarium Play installed with RAID: Shadow Legends + +Install steps: +1. Download `RaidToolkitSetup.exe` from the [latest release](https://github.com/asultan80/raid-toolkit-sdk/releases/latest) +2. Right-click → **Run as administrator** (required for registry writes) +3. If Windows SmartScreen appears: click **More info → Run anyway** (build is unsigned) +4. Launch RAID via Plarium Play, wait for lobby +5. RTK tray icon appears — click → **Accounts** to verify it attached + +### Diagnosing launch failures + +If RTK installs but fails to launch: + +```powershell +# 1. Check RTK's own log +Get-Content "$env:LOCALAPPDATA\RaidToolkit\Logs\$(Get-ChildItem "$env:LOCALAPPDATA\RaidToolkit\Logs" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 -ExpandProperty Name)" | Select-Object -Last 50 + +# 2. Check Windows Event Log for crash +Get-WinEvent -LogName Application -MaxEvents 50 | Where-Object { $_.LevelDisplayName -eq "Error" } | Select-Object -First 5 | Format-List + +# 3. Verify Windows App SDK installed +Get-AppxPackage -Name "Microsoft.WindowsAppRuntime*" | Select-Object Name, Version + +# 4. Verify .NET 6 Desktop Runtime +dotnet --list-runtimes | Select-String "Microsoft.WindowsDesktop" + +# 5. Verify Plarium Play registry key exists (RTK needs this to find the game) +Get-ItemProperty "Registry::HKEY_USERS\.DEFAULT\SOFTWARE\PlariumPlayInstaller" -ErrorAction SilentlyContinue +``` + +Always read the logs first before installing anything. + ## WebSocket API **Endpoint:** `ws://localhost:9090` (the README/NITTYGRITTY says `wss://` but the actual code uses plain `ws://`)