# GameTime Server Integration Checklist

This checklist covers the checks that require a real Docker daemon, PostgreSQL
instance, or Gitea registry. They are intentionally not part of the sandbox test
suite.

## Docker Compose

- Copy `server/.env.example` to `server/.env`.
- Replace `POSTGRES_PASSWORD` and `DATABASE_PASSWORD` with a real secret.
- Set `API_BIND_ADDRESS` to the Docker host interface reachable by the external
  reverse proxy.
- Set `API_PORT` to the host port consumed by the reverse proxy.
- Run:

```bash
cd server
docker compose config
docker compose up -d --build
docker compose ps
docker compose logs api
```

- Verify that the `api` service waits for the PostgreSQL healthcheck.
- Verify that migrations run automatically before the server starts.
- Verify that TLS is terminated by the external reverse proxy, not by the API
  container.

## PostgreSQL Migrations

- Start a disposable PostgreSQL database or reuse the Compose database.
- Run the real migration integration test:

```bash
cd server
TEST_DATABASE_URL=postgres://gametime:change-me@localhost:5432/gametime dart test
```

- Confirm the test sees these tables:
  - `users`
  - `auth_sessions`
  - `synced_resources`
  - `shares`
  - `share_recipients`

## Manual API Smoke Tests

Run the following checks against the real server URL. Use HTTP directly only on
the private LAN path between the reverse proxy and Docker host; external access
should be HTTPS through the reverse proxy.

```bash
curl http://localhost:8080/health
```

- Register a user with `POST /auth/register`.
- Login with `POST /auth/login` and store the returned bearer token.
- Call a protected endpoint without a token and confirm `401`.
- Logout with `POST /auth/logout` and confirm the token can no longer access
  protected endpoints.
- Push a valid resource with `POST /sync/push`.
- Pull it with `GET /sync/pull`.
- Push an older version of the same resource and confirm `ignoredOlder`.
- Use `POST /sync/exchange` and confirm push results and pulled items are both
  present.
- Create a second user, then create a share with `POST /shares`.
- Confirm unknown recipient emails are returned in `unresolvedEmails`.
- List shares with `GET /shares/inbox` as the recipient.
- Accept a share with `POST /shares/{id}/accept` and confirm a copied resource
  appears in `GET /sync/pull` for the recipient.
- Decline a pending share with `POST /shares/{id}/decline`.
- Revoke a sent share with `POST /shares/{id}/revoke`.
- Confirm accepting a revoked or already answered share returns `409`.

## LWW Concurrency

- Run two concurrent `POST /sync/push` requests for the same
  `(owner_user_id, resource_type, client_id)` with different `clientUpdatedAt`
  values.
- Confirm the row with the strictly newer `clientUpdatedAt` wins.
- Confirm an equal timestamp is ignored by the later request.
- Inspect `server_updated_at` to confirm the update trigger advances it on
  accepted updates.

## Gitea Container Registry

- Obtain the real Gitea registry host, owner/namespace, username and token.
- Run:

```bash
cd server
GITEA_REGISTRY=gitea.example.com \
GITEA_OWNER=my-org \
GITEA_IMAGE_NAME=gametime-server \
GITEA_IMAGE_TAG=latest \
GITEA_USERNAME=my-user \
GITEA_TOKEN='replace-with-token' \
./scripts/push-gitea-image.sh
```

- Confirm the image exists in the Gitea Container Registry.
- Pull the pushed image on the deployment host.
- Deploy the pushed image with the same environment variables as the local
  Compose build.
