Files
rudder-csharp-sdk/CHANGELOG.md
T
edmand46 1029f08fba Docs: skills/README/CHANGELOG for effects client rewrite
- scenarios.md rewritten for server-side execution + effects API
- realtime.md deleted; realtime/planstore references purged from docs
- CHANGELOG Unreleased: major bump + migration table
2026-09-04 14:18:05 +03:00

8.3 KiB

Changelog

Unreleased

Breaking change — major bump. The local scenario engine is replaced by a server-driven effects client; the realtime websocket client is removed.

Removed

  • Local scenario runtime: PlanRun, ExecutionPlan walking, node sessions (NotificationSession, StoreOfferSession, LeaderboardSession, WaitSession, QuestSession, BattlePassSession, BattlePassLevelSession, ConfigChangedSession), RespondAsync / Respond, RestoreAsync, Clear, ActiveRuns, IsRunning, CurrentNodeId, OnConfigChanged.
  • RudderClientOptions.PlanStateStore / IPlanStateStore and IPlanScheduler — no local plan persistence or delayed plan work.
  • RealtimeService (client.Realtime), RudderClientOptions.RealtimeUrl / RealtimeTransportFactory, IRealtimeTransport / IRealtimeTransportFactory.

Changed (breaking)

  • client.Scenario is a trigger only: TriggerAsync(eventName) returns Task (not started plans). Returned pending effects are ingested into client.Effects.
  • Subscribe to client.Effects.On* instead of client.Scenario.On*. Sessions are now effect objects (NotificationEffect, StoreOfferEffect, …). Complete them with the methods on the effect (DoneAsync, PurchaseAsync/DeclineAsync, EndAsync/ClaimAsync, …).
  • client.Update(deltaTime) is still required every frame — it now pumps the effects client (30s GET /sdk/v1/scenarios/pending heartbeat + wait-deadline checks), not a local DAG or a websocket.
  • After login (or when constructed with a stored access token), the next Update fetches pending effects. There is no loginEvent option; trigger login-gated scenarios yourself.

Migration

Before After
client.Scenario.OnNotification (and other On*) client.Effects.OnNotification (same event names)
NotificationSession / StoreOfferSession / … NotificationEffect / StoreOfferEffect / …
session.CompleteAsync() / RespondAsync("output") effect.DoneAsync() (and the matching method on each effect)
RudderClientOptions.PlanStateStore + RestoreAsync gone — server owns run state; pending fetch after login + heartbeat
client.Realtime gone
client.Update(deltaTime) still required (effects pump)

0.4.0

  • Generated DTOs live under Models/ (RudderSdk.Core.Models). Wire fields are nullable. ListQuestsRequest is gone; Quests.ListAsync POSTs with no body. BoundaryNode.WaitDeadline is DateTimeOffset?.
  • LeaderboardSession.ClaimAsync / Claim complete the leaderboard node with handle onClaim. The server matches live rank to an authored place.
  • RewardClaimedAsync / RewardClaimed are obsolete aliases and will be removed in the next SDK version.
  • rank_not_eligible on Claim leaves the session open (retry Claim or End); it no longer fails the run.

0.3.0

Removed

  • UGC surface: UgcService (client.Ugc), the generated RudderSdk.Core.Models.Ugc DTOs, IUploadTransport and RudderClientOptions.UploadTransport. The server no longer exposes the UGC endpoints.

Changed (breaking)

  • BattlePassService simple overloads sent empty scenario/node ids and always failed server-side. Battle pass state is tied to a scenario battle pass node, so the public API now mirrors the web SDK: GetProgressAsync(scenarioId, nodeId) and the request-DTO overloads AddXpAsync, ClaimRewardAsync, PurchasePremiumAsync (carrying ScenarioId/NodeId/RunId) are public; the internal request overloads are gone.
  • BattlePassSession now exposes the bound battle pass operations (GetProgressAsync, AddXpAsync(source, amount), ClaimRewardAsync(level, track), PurchasePremiumAsync() — crosses onPremiumPurchase on success), mirroring the web SDK session.
  • BattlePassLevelSession.CompleteAsync/Complete renamed to ClaimAsync/Claim; new Level property reads the levelNumber node data key.
  • Unsupported scenario node types now fail the run (OnScenarioFailed) instead of stalling silently.
  • Scenario counter updates no longer read a continuation plan from the response (the server stopped returning one); when the server reports the objective completed, the node crosses onComplete.

