Files
GameTime/server/README.md
Blomios 60912ebde4 feat(server): API de synchronisation incrémentale LWW (ticket #50)
Ajoute l'endpoint api/sync_api.dart, les use cases de synchronisation
(application/sync_use_cases.dart) et l'adapter Postgres
(infrastructure/postgres/synced_resource_repository.dart) implémentant
un upsert LWW atomique via CTE (INSERT ... ON CONFLICT ... WHERE
client_updated_at < EXCLUDED.client_updated_at, avec fallback UNION
ALL pour le cas ignoré). dart pub get OK, dart analyze clean, dart
test 15/15 vert. SQL d'upsert relu manuellement et jugé correct ; pas
de test de bout en bout contre un vrai PostgreSQL faute d'accès
Docker dans ce sandbox.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 10:23:36 +02:00

122 lines
3.3 KiB
Markdown

# GameTime server
Headless Dart server for future GameTime account, sync and sharing features.
This package is separate from the Flutter app at the repository root.
## Local run
Install dependencies from this directory:
```bash
dart pub get
```
Run the server:
```bash
dart run bin/server.dart
```
The HTTP server binds to `0.0.0.0` and reads `PORT` from the environment.
When `PORT` is not set, it listens on `8080`.
```bash
PORT=9090 dart run bin/server.dart
```
## PostgreSQL
Ticket #49 adds the initial sync-ready PostgreSQL schema and a minimal
connection/migration utility.
Database environment variables:
- `DATABASE_HOST`: PostgreSQL host.
- `DATABASE_PORT`: PostgreSQL port, defaults to `5432` when omitted.
- `DATABASE_NAME`: database name.
- `DATABASE_USER`: database user.
- `DATABASE_PASSWORD`: database password.
Apply migrations from `server/`:
```bash
DATABASE_HOST=localhost \
DATABASE_PORT=5432 \
DATABASE_NAME=gametime \
DATABASE_USER=gametime \
DATABASE_PASSWORD=gametime \
dart run bin/migrate.dart
```
Migrations are read from `server/migrations/` in alphabetical order. The v1
runner is intentionally simple; SQL files use idempotent DDL where practical.
The PostgreSQL integration test is skipped unless `TEST_DATABASE_URL` is set:
```bash
TEST_DATABASE_URL=postgres://gametime:gametime@localhost:5432/gametime dart test
```
Healthcheck:
```bash
curl http://localhost:8080/health
```
Expected response:
```json
{"status":"ok"}
```
## Authentication
Ticket #48 adds account registration, login, logout and bearer-token request
authentication.
Endpoints:
- `POST /auth/register` with `{ "email": "...", "password": "...", "displayName": "..." }`.
- `POST /auth/login` with `{ "email": "...", "password": "...", "deviceLabel": "..." }`.
- `POST /auth/logout` with `Authorization: Bearer <token>`.
Passwords are stored with PBKDF2-HMAC-SHA256 via `package:cryptography`, using a
per-password random salt. API tokens are opaque random values; only a SHA-256
hash of the token is stored in PostgreSQL.
## Sync
Ticket #50 adds authenticated incremental sync endpoints using simple
last-write-wins conflict resolution based on `clientUpdatedAt`.
Endpoints:
- `POST /sync/push` with `Authorization: Bearer <token>`.
- `GET /sync/pull?since=<serverCursor>` with `Authorization: Bearer <token>`.
- `POST /sync/exchange` with `Authorization: Bearer <token>`.
`serverCursor` is an ISO8601 UTC timestamp. For push, it is the greatest
`server_updated_at` currently known for the authenticated user after applying
the batch. For pull, it is the greatest `serverUpdatedAt` returned, or the
server clock if no resource is returned.
`POST /sync/exchange` applies push first, then returns the pull payload with
`pushResults` included so per-item validation errors remain visible to the
client.
## Scope
Ticket #47 only scaffolds the Dart server, the hexagonal directory layout and
the `/health` endpoint. Ticket #49 adds the first PostgreSQL schema. Ticket #48
adds authentication. Ticket #50 adds sync only; sharing behavior is still
implemented in a later ticket.
Upcoming tickets will fill the empty adapters and use cases:
- #48: user authentication and API tokens.
- #49: PostgreSQL schema and repositories.
- #50: incremental sync API.
- #51: targeted sharing.
- #52: Docker and registry packaging.
- #53: API, contract and integration tests.