Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

combat_ledger

A player account and leaderboard backend for an Unreal Engine 5 hack-and-slash prototype. The UE 5.8 client submits combo runs over HTTPS to a FastAPI service on AWS ECS Fargate, backed by PostgreSQL on RDS. Everything is provisioned with Terraform and deployed through OIDC-federated GitHub Actions.

Status: In progress — see Roadmap.

Demo


Why this exists

Real-time gameplay never touches a database, but almost everything around it does: accounts, progression, leaderboards, telemetry. This project builds that "around it" layer the way a live-service studio would, scoped down to one feature so every piece can be done properly instead of half-done.

The game side is a Narrative Pro / Gameplay Ability System melee prototype I'm building separately. The max_combo field in the schema comes straight from the GAS combo-counter attribute, so the leaderboard reflects real gameplay data rather than mock values.


Architecture

flowchart LR
    subgraph Client
        UE[UE 5.8 Client<br/>HTTP + Json modules]
    end

    subgraph AWS["AWS (us-east-1)"]
        ALB[Application Load Balancer<br/>HTTPS / ACM]
        subgraph VPC
            subgraph Private Subnets
                ECS[ECS Fargate<br/>FastAPI]
                RDS[(RDS PostgreSQL 16)]
            end
        end
        SM[Secrets Manager]
        ECR[ECR]
        CW[CloudWatch Logs + Alarms]
    end

    subgraph CI["GitHub Actions (OIDC)"]
        CI1[ci.yml<br/>lint · test · build]
        CI2[deploy.yml<br/>push ECR · migrate · roll ECS]
        CI3[infra.yml<br/>terraform plan / apply]
    end

    UE -->|POST /runs<br/>GET /leaderboard| ALB --> ECS --> RDS
    ECS -.pulls secrets.-> SM
    ECS -.logs.-> CW
    CI2 --> ECR --> ECS
    CI3 --> AWS
Loading

Request flow: the client logs in and receives a short-lived JWT. At the end of a run it POSTs score, max_combo, and duration_ms. The leaderboard is a Postgres view returning each player's best run, read by the main-menu widget.


Stack

Layer Choice Why
Game client Unreal Engine 5.8, C++ UGameInstanceSubsystem Native HTTP/Json modules, no third-party REST plugin
API Python 3.12, FastAPI, SQLAlchemy 2, asyncpg Async, typed, fast to test
Database PostgreSQL 16 on RDS (db.t4g.micro) Industry default for game backends
Auth JWT (HS256), bcrypt password hashing Simple and sufficient for scope
Compute ECS Fargate No cluster to manage; complements the EKS work in WellWatch
Infra Terraform, S3 + DynamoDB remote state Reusable modules, plan-on-PR
CI/CD GitHub Actions with OIDC (no long-lived AWS keys) Same federation pattern as WellWatch
Observability CloudWatch Logs Insights, CPU / 5xx / DB-connection alarms Structured JSON logs from the API
Security scanning checkov in CI Catches IaC misconfigurations before apply

Repository layout

combat_ledger/
├── api/          FastAPI service, tests, Dockerfile
├── db/           Numbered SQL migrations
├── infra/        Terraform — envs/dev, reusable modules/
├── unreal/       C++ subsystem, USTRUCTs, widget screenshots
├── docs/         Diagram source, demo GIF
└── .github/      ci.yml · deploy.yml · infra.yml

Running locally

Requires Docker and Docker Compose.

git clone https://github.com/huicodes/combat_ledger
cd combat_ledger
docker compose up --build

This starts Postgres 16, runs migrations, and serves the API at http://localhost:8080. Interactive docs at http://localhost:8080/docs.

Quick smoke test:

curl -X POST localhost:8080/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"henry","password":"hunter2"}'

Point the Unreal client at localhost:8080 via Project Settings → Combat Ledger → Base URL.


API

Method Path Auth Description
POST /auth/register Create account, returns JWT
POST /auth/login Returns JWT
POST /runs Bearer Submit a completed run
GET /leaderboard?limit=50 Best run per player, ranked by score
GET /players/me Bearer Current player profile
GET /healthz ALB health check

Deploying

  1. Bootstrap remote state (infra/bootstrap/) — one time.
  2. Open a PR touching infra/**; infra.yml posts the Terraform plan as a comment.
  3. Merge → apply runs behind a manual environment approval.
  4. Push to maindeploy.yml builds the image, pushes to ECR tagged with the commit SHA, runs migrations as a one-off ECS task, and forces a new service deployment.

Cost

Roughly $20–40 / month while up (Fargate 0.25 vCPU task + db.t4g.micro + ALB, no NAT gateway — VPC endpoints for ECR, Secrets Manager, and CloudWatch instead). terraform destroy when not demoing.


Known limitations

  • Client-authoritative scoring. The client reports its own score. A production game validates runs on a dedicated server — see roadmap.
  • Single region, single environment. No blue/green, no multi-AZ RDS.
  • HS256 JWTs with a shared secret. Fine here; a real deployment would use RS256 or a managed identity provider (Cognito).

Roadmap

  • Schema and migrations
  • FastAPI service with tests and Docker Compose
  • Terraform: VPC, RDS, ECS Fargate, ALB, Secrets Manager
  • CI/CD workflows with OIDC
  • Unreal HTTP subsystem and leaderboard widget
  • Observability and checkov hardening
  • Demo GIF and cost numbers
  • Stretch: Linux dedicated server on GameLift Anywhere with server-authoritative scoring
  • Stretch: Redis-backed leaderboard cache

Related projects

  • WellWatch — multi-cloud IaC (AWS + Azure, EKS, Ansible)
  • TradeWatch — production support and trade analytics pipeline

About

A Postgres-backed account/leaderboard API on AWS

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors