lobo 0a5186782f
Build, Test & Push Core Service / quality-check (push) Successful in 41s
Build, Test & Push Core Service / docker (push) Successful in 1m20s
test: generate the JWT test keys, drop application-dev.yml
The dev config held real keys. Local dev config now lives outside the repo; integration tests create a fresh Ed25519 keypair per run.
2026-09-25 08:37:55 +02:00

To Be Played – Core Service

Business service of To Be Played, a Steam backlog tracker. It syncs the user's Steam library, stores the backlog (status, rating, notes, priority), tracks playtime per day, syncs the wishlist and adds time-to-beat data from IGDB.

To Be Played is split into three repositories:

Repository Role
ToBePlayed-Auth Users, login, settings, signs JWTs
ToBePlayed-Core (this one) Steam library, backlog, wishlist, stats; verifies JWTs
ToBePlayed-Frontend React single-page app

Features

  • Steam sync: owned games, playtime and achievements through the Steam Web API. Manual sync plus a nightly sync. Resilience4j retries and rate-limits every Steam call; Caffeine caches game counts and player summaries.
  • Backlog: status (BACKLOG, PLAYING, FINISHED, COMPLETED = 100 %, DROPPED), rating 1–5, notes, priority, filters and sorting. "Pile of Shame" summary with a random suggestion of what to play.
  • Playtime history: one row per game and day, for the activity view and the "most played in the last two weeks" dashboard banner.
  • Wishlist: synced from Steam with store price and discount.
  • Time to beat: story, extras and completionist hours from the IGDB API. Optional: without credentials the feature is off and the rest works.
  • Public profile data: totals, status counts, games in progress and finished games with rating. Readable only with a profile ticket issued by Auth. Never returns notes, priority or the Steam ID.

Authentication

Core never issues tokens. It verifies Auth's EdDSA (Ed25519) JWTs with the public key only (JWT_PUBLIC_KEY) and reads userId and steamId from the claims. A token with a typ claim (for example a profile ticket) is rejected on normal endpoints; the profile ticket is accepted only by GET /api/public/profiles/library in the X-Profile-Ticket header.

API

Method Path Auth
GET /api/library/games, /api/library/games/{appid} JWT
PUT /api/library/games/{appid}/backlog JWT
POST /api/library/sync JWT
GET /api/library/sync-status, /summary, /activity, /wishlist, /steam-profile, /games-count JWT
GET /api/public/profiles/library profile ticket
GET /api/stats/public public

Tech stack

  • Java 25, Spring Boot 4.1 (Web MVC, Security, Data JPA, Validation, Cache with Caffeine), virtual threads
  • PostgreSQL 17, Flyway migrations
  • Resilience4j: retry and rate limiter for Steam, rate limiter for IGDB
  • JJWT with Ed25519 public key
  • Spring Boot Actuator + Micrometer (Prometheus)
  • Tests: JUnit 5, Testcontainers (PostgreSQL), ArchUnit
  • CI: Forgejo Actions, multi-stage Docker image

Architecture

A modular monolith. Each module under core_service.modules is a vertical slice that could move to its own service later:

Module Content
library Sync, backlog, playtime history, wishlist, public profile data
stats Public numbers for the landing page
steam_adapter Steam Web API client
igdb_adapter IGDB client (Twitch OAuth)

Inside a module: api (controllers, DTOs), service (business logic), domain (JPA entities) and repo (Spring Data repositories). ArchUnit enforces cycle freedom, controller-to-repository direction, naming and module isolation in src/test/java/core_service/architecture/ArchitectureTest.java.

Run locally

Needs Java 25 and Docker.

./mvnw spring-boot:run -Dspring-boot.run.profiles=dev

Spring Boot's Docker Compose support starts PostgreSQL from compose.yaml, Flyway applies the migrations, and the service listens on http://localhost:8090. Health: /actuator/health, metrics: /actuator/prometheus.

In the dev profile a request without an Authorization header gets a dummy user, so the API is usable without a running Auth service.

Configuration comes from environment variables:

Variable Purpose
JWT_PUBLIC_KEY Auth's Ed25519 public key, Base64 of the X.509 DER bytes
STEAM_API_KEY Steam Web API key
IGDB_CLIENT_ID, IGDB_CLIENT_SECRET Twitch app for IGDB (optional)
DB_PASSWORD Local PostgreSQL password

Tests

./mvnw clean verify

Runs unit, WebMvc, persistence and integration tests plus the ArchUnit rules. Needs Docker for Testcontainers.

Roadmap

  • "What to play next" picker: time budget and mood on top of the current random suggestion.
  • Achievement summary per game and library-wide, "closest to 100 %".
  • Sale alerts for wishlist games.
  • Move steam_adapter DTOs out of api, then turn on strict module independence in ArchUnit.
  • Fetch the public key from a JWKS endpoint in Auth instead of an environment variable.

License

All rights reserved. The source is public for reading only.

S
Description
No description provided
Readme
2.1 MiB
0 Stars 3 Watchers 0 Forks
Languages
Java 99.4%
PLpgSQL 0.5%