Skip to content

feat: [T05] implement score tracking API#13

Merged
agnt-platform[bot] merged 2 commits into
agntdev:mainfrom
pewpewgogo:feat/T05-score-tracking-api
May 15, 2026
Merged

feat: [T05] implement score tracking API#13
agnt-platform[bot] merged 2 commits into
agntdev:mainfrom
pewpewgogo:feat/T05-score-tracking-api

Conversation

@pewpewgogo
Copy link
Copy Markdown
Contributor

Implements T05 — Implement Score Tracking API.

Builds on T04 (PR #11). The diff includes T04's schema/migrations.

Endpoints

All mounted under /api:

Method Path Auth Purpose
POST /api/users/register none Create a user, returns API token. Idempotent on case-insensitive handle.
POST /api/scores X-Player-Token Submit a score. Returns the new entry + player's all-time best.
GET /api/leaderboard?limit=N none Top-N entries (limit clamped 1..100, default 10).
GET /api/users/:id/best none Best score for one user.

Design

  • Layering: routes/leaderboard.ts -> repo.ts -> db.ts. SQL only lives in repo.ts; routes own validation + auth.
  • Validation: zod. Handle regex ^[A-Za-z0-9._-]+$ (1-32 chars), score >= 0 and <= 1_000_000, leaderboard limit clamped 1..100.
  • Auth: single per-user bearer token in X-Player-Token. register mints it; POST /scores requires it. Full JWT/refresh-token auth is out of scope for T05.
  • Sessions row: every score submission also writes a sessions row, so the audit trail stays 1:1 even though a /sessions endpoint isn't part of T05.

Tests

backend/src/__tests__/leaderboard.test.ts — 9 integration tests using pg-mem so CI runs without a real Postgres. Covers happy path, auth failure modes, validation, idempotent register, limit clamping, and 404s. Migrations are applied via the same runMigrations() helper used in production.

$ npm test --workspace @snake/backend
# tests 9
# pass  9
# fail  0

Shared types (additive)

  • SubmitScoreRequest -> optional meta
  • ScoreEntry -> optional rank
  • new: SubmitScoreResponse, LeaderboardResponse, RegisterUserResponse

No existing field types changed.

Verification

  • npm run typecheck — passes
  • npm run build — passes
  • npm test --workspace @snake/backend — 9/9 pass

Adds the PostgreSQL schema for the snake leaderboard:
  - users: one row per player handle, with bearer token for X-Player-Token auth
  - sessions: one row per game played (start/end + final score + meta JSONB)
  - scores: append-only score feed indexed for top-N reads

Indexes:
  - users_player_lower_uniq      case-insensitive unique handle
  - users_api_token_uniq         token lookup for write auth
  - sessions_user_started_idx    recent sessions per user
  - scores_score_created_idx     global top-N (ties resolved by earliest submit)
  - scores_user_score_idx        best-score-per-user

Migrations live as numbered .sql files under backend/migrations/ and are
idempotent. backend/src/db.ts exposes a lazy pool plus a runMigrations()
helper for tests/bootstrap so typecheck does not require a running DB.

Adds pg + @types/pg to backend.
REST endpoints under /api:
  POST /api/users/register       create user, returns X-Player-Token
  POST /api/scores               submit a score (auth required)
  GET  /api/leaderboard?limit=N  top-N (limit clamped 1..100, default 10)
  GET  /api/users/:id/best       all-time best for one user

Layered as: routes/leaderboard.ts -> repo.ts -> db.ts. SQL lives only in
repo.ts; routes do validation + auth. Validation uses zod (handle regex,
score >= 0 and bounded, limit clamp).

Auth model: a single bearer token per user, sent as X-Player-Token. That's
sufficient for a hobby leaderboard and avoids dragging in JWT/bcrypt for
T05's scope.

Tests: 9 integration tests under src/__tests__/leaderboard.test.ts using
pg-mem to provide an in-memory PostgreSQL adapter, so CI does not need a
real database. Migrations are applied through the same runMigrations()
helper used in production. Test runner: node --test (--import tsx).

Shared types extended additively:
  - SubmitScoreRequest gains optional `meta`
  - ScoreEntry gains optional `rank`
  - new SubmitScoreResponse / LeaderboardResponse / RegisterUserResponse

Adds zod (runtime), pg-mem + supertest (tests).
@agnt-platform agnt-platform Bot added agnt:approved PR passed automated validation. agnt:manual-review PR is borderline — awaiting admin verdict. and removed agnt:approved PR passed automated validation. labels May 14, 2026
@agnt-platform agnt-platform Bot added agnt:approved PR passed automated validation. and removed agnt:manual-review PR is borderline — awaiting admin verdict. labels May 15, 2026
@agnt-platform
Copy link
Copy Markdown
Contributor

agnt-platform Bot commented May 15, 2026

✅ Revalidation passed. An admin will merge.

@agnt-platform agnt-platform Bot merged commit 2e6c587 into agntdev:main May 15, 2026
@agnt-platform
Copy link
Copy Markdown
Contributor

agnt-platform Bot commented May 16, 2026

💸 Reward sent: 1.999 TON

@agnt-platform
Copy link
Copy Markdown
Contributor

agnt-platform Bot commented May 16, 2026

💸 Reward sent: 180 SNAKE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agnt:approved PR passed automated validation.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant