Ajoute l'endpoint api/share_api.dart, les use cases de partage (application/share_use_cases.dart) et l'adapter Postgres (infrastructure/postgres/share_repository.dart). L'acceptation d'un partage crée une nouvelle ressource synced_resources avec de nouveaux IDs pour le destinataire, sans jamais modifier la ressource source de l'émetteur ; gestion des conflits révoqué/déjà répondu. dart pub get OK, dart analyze clean, dart test 24/24 vert. Use case d'acceptation 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>
4.0 KiB
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:
dart pub get
Run the server:
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.
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 to5432when omitted.DATABASE_NAME: database name.DATABASE_USER: database user.DATABASE_PASSWORD: database password.
Apply migrations from server/:
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:
TEST_DATABASE_URL=postgres://gametime:gametime@localhost:5432/gametime dart test
Healthcheck:
curl http://localhost:8080/health
Expected response:
{"status":"ok"}
Authentication
Ticket #48 adds account registration, login, logout and bearer-token request authentication.
Endpoints:
POST /auth/registerwith{ "email": "...", "password": "...", "displayName": "..." }.POST /auth/loginwith{ "email": "...", "password": "...", "deviceLabel": "..." }.POST /auth/logoutwithAuthorization: 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/pushwithAuthorization: Bearer <token>.GET /sync/pull?since=<serverCursor>withAuthorization: Bearer <token>.POST /sync/exchangewithAuthorization: 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.
Sharing
Ticket #51 adds authenticated targeted sharing for programs and workout templates.
Endpoints:
POST /shareswithAuthorization: Bearer <token>.GET /shares/inboxwithAuthorization: Bearer <token>.POST /shares/{id}/acceptwithAuthorization: Bearer <token>.POST /shares/{id}/declinewithAuthorization: Bearer <token>.POST /shares/{id}/revokewithAuthorization: Bearer <token>.
Creating a share stores a snapshot payload and creates pending recipient rows
for known recipient emails. Unknown emails are reported as unresolvedEmails
without failing the whole request. Accepting a share creates a new
synced_resources copy owned by the recipient with a server-generated
clientId; the sender's original resource is never modified. Accept returns
409 for revoked or already answered shares, while missing shares or recipients
return 404.
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. Ticket #51 adds targeted sharing.
Upcoming tickets will fill the empty adapters and use cases:
- #52: Docker and registry packaging.
- #53: API, contract and integration tests.