CNA-GAP-073: Offline leaderboards keep no Stream columns, and a column changed without a rating change is not saved offline

CNA snapshot b0e97bb1  ·  Known Issues › Functional gaps  ·  source links pinned to b0e97bb1

✓

Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit b0e97bb1; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.

Without a gamer-services endpoint, LeaderboardWriter saves an entry only when its rating changes and the local store drops Stream columns, so a column edited alone, or any Stream column, does not survive the session offline.

Identifier
CNA-GAP-073
Category
Functional gap
Subsystem
Networking & gamer services
Status
Open
Verified against
CNA b0e97bb1 (b0e97bb1bb876f9b3edd6f4ff1ef3067908ae8ac)
Evidence basis
Source-verified: read at TARGET, not executed
Tests touching this area
Yes: see Current tests
Affected contract
LeaderboardWriter and LeaderboardEntry columns (PropertyDictionary) for gamers without a service account (offline local profiles)

Expected behaviour

XNA 4.0's leaderboard PropertyDictionary supports Stream columns (GetValueStream), and a column written during gameplay is part of the entry as much as its rating. CNA's own service path keeps Stream columns (up to 256 bytes) and collects every changed column for the session's EndGame write.

Actual behaviour at TARGET

For a writer without a service account, LeaderboardWriter.cpp installs only a rating-changed hook (SetOnRatingChangedHookEXT) that saves the entry, with its columns, through SaveLeaderboardEntryEXT; changing a column without changing the rating saves nothing. Stream creation is enabled only for service entries (BindServiceEntry), and ColumnsToJson in LocalGamerServicesStore.cpp writes int32, int64, double, single, string, DateTime, TimeSpan and outcome values and skips any other type, so the offline store keeps no Stream column. CNA records both as its own findings: GS-AUDIT-006 in gamer-services-issues.md and section 22 of gamer-services-known-limitations.md ("offline local boards (no service) do not keep Stream columns").

Source locations

Evidence

Read at b0e97bb1; nothing was built or executed. CNA's audit rates GS-AUDIT-006 as strong evidence and made no implementation change.

Focused reproduction

No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.

Current tests

GamerServicesGamerTests.cpp round-trips offline column types through the store (OfflineIntegerBoundariesRoundTripExactly); no test changes a column alone through LeaderboardWriter offline, and none writes a Stream column offline.

Regression test

Offline, change a column without changing the rating, reload the store and expect the column; write a Stream column offline and expect it back, or a documented refusal.

Blast radius

Games that keep per-player statistics in leaderboard columns on machines without a gamer-services endpoint, or store replay or ghost data in Stream columns there. Service accounts are unaffected.

Workaround

Change the rating together with the columns (for example rewrite it with the same value) so the offline hook saves the entry, and keep Stream data in the game's own storage.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.