From 4fdf74831aa897e716b5041265dcc8ed4c5dbe81 Mon Sep 17 00:00:00 2001 From: Fazorath Date: Wed, 28 Oct 2026 21:55:14 +0000 Subject: [PATCH] Ship the registered EVE client ID as the sign-in default (#57) --- .claude/skills/run-windows/SKILL.md | 65 +++++++++++++++++++++++++++++ EveProfitManager/sso.py | 10 ++--- EveProfitManager/test_sso.py | 20 ++++++++- README.md | 2 + 4 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 .claude/skills/run-windows/SKILL.md diff --git a/.claude/skills/run-windows/SKILL.md b/.claude/skills/run-windows/SKILL.md new file mode 100644 index 0000000..b46035a --- /dev/null +++ b/.claude/skills/run-windows/SKILL.md @@ -0,0 +1,65 @@ +--- +name: run-windows +description: Launch, check and screenshot AbyssTracker on the Windows PC with a live EVE character logged in. Use when asked to test the app in its real setting (ESI token, location, run detection, wallet, every page, pocket mode on top of the EVE client). +--- + +# Run AbyssTracker on the Windows PC + +## Hard rules (read first, never negotiable) + +- **Computer use may control only:** AbyssTracker, a terminal, and a browser. The browser may open only `login.eveonline.com`, `127.0.0.1:8765/callback`, and Gmail (see below). +- **Never send input to the EVE launcher or client:** no clicks, no keystrokes, no window automation. CCP's EULA bans automating client input. If EVE has focus, stop; don't click. Reading EVE's window (`GetWindowRect`, `IsIconic`, its style flags) is fine; never call `SetWindowPos`, `SetForegroundWindow`, `ShowWindow` or send messages to an EVE window handle. +- **Never type the EVE account password. Never handle authenticator-app codes.** If the sign-in asks for either, stop and hand over to the user. +- **You may approve the ESI SSO sign-in yourself:** pick the character and click Authorize. +- **Emailed verification codes:** you may open Gmail and read **only the newest CCP/EVE email** with the code. Read nothing else; archive, delete and mark nothing. **The moment you open Gmail, send the user a push notification, and start your final report with a bold line saying you opened Gmail, when, and why.** +- **No undocking, no filaments, no Abyssal activation, ever.** The character stays docked for the whole test. +- **Never open the real `tracker.db`.** Every run sets `ABYSS_TRACKER_DB` to a throwaway file. +- **Live screenshots stay on the PC, outside the repo** (they show character name, wallet, location; the repo is public). The PR lists pass/fail per check. Any image put in a PR has the name, portrait, wallet and location blurred first. + +## How you reach the desktop + +Use the Claude desktop app's computer use on the PC. SSH is not part of the rig: an SSH session shows no GUI and can't read the ESI token from Windows Credential Manager. The PC's OpenSSH server is off at the moment, so don't plan on SSH even for headless jobs; run tests from the terminal on the desktop. + +## Before a run (the user does this) + +Log in through the EVE launcher, dock the character, and set EVE to windowed or fixed-window mode so the pocket window can sit on top. If EVE isn't docked and windowed, stop and ask. + +## Launch + +`EVE_CLIENT_ID` is optional: the app ships a built-in client ID (callback `http://127.0.0.1:8765/callback`). Set the variable only to override it with another registered app's client ID. + +```powershell +git clone https://github.com/Fazorath/AbyssTracker.git $env:TEMP\abyss-rig # or git pull in an existing clone +cd $env:TEMP\abyss-rig +python -m venv .venv +.venv\Scripts\pip install -r requirements.txt +cd EveProfitManager +..\.venv\Scripts\python -m unittest discover # headless sanity check first +$env:ABYSS_TRACKER_DB = "$env:TEMP\abyss-rig-throwaway.db" +..\.venv\Scripts\python gui.py +``` + +Delete the throwaway db afterwards. The release `.exe` is out of scope. + +## Checks (screenshot each; save under `%USERPROFILE%\Pictures\abyss-rig\\`, never in the repo) + +1. **Start:** the app opens from the fresh clone with no errors in the terminal. +2. **Token:** Settings → sign in. The browser opens `login.eveonline.com`; pick the character and Authorize (see rules for passwords, codes and email). Close and reopen the app: it must be signed in with no browser step (refresh works from the stored token). +3. **Location and detection:** with the character docked, switch on **Detect runs from EVE** on the Abyss page. Leave it polling at least a minute. It must not start the timer or prompt to log a run (no false Abyss entry). Report only that the character reads as not in the Abyss; don't write the system or station name into the report or PR. +4. **Wallet:** the Abyss page's Wallet stat shows "from EVE at HH:MM". Ask the user to read the wallet in the client (you may not touch EVE) and compare; they must match. +5. **Pages:** open and screenshot Abyss, Incursion, History and pocket mode. +6. **Pocket on top:** enter pocket mode and check it by window geometry, not a screenshot (EVE is masked in computer-use screenshots). Read the EVE client and pocket windows' rects and the pocket's `WS_EX_TOPMOST` flag, move the pocket over the client with `SetWindowPos` on the pocket's own handle, and confirm the pocket is above the client in z-order. Pass if it is; fail if it's covered or loses topmost. After **Unpin**, the topmost flag must clear. See the notes below for the calls. + +Active-ship and cargo checks are not part of this skill (see #52). + +## Report + +Lead with the Gmail line if you opened Gmail. Then list pass/fail for each check above, with a short note for any fail. Don't paste screenshots with personal details. + +## Notes from the first run + +- `request_access` only matches installed apps: ask for "Python 3.11" to drive the Tk window (not "python" or "AbyssTracker"). Don't grant the EVE client; its windows are masked in screenshots, which is what you want. +- The refresh token may already be in Windows Credential Manager from an earlier sign-in. If Settings shows the character signed in, don't sign in again: restarting the app and fetching the wallet proves the refresh, and Gmail stays closed. +- The location check can run headless with the app's own code (`Account().client()` plus `location.get_location`); print only `in_abyss`, never the system or token. +- Pocket-on-top is checked without touching EVE: read the EVE client (`exefile`) and pocket windows with Win32 `GetWindowRect`, `IsIconic` and the `WS_EX_TOPMOST` flag, and move the pocket window over the client with `SetWindowPos` on the pocket's own handle. An EVE window that reads as minimized (rect -32000) means the user must restore it. +- The wallet check compares against the figure the user reads in the client; ESI caches it about two minutes, so expect rounding or small drift. diff --git a/EveProfitManager/sso.py b/EveProfitManager/sso.py index 36d693d..57f5108 100644 --- a/EveProfitManager/sso.py +++ b/EveProfitManager/sso.py @@ -37,6 +37,7 @@ class InvalidToken(Exception): class SignInError(Exception): pass +DEFAULT_CLIENT_ID = "28c1d7859b4e49f6bb97a13441e8be7c" @dataclass @@ -46,13 +47,8 @@ class Character: def _client_id(): - client_id = os.environ.get("EVE_CLIENT_ID") - if not client_id: - raise SignInError( - "Set the EVE_CLIENT_ID environment variable to your app's client ID " - "(register at https://developers.eveonline.com/applications)." - ) - return client_id + # PKCE with no client secret: the client ID is public, so it ships as the default. + return os.environ.get("EVE_CLIENT_ID") or DEFAULT_CLIENT_ID def _port(): diff --git a/EveProfitManager/test_sso.py b/EveProfitManager/test_sso.py index 64a9e93..78d7580 100644 --- a/EveProfitManager/test_sso.py +++ b/EveProfitManager/test_sso.py @@ -4,7 +4,10 @@ import jwt from cryptography.hazmat.primitives.asymmetric import rsa -from sso import InvalidToken, validate_token +import os +from unittest import mock + +from sso import DEFAULT_CLIENT_ID, InvalidToken, _client_id, validate_token CLIENT_ID = "my-client-id" KEY = rsa.generate_private_key(public_exponent=65537, key_size=2048) @@ -53,5 +56,20 @@ def test_rejects_bad_tokens(self): validate(token) +class ClientIdTests(unittest.TestCase): + def test_default_when_unset(self): + with mock.patch.dict(os.environ, clear=False): + os.environ.pop("EVE_CLIENT_ID", None) + self.assertEqual(_client_id(), DEFAULT_CLIENT_ID) + + def test_default_when_empty(self): + with mock.patch.dict(os.environ, {"EVE_CLIENT_ID": ""}): + self.assertEqual(_client_id(), DEFAULT_CLIENT_ID) + + def test_env_overrides_default(self): + with mock.patch.dict(os.environ, {"EVE_CLIENT_ID": "mine"}): + self.assertEqual(_client_id(), "mine") + + if __name__ == "__main__": unittest.main() diff --git a/README.md b/README.md index ba0787e..782012a 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ This program is designed to help users track their profits and time spent during payout) field and Log button, the session's profit, ISK/hour and runs, and the last three runs. It shares the timer and session with the full window; **Unpin** lets other windows cover it and **Expand** brings the full window back. + - **Sign-in:** works out of the box with the app's built-in EVE client ID (public, PKCE, no secret). Set the + `EVE_CLIENT_ID` environment variable only to override it with your own registered application. - **Run detection:** when signed in, switch on **Detect runs from EVE** in the session toolbar. The app polls your character's location (ESI caches it for 5 seconds), starts the timer when you enter Abyssal Deadspace, and on exit pauses it and prompts you to enter your wallet and log the run.