Core finds the key by the token kid and loads the JWKS again for an
unknown kid, at most every 10 s. JWT_PUBLIC_KEY is used only until the
first JWKS load works, so a key removed from the JWKS cannot verify
later. While that key still works, requests do not wait for a slow
Auth.
Achievements were fetched only when a game detail page was opened, and a Steam error was stored as "no achievements" or "hidden". A background run after each library sync now fetches schemas and the unlocks of games with new playtime, one Steam call per second for all runs together, and never overwrites stored data on a Steam error. Adds GET /api/library/achievements/summary, achievement counts on GameDto and the public profile, and migration V7 (playtime_at_refresh).
GET /api/library/picker returns random backlog games for a time budget, HIGH priority first. PUT /games/{appid}/status changes only the status, so the picker does not need the game detail (and its Steam calls) to keep rating, notes and priority.
GET /api/public/profiles/library with X-Profile-Ticket returns totals, status
counts, playing and finished games with rating; never notes, priority or the
Steam ID. Login filters reject the ticket, and Core keeps no copy of the
privacy flag.
Each sync fetches the public wishlist and the store name, price and discount
(batches of 100) and replaces the user's wishlist_game rows, without games
the user owns. A Steam error keeps the old list, a failed store batch keeps
the last known price, and a Steam ID change drops the old account's list.
GET /api/library/wishlist returns it newest first.
Each sync records the growth of playtime per game and day (Europe/Berlin).
The first successful sync of a Steam account is only the baseline, tracked in
user_steam_sync.history_steam_id, so a new or failed account never turns its
whole playtime into one day. A nightly sync at 23:55 runs the recently used
accounts one after the other. GET /api/library/activity returns minutes per
day and the games of Steam's last two weeks.
Games without a rating or priority come last in both directions. Priority
sorts HIGH, MEDIUM, LOW instead of by enum name, and appid breaks every tie,
so pages no longer repeat or skip games with equal values.
GET /api/library/summary returns the game count per status, the never-started
count and a random backlog game. exclude=<appid> makes a new pick differ from
the current one.
The per-class container was stopped under the Spring context that the next
test class reused, so a second integration test class failed with
"Connection is not available".
New games start as BACKLOG, or PLAYING when they have playtime. The sync
never changes a status later. PUT /api/library/games/{appid}/backlog sets
all four fields; /api/library/games filters by status and name (q).
/api/steam/test/{steamId} let anyone query any Steam profile with our API key. /internal/** had no controller but was open for any future one. Actuator now exposes only health, without details. The management block was also indented under endpoints, so show-details never applied.
An empty Steam answer (error, private profile, wrong ID) was stored as OK and
soft-deleted the whole library. It is now FAILED, keeps the library and is
retried after 15 minutes (app.library.failed-retry-minutes).
The automatic sync now also runs when the Steam ID in the token differs from
the stored one, and removes the games of the previous Steam account.
Captures the Core slices of the cross-service product roadmap: per-game
tracking schema (status, rating, notes, completion date), picker
endpoint, HLTB integration, achievement aggregation, goals + digest
data, wishlist + sale alerts, library enrichment, and public profile
data. Cross-links to the umbrella roadmap in ToBePlayed-Deployment.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduce SteamOwnedGamesResponse and SteamProfileAndGamesResponse DTOs and extend SteamApiService with getOwnedGames(...) and getFullPlayerProfile(...) to fetch and combine player summary and owned games. Update SteamTestController to return the combined profile/games response. Remove redundant Steam service URL entries from application.yml. Add SteamApiServiceTest to cover player summary, owned games (including null fields), and the combined profile flow; service falls back to empty lists on errors.
Move steam_adapter sources from domain.* to modules.* and rename controller package to api. Update package declarations and imports across SteamTestController, SteamPlayerSummaryResponse, SteamClientConfig, and SteamApiService. Update README to re-label Controller -> API layer and Domain -> Business layer and adjust wording about layer boundaries. Also normalize file endings/newlines in several Java files. No functional logic changes were made.
Introduce Steam integration: add SteamClientConfig (RestClient bean), SteamApiService (calls GetPlayerSummaries and returns a Player DTO), SteamPlayerSummaryResponse DTO, and SteamTestController (/api/steam/test/{steamId}) for quick testing. Update SecurityConfig to permit the test endpoint and adjust the SecurityFilterChain bean signature. Add Steam API settings: base-url in application.yml and a dev API key in application-dev.yml. Includes basic error logging and optional response handling when no player is found.
Add project bootstrap for build, CI/CD, and local development. Introduces Maven Wrapper (mvnw, mvnw.cmd, .mvn/wrapper), multi-stage Dockerfile, docker-compose files (compose.yaml, docker-compose.dev.yml), .env, banner and README. Adds Gitea Actions workflow to build, test and push container images. Update application.yml (port -> 8090, virtual threads, API versioning, management/actuator/prometheus settings, Steam API config) and add application-dev.yml for local overrides. Extend pom.xml with caching, observability (actuator, micrometer/prometheus), testing/dev dependencies (testcontainers, devtools, additional spring test modules) to support CI and local testing.