Fixed

  • A failed scenario counter update no longer fails the run; the error is logged and the node stays active.

0.2.0

Added

  • QuestsService (client.Quests) with ListAsync / ClaimAsync.
  • AuthService.LoginWithDeviceAsync(region, language, nickname?) and AuthService.RefreshAsync(); AuthStateChanged event (RudderAuthState.SignedIn / SignedOut).
  • Session pipeline: single-flight token refresh plus one transparent retry-on-401 for every API call; failed refresh clears tokens and reports SignedOut.
  • HttpClientTransport — default System.Net.Http.HttpClient-based transport. RudderClientOptions.Transport is now optional, as are TokenStore (InMemoryTokenStore) and DeviceIdProvider (GuidDeviceIdProvider).
  • Typed exceptions: RudderAuthException (401), RudderNotFoundException (404), RudderRateLimitException (429), RudderNetworkException (network/timeout). All carry RequestId from the server error payload.
  • StorageService.ListAllAsync and UgcService.ListAllAsync (IAsyncEnumerable<T> cursor pagination helpers).
  • RudderLogLevel enum; IRudderLogger.Log now takes a level.
  • Package metadata (Rudder.Core, MIT) and XML documentation.

Changed (breaking)

  • Generated models moved to domain folders/namespaces (RudderSdk.Core.Models.<Domain>); the flat RudderSdk.Core.DTO namespace is gone. Battlepass*BattlePass*, SdkQuestQuest.
  • BattlepassServiceBattlePassService, client.Battlepassclient.BattlePass.
  • client.Scenariosclient.Scenario.
  • ScenarioService.SendAsyncTriggerAsync, now returning the started PlanRuns.
  • Scenario events reduced to the canonical set: OnNotification, OnStoreOffer, OnLeaderboard, OnConfigChanged, OnWait, OnQuest, OnBattlePass, OnBattlePassLevel, OnScenarioCompleted, OnScenarioFailed. Legacy events (OnShowNotification, OnShowStore, OnQuestEvent, OnBattlepassEvent, OnLeaderboardEvent, OnNodeEvent, OnNode, OnCompleted, OnStore, OnRemoteConfigOverride, OnRunCompleted, OnRunFailed) are removed, along with the Services/Scenarios/Legacy folder.
  • Session types renamed: StoreSessionStoreOfferSession (BuyAsync/BuyPurchaseAsync/Purchase), RemoteConfigOverrideSessionConfigChangedSession, BattlepassSessionBattlePassSession, BattlepassLevelSessionBattlePassLevelSession, ScenarioRunFailedEventScenarioFailedEvent.
  • StoresService.BuyAsyncPurchaseAsync(storeSlug, offerId, idempotencyKey = null); a null key is replaced with a generated GUID.
  • InventoryService.GetAsync returns IReadOnlyList<PlayerInventoryItem>.
  • StoresService.ListAsync returns IReadOnlyList<Store>.
  • QuestsService.ListAsync returns IReadOnlyList<Quest>.
  • UgcService.GetDownloadUrlAsync returns non-null string and throws InvalidOperationException when the server returns no URL.
  • BattlePassService simple overloads (AddXpAsync(long amount), ClaimRewardAsync(level, track), GetProgressAsync(), PurchasePremiumAsync(idempotencyKey?)); the request-DTO overloads are internal for the scenario runtime.
  • LeaderboardsService.GetRankingAsync/SubmitScoreAsync are internal; use the FindBySlug(slug) handle (SubmitAsync, ListAsync).
  • AuthService.LoginViaDeviceAsync removed; use LoginWithDeviceAsync.
  • ScenarioService.Restore() (sync-over-async) removed; use RestoreAsync.
  • RealtimeService.ConnectAsync and IRealtimeTransport.ConnectAsync take TimeSpan timeouts instead of int timeoutSeconds.
  • IRudderTransport.SendAsync takes a string? accessToken instead of RequestOptions; RequestOptions is removed and EmptyResponse is internal.
  • RudderClient getters Options, Transport, TokenStore, DeviceIdProvider are internal.
  • RudderApiException.StatusCode is int (was long).
  • IRudderLogger.Log(string)Log(RudderLogLevel level, string message).
  • Nullable reference types enabled (<Nullable>enable</Nullable>).
  • Remote config cache now includes every config except an explicit "active": false (a missing flag means active).