feat: Phase 4 — dev experience complete
CI / Build, lint & test (push) Successful in 2m21s

Docs:
- .env.example: documents all environment variables with defaults
- CONTRIBUTING.md: dev setup, running tests, code style, design constraints
- MODDING.md: full schema reference for cards, packs, objectives, and SBCs
- .gitea/workflows/ci.yml: Gitea Actions CI (fmt check, clippy, build, test)

Middleware (#50-52):
- Body limit (256 KB) via DefaultBodyLimit on all routes (#50)
- Concurrency limit (256 concurrent requests) via semaphore middleware;
  returns 429 Too Many Requests when at capacity (#51)
- Correlation IDs via tower_http request_id layers; sets x-request-id
  UUID on every request and propagates it to the response headers (#52)

Layer order (outermost → innermost):
  CorsLayer → DefaultBodyLimit → concurrency limit → SetRequestId
  → TraceLayer → PropagateRequestId → routes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-25 15:53:28 -07:00
parent 4ae1081aa9
commit f6dd41fd41
9 changed files with 384 additions and 2 deletions
+93
View File
@@ -0,0 +1,93 @@
# Contributing to OpenFUT Core
## Prerequisites
- **Rust** (stable, 1.80+) — install via [rustup](https://rustup.rs)
- **SQLite 3** — usually pre-installed on Linux/macOS
Recommended tools:
```bash
rustup component add clippy rustfmt
```
## Setup
```bash
git clone <repo-url>
cd openfut-core
cp .env.example .env
cargo build
```
## Running locally
```bash
cargo run
```
The server starts at `http://127.0.0.1:8080` by default. Logs appear in the
terminal. On first run, the SQLite database is created and all migrations are
applied automatically.
## Running tests
```bash
cargo test
```
Tests spin up a full in-process server against an in-memory SQLite database —
no setup required and nothing is written to disk.
## Code style
All PRs must pass before merge:
```bash
cargo fmt --check # formatting
cargo clippy -- -D warnings # lints
cargo test # full test suite
```
Auto-fix formatting with `cargo fmt`.
## Adding card / pack / objective data
See [MODDING.md](MODDING.md) for the data file schemas. No Rust code changes
are needed to add new cards, packs, objectives, or SBC definitions.
## Project layout
```
src/
app.rs router + middleware setup
config.rs Config struct (reads from env)
db.rs SQLite pool init + migrations
error.rs AppError enum
middleware.rs concurrency limit, request ID
models/ Serde structs for DB rows and API payloads
routes/ Axum handler functions (one file per domain)
services/ Business logic (no HTTP types here)
seed/ One-time startup seeds
modding/ JSON data loader utilities
data/
cards/ CardDefinition JSON arrays
packs/ PackDefinition JSON arrays
objectives/ ObjectiveDefinition JSON arrays
sbcs/ SbcDefinition JSON arrays
migrations/ SQLite migration SQL files
```
## Branching & pull requests
- Create a branch from `main`: `git checkout -b feat/my-feature`
- Keep PRs focused — one feature or fix per PR
- PR description should explain *why*, not just *what*
## Design constraints
- **No online multiplayer.** This is an offline local backend only.
- **No copyrighted assets.** All card data in `data/` must be original.
- **No real EA services.** Do not hardcode or reverse-engineer EA endpoints.
- **Game-independent core.** `openfut-core` must stay game-agnostic;
FIFA-specific logic belongs in `openfut-bridge`.