# When a deprecated surface stops working

A handful of the surfaces in this SDK are marked **deprecated**. The mark tells you there is
something better to call. It does not tell you how long the old one has, and that is the
question you actually need answered before you can decide what to do about it. This page is
the answer, and it is the only place in this documentation that gives it.

Read it when something your game calls is marked deprecated and you are choosing between
migrating now and folding the migration into your next major upgrade. If nothing you call is
marked, you do not need this page.

- [1. What this covers](#1-what-this-covers)
- [2. The rule for the package's API surface](#2-the-rule-for-the-packages-api-surface)
- [3. Runtime-delivered pushes are a separate question](#3-runtime-delivered-pushes-are-a-separate-question)
- [4. What is deprecated today](#4-what-is-deprecated-today)
- [5. What this is not](#5-what-this-is-not)

---

## 1. What this covers

This policy governs the **API surface of `@indiegems/gem-web-sdk`**: the exports, methods,
fields and options your game compiles against. A deprecation on one of those is a statement
about package releases, and section 2 is the statement.

**A deprecated surface still works.** The mark removes nothing and changes no behaviour. It is
a notice period, and the point of a notice period is that you get to spend it rather than
react to it.

Four of the surfaces in section 4 are only half a package question, because the value behind
them is pushed to your server bundle by the platform rather than returned by a call you make.
Section 3 is that other half. And three separate things on this platform carry a version;
section 5 says which of them this is.

## 2. The rule for the package's API surface

**A surface deprecated in a `3.x` release keeps working for every remaining `3.x` release, and
`4.0.0` is the earliest release that may remove it.**

*Earliest release that may* is the whole of the strength, and it is worth reading twice. It is
a floor: it names the soonest a removal could reach you, which is the number a migration plan
needs. It is not a schedule. It does not say the surface is removed in `4.0.0`, and it does
not put a date on `4.0.0`.

What the floor buys you is that the removal lands on an upgrade you already control. No minor
and no patch release inside `3.x` takes a deprecated surface away, so a dependency range that
stays inside `3.x` cannot lose one underneath you — not on an install, not on a lockfile
refresh, not on a transitive bump. The next time you have to think about any of this is the
next time you deliberately change a major version.

This is what package-level semver already costs here rather than a new promise:
[`server-bundles.md`](server-bundles.md) records the whole package going to `3.0.0` for a
single removed export, because that is the price of taking a surface away.

**So migrate at the major, not at the mark.** A deprecation is worth a note in your backlog
the day you read it; it is worth your afternoon only when you are already planning the major
upgrade it lands on.

## 3. Runtime-delivered pushes are a separate question

Four of the deprecated surfaces are not values this package produces. `roomArgs` and `roster`
on the server host — and the same two on the match-server wrapper around it — are **pushed into
your bundle by the dedicated-server runtime image your bundle runs on**. That splits the
question in two, and the halves are decided in different places.

- **The member is package surface, and section 2 governs it unchanged.** The property keeps
  compiling for the rest of `3.x`, and `4.0.0` is the earliest release that may take it off
  the type.
- **Whether a value still arrives is the runtime's decision, and no date has been set for it.**
  This package does not build the runtime image and cannot say when a server stops sending one
  of these. That is decided where the image is built. Nothing here names a version for it,
  because a version this package cannot honour would be worse than the silence it replaces.

**So treat delivery as something your code checks, not something you can read off a version.**
That is the advice [`server-bundles.md`](server-bundles.md) already gives and none of it
changes: read the room when it is there, and keep the deprecated push as the fallback for a
server running an older image. [Room args](server-bundles.md#room-args) has the shape of both
and the check that chooses between them.

## 4. What is deprecated today

Every deprecated surface this documentation publishes, with what to call instead. A notice you
meet in the reference or in a guide points here; if a surface is not in this table, it is not
deprecated.

| Surface | Replacement | Earliest release that may remove it | Governing rule |
| ------- | ----------- | ----------------------------------- | -------------- |
| `Gem.client` | The named surfaces — `Gem.rooms`, `Gem.me`, `Gem.characters` and the rest | `4.0.0` | Package API surface |
| `ClientVersion.platform` | None; drop the field, the SDK reports it | `4.0.0` | Package API surface |
| `CreateRoomOptions.maxPlayers` | The room template's seats | `4.0.0` | Package API surface |
| `GemServerHost.roomArgs` | `gem.room?.args()` | `4.0.0`, for the member | Package API surface, plus runtime delivery |
| `GemServerHost.roster` | `gem.room?.get()` | `4.0.0`, for the member | Package API surface, plus runtime delivery |
| `GemMatchServer.roomArgs` | `gem.room?.args()` | `4.0.0`, for the member | Package API surface, plus runtime delivery |
| `GemMatchServer.roster` | `gem.room?.get()` | `4.0.0`, for the member | Package API surface, plus runtime delivery |
| `profile(playerId)` | The room read's per-member display identity | Not a package release | Runtime delivery only |

**"For the member" is the split from section 3**, and it is the row's real answer: `4.0.0` is
the earliest release that may take the property off the type, and it says nothing about when a
server stops putting a value in it.

The last row is the one that is only a guide's. `profile(playerId)` is marked deprecated in
[`server-bundles.md`](server-bundles.md) and carries no mark in the generated reference, so
there is no package release to name for it and section 3 is its whole rule.

## 5. What this is not

Three separate things on this platform carry a version. This policy is about one of them, and
mistaking it for either of the others produces a plan for a rule that does not exist.

- **Not the bridge protocol version.** The handshake between the arcade page and your game
  negotiates its own version, and `README.md` § "Version negotiation" is the rule that governs
  it. Different axis, different trigger, and nothing on this page restates or amends it.
- **Not your game's compatibility line.** Which builds of *your* game can meet in a room is
  derived from your `gameVersion`, and
  [the compatibility line](platform-rules.md#4-the-compatibility-line) is the rule for that.
- **Not a removal schedule.** This page names the earliest release that may remove a surface,
  which is a floor and not a plan. A surface may outlive the release named beside it.
