Files
Rendezvous/docs/architecture/0007-caller-owned-dotnet-client-sdk.md
T
KyuubiYoru 06c3973ce7
quality-gate / quality (push) Successful in 1m6s
feat: add publisher and browser client SDK (#9)
Closes #9
2026-07-16 06:27:44 +02:00

54 lines
2.9 KiB
Markdown

# ADR 0007: caller-owned .NET publisher and browser SDK
- Status: Accepted
- Date: 2026-07-16
- Tracking: #9
## Decision
The .NET client package exposes separate publisher and browser interfaces plus
concrete clients over a caller-supplied `HttpClient`. The caller owns that client,
its handler, base address, connection pool, proxy, and lifetime. SDK operations
dispose every request, response, and response body they create, but never dispose
the supplied client. The package targets `netstandard2.1`, depends only on the
wire-contract package and LiteNetLib, and contains no Godot types, global client,
service URL, publisher secret, or embedded game credential.
Every operation returns `RendezvousClientResult<T>` with a stable error code,
message, and optional retry guidance. Cancellation remains exceptional through
the caller's `CancellationToken`; transport failures become `ServiceUnavailable`.
Response bodies are streamed under the contract's 256 KiB browser ceiling before
deserialization. Invalid or oversized success bodies become `InternalError` and
never escape as partially trusted contract objects.
The SDK retries only operations whose duplicate execution is safe: scoped reads,
idempotency-keyed registration, lease renewal with the same lease token, complete
resource update, and lease-token deregistration. It honors bounded server retry
guidance and otherwise uses capped exponential backoff with jitter. Each retry
creates a fresh HTTP request while preserving the caller's registration
idempotency key. Configuration is copied on construction so later option mutation
cannot change an in-flight client's behavior.
`PublishedSession` holds the server-issued lease and presence capabilities needed
by the host. Its string representation always redacts them. Update requests are
copied before the lease token is attached, so the SDK never mutates caller-owned
DTOs. The browser exposes one-page calls and bounded cursor traversal; cursor
values remain opaque and caller requests remain unchanged.
Lease maintenance is explicit. Creating a `SessionLeaseMaintainer` starts no task;
the game chooses when to call `RunAsync`, owns cancellation, and awaits
`DisposeAsync`. The loop uses the latest server-provided renewal interval and
returns a distinct cancelled, disposed, lost-lease, or failed result. Terminal
authorization, expiry, and missing-lease responses also raise `LeaseLost` so the
host can stop advertising or re-register deliberately.
## Consequences
- SpaceGame and Unscouted can inject the publisher/browser interfaces in tests
without an engine runtime or real network.
- Games must configure an absolute `HttpClient.BaseAddress` (or equivalent
handler routing), obtain publisher credentials from their deployment boundary,
and explicitly run and dispose lease maintenance.
- The versioned client public-API snapshot and live-server integration tests fail
together when SDK and HTTP contracts drift.