Skip to content

[2.0] Split the SDK into Ably.PubSub.Core and Device/Server door packages - #1340

Open
sacOO7 wants to merge 46 commits into
mainfrom
integration/v2
Open

sacOO7 wants to merge 46 commits into
mainfrom
integration/v2

Conversation

@sacOO7

@sacOO7 sacOO7 commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Status: DRAFT — do not merge. This PR exists so the 2.0 line is visible and reviewable against main.
It merges only when every item in the "Do not merge until" checklist below is ticked, on the release
owner's explicit go. It must be squash-merged (see "Merge mechanics").

What this PR is

This merges the completed 2.0 "SDK split" line — the integration/v2 branch — into main. It implements
the PubSub SDK split (PDR-091b) for .NET: the single ably.io package is split into an internal core plus
two "door" packages, so that every client is classified as device-side or server-side on the wire,
which Ably's platform behaviour and MAU-based billing depend on.

The new package landscape

Package Audience What it is
Ably.PubSub.Core Internal / transitive only The full SDK engine (the former ably.io codebase, IO.Ably namespace). Not intended for direct installation; its plain AblyRealtime/AblyRest constructors are [Obsolete] and produce unclassified clients.
Ably.PubSub.Device Device-side apps (MAUI, Unity, WPF/WinForms, mobile) Door package. Construct via PubSubDevice.CreateClient(...) — stamps the versionless ably-pubsub-device agent flag.
Ably.PubSub.Server Server-side apps (ASP.NET, workers, functions) Door package. Construct via PubSubServer.CreateRealtimeClient(...) / PubSubServer.CreateHttpClient(...) — stamps ably-pubsub-server.
ably.io (1.x) Existing consumers Maintenance-only on the v1 branch (cut from tag 1.2.19). No further ably.io releases from main.

The door packages pin the core exactly ([2.0.x]) and the three packages version in lockstep. The side
flags are versionless agent entries read by Ably's billing pipeline.

How this was built and reviewed

The work landed on integration/v2 as three stacked, individually reviewed PRs, followed by review-feedback
commits on the integration branch itself:

  1. Split 1/3 — restructure into Ably.PubSub.Core (project/namespace restructure, packaging, CI):
    [Split 1/3] Restructure into Ably.PubSub.Core (assembly rename, drop Xamarin heads and push satellites, version 2.0.0) #1333
  2. Split 2/3 — door packages (Ably.PubSub.Device / Ably.PubSub.Server, ClientOptions.Clone()
    copy-on-entry semantics, sandbox door specs, Unity plugin rename to Ably.PubSub.Device.dll):
    [Split 2/3] Add Ably.PubSub.Device and Ably.PubSub.Server door packages with side-declaring agents #1334
  3. Split 3/3 — release tooling (dispatch-driven publish.yml with NuGet Trusted Publishing, release
    pre-flight assertions, prerelease support, CHANGELOG/UPDATING docs):
    [Split 3/3] Lockstep release pre-flight, release dry-run CI job, and publish workflow #1335
  4. Review-feedback follow-ups. The Unity dashboard sample ClientId fix landed pre-merge on the
    Split 2/3 branch (so its diff stays coherent). The remaining feedback landed as follow-up commits on
    integration/v2: build/CI hygiene and packaging metadata; a reflection-based ClientOptions.Clone()
    completeness spec; solution and namespace metadata alignment; reporting the informational version in the
    agent string; and reframing the parked device push-port wording. Two items are deferred, not yet landed:
    the billing-dependency wording softening (the "rejected once MAU-based pricing is live" claim), pending
    confirmation against PDR-091b §5; and the RTN2g realtime wire-key alignment (agent vs Ably-Agent),
    pending realtime-team confirmation — see the checklist below.

A main → integration/v2 sync was performed before the stack merged, so this branch already contains
everything on main (including the repository rename and the 1.2.19 release).

Consumer impact and migration

  • New applications install only Ably.PubSub.Device or Ably.PubSub.Server and construct clients
    through the door factories. The core is a transitive dependency; do not install or construct it directly.
  • Existing ably.io 1.x consumers migrate per UPDATING.md in this tree: swap the package, construct
    through a door. The API surface is otherwise the familiar IO.Ably namespace.
  • Never reference ably.io and Ably.PubSub.* from the same project — the types collide by design
    (compile error). The transitive-dependency scenario is covered in UPDATING.md.
  • Unity ships a single merged plugin, Ably.PubSub.Device.dll (door types public; core, Newtonsoft,
    and DeltaCodec internalized).
  • Device push-receive (the 1.x Android/iOS push satellites) is not part of the 2.0 package set; push
    admin remains in the core. See PushNotifications.md for the decision record.

Do not merge until (gates)

  • v1 maintenance branch cut from tag 1.2.19 (must carry package.yml and nuget/io.ably.nuspec) — hard gate.
  • Agent-registry entries merged in ably-common (ably-pubsub-dotnet, ably-pubsub-device, ably-pubsub-server): Register the Pub/Sub split agent identifiers: per-side flags and per-language families ably-common#361
  • AWS IAM OIDC trust re-bound to the renamed repository so the Features workflow is green (infra ticket: infrastructure#13005).
  • release GitHub environment configured with required reviewers and a branch restriction (the auto-created one is unprotected).
  • nuget.org Trusted Publishing policy re-bound to ably-pubsub-dotnet.
  • Realtime wire-key question resolved (RTN2g: agent query param vs Ably-Agent) and any resulting fix landed on this branch.
  • Unity plugin regenerated on Mono/Windows; duplicate-attribute (monodis) check clean; Unity EditMode/PlayMode smoke pass.
  • Full CI green on integration/v2 at the exact head this PR points at.

Merge mechanics

Squash-merge only. The integration branch briefly carried a 1.6 MB test-results file (added, then
removed); squashing keeps that blob out of main's history. After merge: tag and publish per
CONTRIBUTING.md — first real dispatch recommended as a 2.0.0-rc.1 prerelease rather than the
name-claim placeholder.

umair-ably and others added 30 commits September 2, 2026 14:32
Per PDR-091b plan decisions 5b and 6:

- delete the `IO.Ably.Android` (monoandroid) and `IO.Ably.iOS` (Xamarin.iOS)
  platform heads. They were 30-line `Platform.cs` heads whose only functional
  difference from the netstandard2.0 head was reporting the agent runtime as
  `xamarin`, no test workflow covered them, and they are what pinned the
  packaging workflow to windows-2022 plus a legacy Xamarin VS installer.
  Classic Xamarin / .NET for Android+iOS / MAUI consumers now receive the
  netstandard2.0 asset.
- delete the `IO.Ably.Push.Android` / `IO.Ably.Push.iOS` satellites, their
  nuspecs and the `package-push` scripts. `ably.io.push.android` /
  `ably.io.push.ios` 1.x continue from the 1.x maintenance line; a modern
  net8.0-android/net8.0-ios port is a post-GA 2.x follow-up.
- delete the `AndroidSample` and `DotnetPush` examples (they target the removed
  heads and satellites; they live on in the 1.x maintenance line).
- delete `IO.Ably.PackagePush.sln`, `IO.Ably.Xamarin.sln` and
  `IO.Ably.DotNetPush.sln`, which only existed for the removed projects, and
  drop the removed projects from the remaining solutions.
- drop the ILRepack `_Package_Merge_All` task, the `PushPackage` target and the
  Xamarin build tasks from the Cake build. The ILRepack helper itself stays:
  `Update.AblyUnity` still uses it to build the Unity plugin assembly.
- drop the Android SDK and legacy Xamarin installer steps and the whole
  `package-push` job from `.github/workflows/package.yml`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Per PDR-091b plan decision 2: the package/assembly identity changes, the code
namespace does not. `namespace IO.Ably` and every public type name are
untouched; the compiled assembly becomes `Ably.PubSub.Core.dll`.

The distinct assembly name is the load-bearing half of the decision: with
`IO.Ably.dll` kept, an app that transitively pulled both `ably.io` and the new
core would have MSBuild pick the higher version with only an MSB3277 warning
and fail at runtime. With a distinct assembly name and a shared namespace,
mixing the two produces loud CS0433 compile errors instead.

Moves (via `git mv`, so history follows):

  src/IO.Ably.NETStandard20      -> src/Ably.PubSub.Core
  src/IO.Ably.NETFramework       -> src/Ably.PubSub.Core.NETFramework
  src/IO.Ably.Shared             -> src/Ably.PubSub.Shared
  src/IO.Ably.Shared.MsgPack     -> src/Ably.PubSub.Shared.MsgPack
  src/IO.Ably.Tests.Shared       -> src/Ably.PubSub.Tests.Shared
  src/IO.Ably.Tests.DotNET       -> src/Ably.PubSub.Tests.DotNET
  src/IO.Ably.Tests.NETFramework -> src/Ably.PubSub.Tests.NETFramework
  src/IO.Ably.sln                -> src/Ably.PubSub.sln
  src/IO.Ably.Package.sln        -> src/Ably.PubSub.Package.sln
  src/IO.Ably.NetStandard.sln    -> src/Ably.PubSub.NetStandard.sln
  src/IO.Ably.NetFramework.sln   -> src/Ably.PubSub.NetFramework.sln

Target frameworks are unchanged: `netstandard2.0;net6.0;net7.0` plus the
`net462` head (decision 5).

Also updated: every project/solution/shared-project import path, the
`AssemblyName` and XML documentation file names on both heads, the
`InternalsVisibleTo` entries for the renamed test assemblies, `AssemblyTitle`,
the Cake paths/targets and the test-assembly names they look for, and
`tools/list-test-categories.fsx`.

`IO.Ably.ruleset`, `IO.Ably.Tests.ruleset`, `stylecop.json` and `IO.Ably.snk`
keep their names: the strong-name key must stay byte-identical and renaming the
rulesets buys nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`ably.io` is never published from this branch again — 1.x fixes ship from the
1.x maintenance line — so `nuget/io.ably.nuspec` is deleted rather than
retargeted, and `nuget/ably.pubsub.core.nuspec` takes its place.

- `<id>Ably.PubSub.Core</id>`, same `$version$` token, authors/owners/license/
  icon/readme/repository metadata as before, copyright year bumped to 2026.
- The `<description>` states plainly that this is an internal implementation
  package for Ably's own `Ably.PubSub.Device` / `Ably.PubSub.Server` packages
  and is not intended for direct use (PDR-091b §1). NuGet consumers receive it
  transitively, so "internal" is a statement in metadata and docs, not
  something the dependency graph can enforce.
- Dependency groups: netstandard2.0 / net6.0 / net7.0 / net46, each declaring
  Newtonsoft.Json 13.0.1 and System.Threading.Channels. The monoandroid /
  Xamarin.iOS / monotouch groups are gone with their heads.
- The net46 assets now come from the plain build output rather than an
  ILRepack-merged `Packaged/` directory, hence Newtonsoft.Json is a declared
  net46 dependency instead of a merged-in one.
- `IO.Ably.DeltaCodec.*` now needs explicit `files` entries: the old
  `IO.Ably.*` glob happened to pick the delta codec up, and
  `Ably.PubSub.Core.*` does not.

`_Package_Create_NuGet` now packs a list of nuspecs so stack PR 2 can add the
device and server nuspecs to it, and `package.cmd` / `package-unity.sh` no
longer name `ably.io`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`Ably.PubSub.Core` starts at 2.0.0 and, from stack PR 2 on, releases in
lockstep with `Ably.PubSub.Device` and `Ably.PubSub.Server`. Bump the single
source of the runtime version (`src/CommonAssemblyInfo.cs`, read back by
`Defaults.GetVersion()`) and the Unity package version, and move the copyright
year to 2026.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The Unity package ships a single ILRepack-merged plugin assembly. Point
everything that names it at the new assembly name: the `Update.AblyUnity` Cake
task (input and output), `link.xml`'s `<assembly fullname>`, the
`precompiledReferences` of the AblySandbox / EditMode / PlayMode asmdefs, and
the `unity/CONTRIBUTING.md` note.

The stale `unity/Assets/Ably/Plugins/IO.Ably.dll` is removed rather than
regenerated: ILRepack needs Mono or Windows, neither of which is available in
the environment this branch was prepared in, so the merged
`Ably.PubSub.Core.dll` has to be produced by running
`unity-plugins-updater.sh 2.0.0` (or the `.cmd`) on a machine that has Mono.
The plugin's `.meta` is renamed in place so the importer settings and asset
GUID survive; the regenerated dll drops straight into it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Minimal docs pass only; the full README rewrite and the migration guide are a
later phase of the plan.

- README: a "2.0 is in development" note at the top describing the new package
  set (`Ably.PubSub.Device` / `Ably.PubSub.Server` in the next PR,
  `Ably.PubSub.Core` internal), the unchanged `IO.Ably` namespace, the
  never-mix rule, and that `ably.io` 1.x continues from a maintenance branch.
  The "Supported platforms" table drops the Xamarin.Android/iOS/Mac rows for
  ".NET for Android, .NET for iOS and MAUI via netstandard2.0", and the MAUI
  `TrimmerRootAssembly` snippet now names `Ably.PubSub.Core`. Install and usage
  sections still describe 1.x and say so.
- CONTRIBUTING: the "working from source" project paths, and the release-step
  artifact names.
- cake-build/README: new project names, the `Build.Xamarin` target is gone, and
  the packaging section documents `package.cmd` producing
  `Ably.PubSub.Core.*.nupkg` from the nuspec list plus `package-unity.sh`.
- PushNotifications.md: a note that it describes the 1.x push-receive packages,
  which are not in the 2.0 set, and that push admin is unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`IoC`'s static constructor located the platform head's `IO.Ably.Platform` type
by loading an assembly literally named "IO.Ably". After the assembly rename
that load throws `FileNotFoundException`, which the ctor swallows, leaving
`Platform` null. Every platform service then silently degraded: the transport
factory and `PlatformId` fell back (so the agent string lost its `dotnetN` /
OS entries), and `IoC.MobileDevice` threw `NullReferenceException` because only
`NotImplementedException` is caught there — which is what 18 `RestInitSpecs`
tests hit.

`Platform.cs` is compiled into the same assembly as this shared code by every
head, so look the type up in this assembly instead. That is also immune to any
later rename.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`FindTestAssemblies` defaults to a filename pattern, which still looked for
`IO.Ably.Tests.*.dll` and so found nothing after the test assemblies were
renamed. The Cake helper only warns when it finds no assemblies and the task
then returns early, so the .NET Framework test legs would have gone green
without running a single test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- D9: remove the committed 1.6 MB test-results .trx artifact and ignore *.trx and test-results/
- D27: add a pinned root nuget.config (nuget.org only, with source mapping) and drop the four solutions' dangling .nuget\NuGet.Config solution item
- D29: align built-against System.Threading.Channels to 4.6.0 (matching the nuspec) and System.Threading.Tasks.Extensions to 4.5.2 (matching the net46 head)
- D11: document the transitive ably.io/Ably.PubSub.* mixed-graph failure (CS0433, type identity) plus the dotnet-nuget-why detection and extern alias isolation recipe
- D32: replace the false "rewritten later in this stack" Installation/Usage promise with an honest before-2.0-GA sequencing note
- D33: discourage the direct core AblyRealtime/AblyRest constructors in XML docs (summary one-liner plus remarks rationale), pointing at the door factories
- D34: drop the stale 1.x ably.io NuGet badge from the README
- D35: fix stale doc cross-references (PushNotifications.md Dart link, unity/README.md dead anchor, past-dated protocol-v1 deprecation line)
- D17 (change 1): sign the net46 core head under package builds only, matching the SDK-style core
- D8 (guard): fail _Package_Unity packaging when the committed Unity plugin Ably.PubSub.Device.dll is missing

PubSub device/server split rollout (PDR-091b2) review follow-ups.
The core stamped `ably-dotnet/<version>` as its RSC7d1 family identifier.
At the Pub/Sub package split (PDR-091b) it becomes
`ably-pubsub-dotnet/<version>`, registered in ably-common#361 as a
versioned `sdk` entry.

The flip is the point: with the 1.x maintenance branch keeping the old
identifier, the string alone partitions legacy traffic from
new-package traffic, so no version correlation is needed to tell them
apart.

Updates the four spec files that assert on the token: the shared
realtime connection-parameter specs, the shared REST HTTP client specs,
and the Unity EditMode/PlayMode specs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ports the ably-js `packages/shared/side.ts` contract (ably-js#2293,
ably-java#1233).

`src/Ably.PubSub.Side/Side.cs` is a single shared source file compiled
into both door assemblies by a `<Compile Include>` item rather than
published as a third package - the .NET analogue of ably-js's
`shared/side.ts` and ably-java's `shared/.../Side.java`. It holds both
side identifiers, with the load-bearing-suffix warning, and
`WithSideAgent`, which:

  - builds a new `Agents` dictionary from the caller's entries, so the
    caller's own dictionary instance is never mutated;
  - applies the side entry last with a null value, so the flag is
    versionless (`Agent.AddAgentIdentifier` already emits a bare token
    for a null version) and wins a collision on its own key.

`PubSubServer` (`CreateRealtimeClient` / `CreateHttpClient`) and
`PubSubDevice` (`CreateClient`) each take the three shapes the core
constructors accept - key or token string, `ClientOptions`,
`Action<ClientOptions>` - and return the concrete `AblyRealtime` /
`AblyRest`. One device door by design: device-side connectionless
operations stay available on that client, so there is no device HTTP
door.

Both doors are strong-named in every configuration, so a consumer of
the signed core never mixes signed and unsigned Ably assemblies, and
both target the core's `netstandard2.0;net6.0;net7.0`. Server also gets
an old-style `net462` head mirroring the core's, so the package has a
`lib/net46` asset; there is deliberately no `net462` Device.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`ably.pubsub.device.nuspec` and `ably.pubsub.server.nuspec` carry the
same authors/licence/icon/repository metadata as the core's, and each
declares an exact pin on the core (`[$version$]`) per target-framework
group - the NuGet analogue of ably-js's exact `peerDependencies`, so a
consumer can never resolve two core versions. Server ships net46 (from
its .NET Framework head), netstandard2.0, net6.0 and net7.0; Device
ships the same minus net46.

`_Package_Create_NuGet` packs core, then device, then server, matching
the publish order stack PR 3 will need.

The `[$version$]` substitution inside a dependency version attribute is
marked TODO to verify on the release dry run - no nuget.exe or Mono
locally to check it. Stack PR 3 adds the pre-flight that asserts the
packed pin equals the version.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Thirteen specs in Ably.PubSub.Tests.DotNET/PubSub/PubSubPackageSpecs.cs.
They live in the .NET test head rather than Ably.PubSub.Tests.Shared
because Ably.PubSub.Device has no net462 asset, so the shared project
cannot reference it from the .NET Framework head.

What they pin, using the existing MockHttp/FakeHttpMessageHandler
capture for the header and the fake transport factory for the realtime
connection params, so nothing here opens a network connection:

  - the `Ably-Agent` header a door-created REST client actually puts on
    the wire contains the bare side flag, no versioned form of it, the
    versioned `ably-pubsub-dotnet/<version>` family identifier, and not
    the other side's flag;
  - the same for the realtime connection params from
    `TransportParams.GetParams()`;
  - caller `Agents` entries survive alongside the flag; a caller entry
    under the side's own key is overridden; the caller's own dictionary
    instance is untouched;
  - null options and a null configure action throw
    ArgumentNullException from every door;
  - all three overload shapes return the concrete core types;
  - the string overload's key-versus-token colon rule.

The identifiers are written out as literals, not read from `Side`, so a
rename of the constant fails here instead of passing silently.
Verified by mutation: giving the flag a version fails 8 of the 13.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Replaces the "added in the next PR in this stack" placeholders in the
2.0-in-development note with install commands and the door snippets for
both sides, and states plainly that the doors are the supported entry
points and Ably.PubSub.Core is internal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…evice door

- D3: add ClientOptions.Clone() to the core (member-wise copy; fresh dictionaries for Agents/AuthHeaders/AuthParams/TransportParams; private write-only host fields carried from inside the class) and make Side.WithSideAgent stamp a clone, never the caller's instance; rewrite the mutation-ratifying spec and add a cross-door reuse regression spec
- D4: add PubSubDoorSandboxSpecs (type=integration) - one sandbox publish/subscribe round-trip per realtime door and one REST call through the HTTP door
- D14: pin the unclassified-core promise - directly-constructed AblyRest/AblyRealtime emit neither side flag (while carrying the family identifier)
- D16: exception-parity spec - the no-credentials HTTP door fails with exactly the core's own 40106, proving it neither requires nor injects auth
- D28: fix Ably.PubSub.Package.sln shared-project metadata (drop phantom GUID, register the real Core consumer)
- D1: merge the Ably.PubSub.Device door into the Unity plugin - MergeDLLs gains an internalize-exclude-file parameter, cake-build/unity-internalize-exclude.txt keeps IO.Ably.PubSub.Device.* public, the merge output is renamed Ably.PubSub.Device.dll (.meta GUID preserved, link.xml, three test asmdefs, unity CONTRIBUTING/README synced), and the Unity sample constructs through PubSubDevice.CreateClient
- D36: route the NotificationsPublisher example through PubSubServer.CreateRealtimeClient with a server-door project reference
- D33: soft-[Obsolete] the five public core AblyRealtime/AblyRest constructors pointing at the door factories; scoped CS0618 suppressions at the sanctioned door call sites; NoWarn 618 on the two test heads that deliberately exercise the constructors
- D17 (changes 2-3): make door signing Package-conditional in lockstep with the core (all three door heads) and delete the ruleset CS8002 suppression so any future signed-vs-unsigned mix fails the build
- D32: rewrite the README Installation/Usage sections onto the door packages and drop the now-satisfied interim sequencing note; the transport-buffer example moves to the server door alongside the constructor obsoletion
- D15: verified locally with nuget.exe 6.3.1 (Mono) that $version$ substitutes inside dependency version attributes (packed pins read [2.0.0]); settled the TODO comments in both door nuspecs
- MergeDLLs also gains a Mono-facades /lib fallback (appended only when the facades directory exists on disk, so Windows invocations are bit-for-bit unchanged): under Mono, /targetplatform:v4 cannot resolve the netstandard facade the netstandard2.0 inputs reference

Includes the regenerated Unity plugin, produced by the sanctioned
./unity-plugins-updater.sh 2.0.0 pass under local Mono with the facades-lib
robustness fix; merged-assembly surface verified with monodis: assembly
Ably.PubSub.Device 2.0.0, door public, core public, Newtonsoft/DeltaCodec
internalized (D8, D1 dry-run items executed). Unity EditMode/PlayMode smoke
remains for the Windows/Unity pass.

PubSub device/server split rollout (PDR-091b2) review follow-ups.
Three packages ship at one version and both doors pin the core with an
exact version range. Nothing in the build enforced any of that, so a
loose pin, a stale build or a version-file skew would first become
visible to a consumer after the version had been published and could
never be changed again.

cake-build/tasks/release.cake adds three tasks that bracket the pack:

  _Release_Preflight       source-only assertions: the --version input
                           equals all three attributes in
                           src/CommonAssemblyInfo.cs and
                           unity/Assets/Ably/version.txt; nuget/ holds
                           exactly the lockstep set with the expected
                           ids and the $version$ token; every dependency
                           group of every door pins Ably.PubSub.Core as
                           [$version$]; nothing depends on ably.io or
                           the 1.x push satellites.
  _Release_Verify_Files    every <file src> glob resolves to a real
                           file. nuget silently omits a files entry it
                           cannot resolve, so this is the last point at
                           which an empty or partial package can be
                           caught.
  _Release_Verify_Packages post-pack assertions against the produced
                           .nupkg files: id, version, one lib/<tfm>
                           assembly per declared target, and the packed
                           door -> core pin.

The pre-flight is a dependency of _Version rather than of
_Package_Build_All because _Version overwrites CommonAssemblyInfo.cs
with the --version input; running after it would make the version
assertion a tautology. Package now fails loudly without --version
instead of silently producing nothing.

The packed-pin assertion is what proves the open question from the door
packages PR: NuGet does substitute $version$ inside a dependency's
version attribute, and the packed pin comes out as [2.0.0]. Both door
nuspecs lose their TODO and say so.

The same source-level assertions are duplicated as xunit specs in
Ably.PubSub.Tests.DotNET/PubSub/PackagingSpecs.cs, so a PR that edits a
nuspec fails the ordinary unit run without waiting for a packaging job.
They locate nuget/ by walking up from the test assembly rather than by
counting directories.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The lockstep invariants live in the version files and the nuspecs, none
of which the compiler reads, and a NuGet version once published can
never be changed. This packs all three packages from every PR commit
and runs the pre-flight and the post-pack assertions over them, so a
version-file skew, a loosened pin, a renamed id or a nuspec files entry
that no longer resolves fails on the PR that introduced it rather than
on release day.

Windows, not Linux, because the core and server packages carry a
lib/net46 asset built by an old-style MSBuild head. `dotnet pack
-p:NuspecFile=...` does pack a nuspec Mono-free, so packing is not what
needs Windows - the net462 build is - and _Release_Verify_Files fails
loudly rather than letting a Linux run ship packages silently missing
that asset.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Today's release is a human downloading an artifact zip and running
`dotnet nuget push` by hand. With three packages that must land in
dependency order, at one version, and where a half-finished release
cannot be undone, that is not a process anyone should be asked to
execute correctly under pressure.

publish.yml is dispatch-only, takes `version` and `dry_run` (default
true), and:

  - runs the pre-flight before anything is built, so a mismatched
    version or a loosened pin aborts the run with nothing produced;
  - builds, packs and creates the .unitypackage in one job from one
    build, so the Unity asset and the .nupkg files can never come from
    different builds of the same version;
  - pushes core -> device -> server, and waits for the core version to
    be listed on nuget.org before the doors that pin it go out, because
    nuget.org validates and indexes asynchronously;
  - queries the flat container before each push and skips a version
    already published, so a run that fails partway is completed by
    re-running it with the same version rather than by hand;
  - creates the tag and GitHub release, with all four artifacts
    attached, from a separate job so that contents: write is scoped to
    the only step that needs it;
  - prints the unlist guidance on every run, because NuGet cannot
    delete and the moment it is needed is the moment nobody wants to be
    reading a workflow file.

Authentication is nuget.org Trusted Publishing: GitHub OIDC exchanged
by NuGet/login for an API key valid for one hour, requested immediately
before the push, so the repository holds no long-lived NuGet
credential. The fallback to a NUGET_API_KEY secret is documented in a
comment at the step, and the registry-side setup in CONTRIBUTING.md.

Because the pre-flight demands the 2.0 nuspec set, this workflow is
inert on a 1.x checkout: it can be cherry-picked to the default branch
(which is where `gh workflow run` reads workflow files from) and
dispatched against integration refs without being able to release 1.x.

package.yml is deleted rather than kept alongside: it built the same
artifacts by the same Cake targets and then asked a human to push them,
which is now `dry_run=true` with assertions. package.cmd,
package-unity.sh and build.sh are unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CONTRIBUTING.md's release process was ten manual steps ending in a
hand-run `dotnet nuget push` of an artifact zip. It is now: bump one
version in two files, PR, merge, dispatch publish.yml with
dry_run=true, dispatch it again with dry_run=false. The tag, the GitHub
release and the .unitypackage attachment are the workflow's job. The
changelog and Headway steps are unchanged, and the re-run-to-complete
and unlist-to-abandon behaviours are written down where someone
mid-incident will find them.

Adds the nuget.org Trusted Publishing setup as its own section: what
the policy binds (owner, repository, the workflow file name only), that
its scope has to allow new packages if a brand-new id is being claimed,
that a private-repo policy is provisional for 7 days until the first
publish gives nuget.org the repository ids, that it matches by
repository name and so must be created after any rename, and how to
fall back to an API key.

cake-build/README.md documents Release.Preflight and
Release.VerifyPackages, the three packages that package.cmd now
produces, --packageOutput, and the `--` separator that Cake's reserved
--version flag forces.

README gains a paragraph on why the exact core pin means all
Ably.PubSub.* references in a project move together.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…tooling

- D17 follow-up (composition break surfaced by the release dry run): under Package builds the signed core references the unsigned submodule-built DeltaCodec on the SDK TFMs - a pre-existing mix the deleted global ruleset suppression had been masking. Scope a CS8002 NoWarn to the core's Package-conditional signing group only (the doors compile clean and get nothing); the plain-Release guard stays fully live; proper cure is signing the submodule build (follow-up)
- D25: make 2.0.0-beta.N buildable and publishable - _Version stamps numeric identity into AssemblyVersion/AssemblyFileVersion (CS7034 otherwise) and the full string into AssemblyInformationalVersion; ReleaseAssertVersionFilesAgree asserts per-attribute expectations and its success message reworded; gh release create gains --prerelease for hyphenated versions; PackagingSpecs.TheTwoVersionFiles_Agree mirror-patched to the same split; README exact-pin paragraph gains the prerelease-pinning sentence
- D26: publish.yml gains a workflow-level concurrency group keyed on the version (never cancel in-progress) and the publish job runs in the `release` environment as the required-reviewer gate
- D7: new pre-flight assertion ReleaseAssertUnityPluginVersion - the committed unity/Assets/Ably/Plugins/Ably.PubSub.Device.dll must exist and carry the release's numeric identity and full informational version, so a stale merged plugin can never ship inside the .unitypackage
- D1 (CI): publish.yml regenerates the Unity plugin from the release checkout before UnityPackage and cross-checks identity/informational version against the committed DLL, which stays canonical and ships (it is what the Unity test pass validated)
- D12: nuspec projectUrl/releaseNotes/repository URLs moved to ably-pubsub-dotnet in all three nuspecs (metadata freezes per version at push time)
- D13: CHANGELOG gains the 2.0.0 entry and UPDATING.md is added as the 1.x -> 2.0 migration guide (door factories, mixed-graph rule, exact pinning, MAU forcing function, Xamarin push-receive gap, Unity door usage)
- D30: the five run-tests workflows also trigger on pushes to integration/** branches (previously only release-dry-run.yml did)
- D31: RestoreSolution stops swallowing restore failures - Windows NuGetRestore throws; the non-Windows nuget CLI path probes for the tool, warns-and-skips when absent (Mono-less macOS/Linux legs) and throws when present-and-failing; DotNetRestore now throws unconditionally
- D5: features.yml repository-name updated to ably-pubsub-dotnet - the check stays red regardless until the ops-side AWS IAM trust-policy re-bind allows the renamed repo
- D18 (optional polish, included - builds clean): Microsoft.SourceLink.GitHub 8.0.0 with PublishRepositoryUrl/EmbedUntrackedSources on the three SDK csprojs

Deferred/ops notes: the Windows-pack halves remain for CI (net46 pack/install
check, sn -v on packed assemblies, the publish.yml regenerate/cross-check dry
run); the `release` GitHub environment must be created and given required
reviewers plus a deployment-branch restriction in repo Settings - referencing
it auto-creates it unprotected; D13's entry needs its release date and compare
link when the release is cut; D25's wire-agent consequence (a beta build
reports ably-pubsub-dotnet/2.0.0 without the label via Defaults.GetVersion())
needs rollout-owner sign-off; Unity EditMode/PlayMode smoke of the committed
plugin remains for the Windows/Unity pass.

PubSub device/server split rollout (PDR-091b2) review follow-ups.
Bring the main-side changes now on integration/v2 (RTN23 connection
fixes, ably-dotnet -> ably-pubsub-dotnet rename references, the 1.2.19
release commits and the package-push runner fix) into the split-1 Core
restructure. Rename-aware resolution: main's edits to the old
src/IO.Ably.* paths land in the renamed src/Ably.PubSub.* files via
git rename detection (verified: TransportParams RTN23b heartbeats change
is byte-identical to main in the renamed Ably.PubSub.Shared file).

Conflict resolutions:
- .github/workflows/package.yml: keep restructure (the package-push
  Xamarin job was removed in the 2.0 layout; main's runner fix targets
  that now-deleted job).
- CONTRIBUTING.md, README.md: keep the 2.0 restructure content; main's
  ably-dotnet -> ably-pubsub-dotnet URL swaps are cosmetic and slated
  for a post-merge docs pass.
- src/CommonAssemblyInfo.cs, unity/Assets/Ably/version.txt: keep 2.0.0
  (main's 1.2.19 bump is superseded, not a downgrade of the 2.0 branch).
- nuget/io.ably*.nuspec, unity/Assets/Ably/Plugins/IO.Ably.dll: keep the
  restructure deletions (renamed to ably.pubsub.* / Ably.PubSub.Device).
Propagate the integration/v2 sync (RTN23 fixes, rename references,
1.2.19 release commits) up the stack via the split-1 Core branch.
Clean auto-merge, no conflicts.
Propagate the integration/v2 sync (RTN23 fixes, rename references,
1.2.19 release commits) to the top of the stack.

Conflict resolutions:
- .github/workflows/features.yml: both sides set
  repository-name: ably-pubsub-dotnet; keep the incoming explanatory
  comment about the IAM OIDC role binding.
- CHANGELOG.md: both sides added a section at the top; keep both, the
  hand-written 2.0.0 section above the generated 1.2.19 section.
M18: the door factory PubSubDevice.CreateClient clones the options it
is given, where new AblyRealtime(options) used to store them by
reference. The dashboard sample created its client at startup and
assigned _clientOptions.ClientId in the connect handler, so the typed
ClientId mutated only the caller's copy and was silently ignored by the
already-created client - the sample's ClientId input became a no-op.

Restructure the sample so ClientId is set before the options are
cloned, and recreate the client on each connect so a ClientId changed
between sessions is captured:
- InitializeAbly() now only constructs _clientOptions.
- New CreateAblyClient() creates the client, wires the existing
  Connection.On handler unchanged, and closes any client it replaces.
- ConnectClickHandler() closes when connected; otherwise it sets
  ClientId, recreates the client, and connects.

Scope extension over the planned AblyMain.cs-only change: AblyChannel
and AblyPresence captured the client reference in readonly fields at
startup, so recreate-on-connect requires them to accept an updated
reference - they gain an internal UpdateClient(AblyRealtime) which
AblyMain calls (null-conditionally) after each recreation.

unity/README.md's simpler sample (no connect handler) gets the minimal
faithful mapping: InitializeAbly split into options construction plus
CreateAblyClient, with a comment on the clone semantics.
Merge the door-packages branch (M18 sample fix) so the release-tooling
tip stays consistent with the layer below. Clean auto-merge.
[Split 3/3] Lockstep release pre-flight, release dry-run CI job, and publish workflow
Review follow-ups (M-IDs from the review-response plan):

- M5: FindTestAssemblies now throws when a pattern matches zero test
  assemblies instead of warning and returning green - a glob typo can
  no longer pass as a successful run with zero tests.
- M40: features.yml gains the integration/** push trigger the other
  six workflows already have.
- M7: the core nuspec lists the lib/net46 files explicitly (dll + xml
  + DeltaCodec dll) so the old glob no longer sweeps in the .dll.config
  and .pdb.
- M34: the net46 Server head cannot host the SourceLink analyzer (legacy
  packages.config project); the limitation is documented in the csproj
  header alongside the same-shaped core head rather than half-wired in.
- M32: CONTRIBUTING no longer claims the publish workflow uses no GitHub
  environment - it documents the release environment as the human
  approval gate and the optional nuget.org policy Environment pin.
- M37: release steps note that the hand-written 2.0.0 CHANGELOG section
  must be merged with the generator output, not duplicated.
- M38: the Unity regenerate-and-cross-check step documents its limit
  (identity/version comparison, not byte identity - ILRepack output is
  nondeterministic; the committed, Unity-tested copy stays canonical).
- M39: the same step documents why the pack step must stay ordered
  before it (Build.NetStandard depends on _Clean, which wipes bin/).
- M1 hardening: the committed Unity plugin path is defined once, in
  paths.cake (UnityPluginDll), and referenced by the build task, the
  packaging guard and the release pre-flight so the sites cannot drift.
- M2 residual: remaining ably-dotnet URLs and package-name mentions in
  README updated to ably-pubsub-dotnet.
- README usage sample: add the missing 'using IO.Ably;' - the block
  uses core types (ConnectionEvent, IRealtimeChannel) that the door
  namespace alone does not import, so it did not compile as copied.
  (UPDATING.md samples already carry both usings.)

Validation: cake graph compiles (dry run of the Package target);
FindTestAssemblies exercised both ways via a scratch cake script
(real pattern finds 1 assembly, wrong pattern throws); both workflow
files YAML-parse; nuspec and csproj XML-parse; NetStandard solution
builds with 0 warnings / 0 errors.
M21: ClientOptions.Clone() is a hand-maintained public API of the core
(the door factories copy options through it on entry), so it silently
drops the first property someone adds and forgets to copy. Guard against
that rot with a reflection spec that stamps a distinct, non-default value
on every public settable property (including the inherited AuthOptions
members), clones, and asserts the clone matches the original.

Design notes:
- Compares the clone against the ORIGINAL's getter, not the stamped value,
  so a deliberately no-op setter (UseBinaryProtocol discards its value in
  non-MSGPACK builds) compares default-to-default and passes, while a
  forgotten copy still fails (original carries the stamp, clone the default).
- Write-only host fields (RestHost/RealtimeHost/FallbackHosts) are asserted
  through their private backing fields.
- Deep-copied dictionaries (Agents/AuthHeaders/AuthParams/TransportParams)
  are asserted NotBeSameAs + BeEquivalentTo (Clone rebuilds them).
- ChannelDefaults (internal setter) is asserted BeSameAs separately.
- Obsolete members are pragma-618 guarded; the value factory throws on an
  unhandled property type so a new property of a new shape fails here too.
- A separate block covers the internal Logger/NowFunc (by reference) and
  SkipInternetCheck (by value) via InternalsVisibleTo.

Validation: the spec passes; verified non-vacuous by temporarily dropping
the ClientId copy in Clone() and confirming the spec fails, then reverting.
NetStandard solution builds 0 warnings / 0 errors.
M26: the SDK-style door projects Ably.PubSub.Device and
Ably.PubSub.Server carried the legacy project-type GUID
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} in every solution that lists
them; give them the SDK-style {9A19103F-16F7-4668-BE54-9A1E7A4F7556}.
The net46 heads (Core.NETFramework, Server.NETFramework,
Tests.NETFramework) and IO.Ably.DeltaCodec are genuinely non-SDK and
keep the legacy GUID. Also unify each door's per-project GUID across
solutions (Device -> {ADD94C3B-...}, Server -> {882D22FB-...}) so one
project no longer has three identities; no csproj ProjectReference keys
off these GUIDs, so the change is self-contained to the solutions.

M26 (config): in Ably.PubSub.NetFramework.sln, Ably.PubSub.Server.NETFramework
{7B3C1F42-...} mapped its solution-level  and
configurations to Debug|Any CPU, so a solution-level Package build would
produce and consume Debug bits for the net46 Server asset. Map both
configurations (ActiveCfg + Build.0, all four platforms) to Release|Any CPU,
matching the sibling Ably.PubSub.Core.NETFramework {2D265650-...} precedent in
the same solution. (Ably.PubSub.Package.sln, the solution the packaging
pipeline actually builds, declares no package/package_netstandard solution
configs and already maps Release->Release, so it was correct.)

M10: RootNamespace hints pointed at the assembly names
(Ably.PubSub.Shared, Ably.PubSub.Tests.NETFramework) while the code
namespace is IO.Ably; a contributor adding a file in VS got the wrong
namespace seeded. Set them to IO.Ably and IO.Ably.Tests. Presentation
only - RootNamespace does not affect compiled output here.

M25: the Device csproj comment said '.NET Framework is not a supported
device target', which is wrong - a .NET Framework 4.6.2+ WPF/WinForms app
is a device target and consumes the netstandard2.0 asset, as MAUI does.
Reword to say why there is no separate .NET Framework Device head.

Validation: all four solutions parse (balanced Project/EndProject, BOM
and LF line endings preserved, diff symmetric); FAE04EC0 now appears only
on the net46 heads and DeltaCodec; NetStandard solution builds 0W/0E;
targeted PubSub + Clone specs pass (32/32).
M33: Defaults.GetVersion() read AssemblyFileVersion, which D25 stamps
numeric-only (2.0.0) while the full SemVer including any prerelease
label lives in AssemblyInformationalVersion. A prerelease such as
2.0.0-beta.1 therefore identified on the wire as 2.0.0, indistinguishable
from GA.

Read AssemblyInformationalVersion instead and strip the SourceLink
'+<commit>' build-metadata suffix via a new internal
NormalizeInformationalVersion helper, keeping the SemVer core and the
prerelease label. The old numeric file-version path (first three parts)
stays as a fallback when no informational version is present; the .Take(3)
truncation is deliberately not applied to the informational version, which
would corrupt a prerelease label.

This does NOT include the RTN2g realtime wire-key change (M16), which is
still gated on realtime-team confirmation.

Validation: NetStandard solution builds 0 warnings / 0 errors; new
normalizer theory covers the beta+metadata, GA+metadata, prerelease and
plain cases, plus a spec asserting GetVersion() carries no '+' suffix in
this SourceLink-enabled build; targeted Defaults/Agent/HTTP tests pass
(31/31).
M-mau-wording (push-port half only): decision 6 parks the device
push-receive port rather than committing it to a milestone, but the docs
described a modern net8.0-android/net8.0-ios port on Ably.PubSub.Device as
a "post-GA (2.x) follow-up", which reads as a scheduled commitment.
Reframe it as a possible future follow-up, currently parked with no
committed milestone, at the three sites: PushNotifications.md, CHANGELOG.md
and UPDATING.md.

Scope: this lands only the unconditional push-port half of the wording
work. The billing-dependency half (softening "a directly-constructed
client is rejected once MAU-based pricing is live" across the docs and the
AblyRealtime/AblyRest XML docs and [Obsolete] messages) is deferred pending
confirmation against PDR-091b section 5 of whether the rejection claim
holds for 2.x core constructors as written, and is intentionally left
unchanged here.

Validation: docs-only change; verified the diff touches only the three
push-port sentences and leaves the billing/MAU wording untouched.
@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 577 files, which is 477 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

Usage-priced reviews support at most 300 files.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 18965833-5a60-45af-b4c8-993d5d7cdd5c

📥 Commits

Reviewing files that changed from the base of the PR and between c7bdc09 and 54eff1b.

⛔ Files ignored due to path filters (62)
  • examples/AndroidSample/Resources/drawable-hdpi/icon.png is excluded by !**/*.png
  • examples/AndroidSample/Resources/drawable-xhdpi/icon.png is excluded by !**/*.png
  • examples/AndroidSample/Resources/drawable-xxhdpi/icon.png is excluded by !**/*.png
  • examples/AndroidSample/Resources/drawable/Icon.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/drawable/ably_logo.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/drawable/icon_about.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/drawable/icon_feed.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/drawable/xamarin_logo.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-hdpi/icon.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-hdpi/launcher_foreground.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-hdpi/logo.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-hdpi/logo_adaptive_back.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-hdpi/logo_adaptive_fore.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-mdpi/icon.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-mdpi/launcher_foreground.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-mdpi/logo.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-mdpi/logo_adaptive_back.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-mdpi/logo_adaptive_fore.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xhdpi/icon.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xhdpi/launcher_foreground.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xhdpi/logo.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xhdpi/logo_adaptive_back.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xhdpi/logo_adaptive_fore.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxhdpi/icon.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxhdpi/launcher_foreground.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxhdpi/logo.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxhdpi/logo_adaptive_back.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxhdpi/logo_adaptive_fore.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxxhdpi/icon.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxxhdpi/launcher_foreground.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxxhdpi/logo.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxxhdpi/logo_adaptive_back.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-xxxhdpi/logo_adaptive_fore.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon1024.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon120.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon152.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon167.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon180.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon20.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon29.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon40.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon58.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon60.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon76.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon80.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Icon87.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/Default-568h@2x.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/Default-Portrait.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/Default-Portrait@2x.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/Default.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/Default@2x.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/icon_about.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/icon_about@2x.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/icon_about@3x.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/icon_feed.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/icon_feed@2x.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/icon_feed@3x.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/xamarin_logo.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/xamarin_logo@2x.png is excluded by !**/*.png
  • examples/DotnetPush/DotnetPush.iOS/Resources/xamarin_logo@3x.png is excluded by !**/*.png
  • unity/Assets/Ably/Plugins/Ably.PubSub.Device.dll is excluded by !**/*.dll
  • unity/Assets/Ably/Plugins/IO.Ably.dll is excluded by !**/*.dll
📒 Files selected for processing (577)
  • .github/workflows/features.yml
  • .github/workflows/package.yml
  • .github/workflows/publish.yml
  • .github/workflows/release-dry-run.yml
  • .github/workflows/run-tests-linux.yml
  • .github/workflows/run-tests-macos-mono.yml
  • .github/workflows/run-tests-macos.yml
  • .github/workflows/run-tests-windows-netframework.yml
  • .github/workflows/run-tests-windows.yml
  • .gitignore
  • CHANGELOG.md
  • CLAUDE.md
  • CONTRIBUTING.md
  • PushNotifications.md
  • README.md
  • UPDATING.md
  • cake-build/README.md
  • cake-build/build.cake
  • cake-build/helpers/paths.cake
  • cake-build/helpers/test-execution.cake
  • cake-build/helpers/tools.cake
  • cake-build/helpers/utils.cake
  • cake-build/tasks/build.cake
  • cake-build/tasks/package.cake
  • cake-build/tasks/release.cake
  • cake-build/tasks/test.cake
  • cake-build/unity-internalize-exclude.txt
  • examples/AndroidSample/AblyService.cs
  • examples/AndroidSample/AndroidSample.csproj
  • examples/AndroidSample/App.xaml
  • examples/AndroidSample/App.xaml.cs
  • examples/AndroidSample/Assets/AboutAssets.txt
  • examples/AndroidSample/Class1.cs
  • examples/AndroidSample/GettingStarted.Xamarin
  • examples/AndroidSample/IAblyService.cs
  • examples/AndroidSample/LogPage.xaml
  • examples/AndroidSample/LogPage.xaml.cs
  • examples/AndroidSample/MainActivity.cs
  • examples/AndroidSample/MainPage.xaml
  • examples/AndroidSample/MainPage.xaml.cs
  • examples/AndroidSample/MainViewModel.cs
  • examples/AndroidSample/Properties/AndroidManifest.xml
  • examples/AndroidSample/Properties/AssemblyInfo.cs
  • examples/AndroidSample/Resources/AboutResources.txt
  • examples/AndroidSample/Resources/Resource.Designer.cs
  • examples/AndroidSample/Resources/layout/Tabbar.axml
  • examples/AndroidSample/Resources/layout/Toolbar.axml
  • examples/AndroidSample/Resources/values/Strings.xml
  • examples/AndroidSample/Resources/values/styles.xml
  • examples/AndroidSample/app.config
  • examples/AndroidSample/packages.config
  • examples/DotnetPush/DotnetPush.Android/Assets/AboutAssets.txt
  • examples/DotnetPush/DotnetPush.Android/DotnetPush.Android.csproj
  • examples/DotnetPush/DotnetPush.Android/MainActivity.cs
  • examples/DotnetPush/DotnetPush.Android/MyFirebaseMessaging.cs
  • examples/DotnetPush/DotnetPush.Android/Properties/AndroidManifest.xml
  • examples/DotnetPush/DotnetPush.Android/Properties/AssemblyInfo.cs
  • examples/DotnetPush/DotnetPush.Android/Resources/AboutResources.txt
  • examples/DotnetPush/DotnetPush.Android/Resources/Resource.designer.cs
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-anydpi-v26/icon.xml
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-anydpi-v26/icon_round.xml
  • examples/DotnetPush/DotnetPush.Android/Resources/mipmap-anydpi-v26/logo.xml
  • examples/DotnetPush/DotnetPush.Android/Resources/values/colors.xml
  • examples/DotnetPush/DotnetPush.Android/Resources/values/styles.xml
  • examples/DotnetPush/DotnetPush.iOS/AppDelegate.cs
  • examples/DotnetPush/DotnetPush.iOS/Application.cs
  • examples/DotnetPush/DotnetPush.iOS/Assets.xcassets/AppIcon.appiconset/Contents.json
  • examples/DotnetPush/DotnetPush.iOS/DotnetPush.iOS.csproj
  • examples/DotnetPush/DotnetPush.iOS/Entitlements.plist
  • examples/DotnetPush/DotnetPush.iOS/Info.plist
  • examples/DotnetPush/DotnetPush.iOS/Properties/AssemblyInfo.cs
  • examples/DotnetPush/DotnetPush.iOS/Resources/LaunchScreen.storyboard
  • examples/DotnetPush/DotnetPush/AblySettings.cs
  • examples/DotnetPush/DotnetPush/App.xaml
  • examples/DotnetPush/DotnetPush/App.xaml.cs
  • examples/DotnetPush/DotnetPush/AppLoggerSink.cs
  • examples/DotnetPush/DotnetPush/AppShell.xaml
  • examples/DotnetPush/DotnetPush/AppShell.xaml.cs
  • examples/DotnetPush/DotnetPush/AssemblyInfo.cs
  • examples/DotnetPush/DotnetPush/DotnetPush.csproj
  • examples/DotnetPush/DotnetPush/GettingStarted.txt
  • examples/DotnetPush/DotnetPush/Infrastructure/Helpers.cs
  • examples/DotnetPush/DotnetPush/Models/AblyChannel.cs
  • examples/DotnetPush/DotnetPush/Models/LogEntry.cs
  • examples/DotnetPush/DotnetPush/Models/StateModel.cs
  • examples/DotnetPush/DotnetPush/PushNotificationReceiver.cs
  • examples/DotnetPush/DotnetPush/ViewModels/BaseViewModel.cs
  • examples/DotnetPush/DotnetPush/ViewModels/ChannelsViewModel.cs
  • examples/DotnetPush/DotnetPush/ViewModels/LogViewModel.cs
  • examples/DotnetPush/DotnetPush/ViewModels/NotificationsModel.cs
  • examples/DotnetPush/DotnetPush/ViewModels/StateViewModel.cs
  • examples/DotnetPush/DotnetPush/ViewModels/SubscribeViewModel.cs
  • examples/DotnetPush/DotnetPush/Views/ChannelsPage.xaml
  • examples/DotnetPush/DotnetPush/Views/ChannelsPage.xaml.cs
  • examples/DotnetPush/DotnetPush/Views/LogPage.xaml
  • examples/DotnetPush/DotnetPush/Views/LogPage.xaml.cs
  • examples/DotnetPush/DotnetPush/Views/NotificationsPage.xaml
  • examples/DotnetPush/DotnetPush/Views/NotificationsPage.xaml.cs
  • examples/DotnetPush/DotnetPush/Views/StatePage.xaml
  • examples/DotnetPush/DotnetPush/Views/StatePage.xaml.cs
  • examples/DotnetPush/DotnetPush/Views/SubscribePage.xaml
  • examples/DotnetPush/DotnetPush/Views/SubscribePage.xaml.cs
  • examples/DotnetPush/Readme.md
  • examples/NotificationsPublisher/AppLogger.cs
  • examples/NotificationsPublisher/NotificationsPublisher.csproj
  • examples/NotificationsPublisher/Program.cs
  • nuget.config
  • nuget/ably.pubsub.core.nuspec
  • nuget/ably.pubsub.device.nuspec
  • nuget/ably.pubsub.server.nuspec
  • nuget/io.ably.nuspec
  • nuget/io.ably.push.android.nuspec
  • nuget/io.ably.push.ios.nuspec
  • package-push.cmd
  • package-push.sh
  • package-unity.sh
  • package.cmd
  • src/Ably.PubSub.Core.NETFramework/Ably.PubSub.Core.NETFramework.csproj
  • src/Ably.PubSub.Core.NETFramework/IO.Ably.snk
  • src/Ably.PubSub.Core.NETFramework/Platform.cs
  • src/Ably.PubSub.Core.NETFramework/Properties/AssemblyInfo.cs
  • src/Ably.PubSub.Core.NETFramework/app.config
  • src/Ably.PubSub.Core.NETFramework/packages.config
  • src/Ably.PubSub.Core/Ably.PubSub.Core.csproj
  • src/Ably.PubSub.Core/Platform.cs
  • src/Ably.PubSub.Core/Properties/AssemblyInfo.cs
  • src/Ably.PubSub.Device/Ably.PubSub.Device.csproj
  • src/Ably.PubSub.Device/PubSubDevice.cs
  • src/Ably.PubSub.NetFramework.sln
  • src/Ably.PubSub.NetStandard.sln
  • src/Ably.PubSub.Package.sln
  • src/Ably.PubSub.Server.NETFramework/Ably.PubSub.Server.NETFramework.csproj
  • src/Ably.PubSub.Server.NETFramework/Properties/AssemblyInfo.cs
  • src/Ably.PubSub.Server.NETFramework/packages.config
  • src/Ably.PubSub.Server/Ably.PubSub.Server.csproj
  • src/Ably.PubSub.Server/PubSubServer.cs
  • src/Ably.PubSub.Shared.MsgPack/Ably.PubSub.Shared.MsgPack.projitems
  • src/Ably.PubSub.Shared.MsgPack/Ably.PubSub.Shared.MsgPack.shproj
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/CapabilityMessagePackSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/DateTimeOffsetMessagePackSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_Auth_TokenDetailsSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_CapabilitySerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_ConnectionDetailsMessageSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_ConnectionTypesSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_ErrorInfoSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_InboundMessageTrafficSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_MessageCountSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_MessageSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_MessageTypesSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_OutboundMessageTrafficSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_PresenceMessageSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_PresenceMessage_ActionTypeSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_RequestCountSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_ResourceCountSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_StatsSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_TokenRequestSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_Types_ProtocolMessageSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/IO_Ably_Types_ProtocolMessage_MessageActionSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/GeneratedSerializers/System_Net_HttpStatusCodeSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/CustomSerialisers/TimespanMessagePackSerializer.cs
  • src/Ably.PubSub.Shared.MsgPack/MsgPackHelper.cs
  • src/Ably.PubSub.Shared/Ably.PubSub.Shared.projitems
  • src/Ably.PubSub.Shared/Ably.PubSub.Shared.shproj
  • src/Ably.PubSub.Shared/AblyAuth.cs
  • src/Ably.PubSub.Shared/AblyException.cs
  • src/Ably.PubSub.Shared/AblyInsecureRequestException.cs
  • src/Ably.PubSub.Shared/Agent.cs
  • src/Ably.PubSub.Shared/ApiKey.cs
  • src/Ably.PubSub.Shared/AsyncHelper.cs
  • src/Ably.PubSub.Shared/AuthMethod.cs
  • src/Ably.PubSub.Shared/AuthOptions.cs
  • src/Ably.PubSub.Shared/Capability.cs
  • src/Ably.PubSub.Shared/CapabilityResource.cs
  • src/Ably.PubSub.Shared/CipherParams.cs
  • src/Ably.PubSub.Shared/ClientOptions.cs
  • src/Ably.PubSub.Shared/CustomSerialisers/CapabilityJsonConverter.cs
  • src/Ably.PubSub.Shared/CustomSerialisers/DateTimeOffsetJsonConverter.cs
  • src/Ably.PubSub.Shared/CustomSerialisers/MessageDataConverter.cs
  • src/Ably.PubSub.Shared/CustomSerialisers/MessageExtrasConverter.cs
  • src/Ably.PubSub.Shared/CustomSerialisers/TimeSpanJsonConverter.cs
  • src/Ably.PubSub.Shared/DataRequestQuery.cs
  • src/Ably.PubSub.Shared/DefaultLogger.cs
  • src/Ably.PubSub.Shared/DefaultLoggerSink.cs
  • src/Ably.PubSub.Shared/Defaults.cs
  • src/Ably.PubSub.Shared/Encryption/AesCipher.cs
  • src/Ably.PubSub.Shared/Encryption/Crypto.cs
  • src/Ably.PubSub.Shared/EventEmitter.cs
  • src/Ably.PubSub.Shared/Extensions/ChannelModeExtensions.cs
  • src/Ably.PubSub.Shared/Extensions/DateExtensions.cs
  • src/Ably.PubSub.Shared/Extensions/DictionaryExtensions.cs
  • src/Ably.PubSub.Shared/Extensions/EnumerableExtensions.cs
  • src/Ably.PubSub.Shared/Extensions/ObjectExtensions.cs
  • src/Ably.PubSub.Shared/Extensions/PresenceExtensions.cs
  • src/Ably.PubSub.Shared/Extensions/StringExtensions.cs
  • src/Ably.PubSub.Shared/Extensions/TaskExtensions.cs
  • src/Ably.PubSub.Shared/Extensions/UriExtensions.cs
  • src/Ably.PubSub.Shared/Http/AblyHttpOptions.cs
  • src/Ably.PubSub.Shared/Http/AblyHttpRequester.cs
  • src/Ably.PubSub.Shared/Http/AblyRequest.cs
  • src/Ably.PubSub.Shared/Http/AblyResponse.cs
  • src/Ably.PubSub.Shared/Http/ChannelDetails.cs
  • src/Ably.PubSub.Shared/Http/ChannelOptions.cs
  • src/Ably.PubSub.Shared/Http/HttpChannel.cs
  • src/Ably.PubSub.Shared/Http/HttpChannels.cs
  • src/Ably.PubSub.Shared/Http/IHttpChannel.cs
  • src/Ably.PubSub.Shared/HttpPaginatedResponse.cs
  • src/Ably.PubSub.Shared/HttpUtility.cs
  • src/Ably.PubSub.Shared/IAblyAuth.cs
  • src/Ably.PubSub.Shared/IAblyHttpRequester.cs
  • src/Ably.PubSub.Shared/IChannelCipher.cs
  • src/Ably.PubSub.Shared/IChannels.cs
  • src/Ably.PubSub.Shared/IInternalLogger.cs
  • src/Ably.PubSub.Shared/ILogger.cs
  • src/Ably.PubSub.Shared/ILoggerSink.cs
  • src/Ably.PubSub.Shared/IPlatform.cs
  • src/Ably.PubSub.Shared/IPubSubHttpClient.cs
  • src/Ably.PubSub.Shared/IPubSubRealtimeClient.cs
  • src/Ably.PubSub.Shared/InternalLogger.cs
  • src/Ably.PubSub.Shared/IoC.cs
  • src/Ably.PubSub.Shared/JsonHelper.cs
  • src/Ably.PubSub.Shared/MessageEncoders/Base64Encoder.cs
  • src/Ably.PubSub.Shared/MessageEncoders/CipherEncoder.cs
  • src/Ably.PubSub.Shared/MessageEncoders/DecodingContext.cs
  • src/Ably.PubSub.Shared/MessageEncoders/JsonEncoder.cs
  • src/Ably.PubSub.Shared/MessageEncoders/MessageEncoder.cs
  • src/Ably.PubSub.Shared/MessageEncoders/MessageHandler.cs
  • src/Ably.PubSub.Shared/MessageEncoders/PayloadCache.cs
  • src/Ably.PubSub.Shared/MessageEncoders/ProcessedPayload.cs
  • src/Ably.PubSub.Shared/MessageEncoders/Utf8Encoder.cs
  • src/Ably.PubSub.Shared/MessageEncoders/VCDiffEncoder.cs
  • src/Ably.PubSub.Shared/MessageEncoders/VcDiffErrorInfo.cs
  • src/Ably.PubSub.Shared/PaginatedRequestParams.cs
  • src/Ably.PubSub.Shared/PaginatedResult.cs
  • src/Ably.PubSub.Shared/Protocol.cs
  • src/Ably.PubSub.Shared/PubSubHttpClient.cs
  • src/Ably.PubSub.Shared/PubSubRealtimeClient.cs
  • src/Ably.PubSub.Shared/Push/ActivationStateMachine.Events.cs
  • src/Ably.PubSub.Shared/Push/ActivationStateMachine.States.cs
  • src/Ably.PubSub.Shared/Push/ActivationStateMachine.cs
  • src/Ably.PubSub.Shared/Push/DeviceDetails.cs
  • src/Ably.PubSub.Shared/Push/DeviceFormFactor.cs
  • src/Ably.PubSub.Shared/Push/IDeviceRegistrations.cs
  • src/Ably.PubSub.Shared/Push/IMobileDevice.cs
  • src/Ably.PubSub.Shared/Push/IPushChannelSubscriptions.cs
  • src/Ably.PubSub.Shared/Push/ListDeviceDetailsRequest.cs
  • src/Ably.PubSub.Shared/Push/ListSubscriptionsRequest.cs
  • src/Ably.PubSub.Shared/Push/LocalDevice.cs
  • src/Ably.PubSub.Shared/Push/PersistKeys.cs
  • src/Ably.PubSub.Shared/Push/PushAdmin.cs
  • src/Ably.PubSub.Shared/Push/PushCallbacks.cs
  • src/Ably.PubSub.Shared/Push/PushChannel.cs
  • src/Ably.PubSub.Shared/Push/PushChannelSubscription.cs
  • src/Ably.PubSub.Shared/Push/PushHttp.cs
  • src/Ably.PubSub.Shared/Push/PushRealtime.cs
  • src/Ably.PubSub.Shared/Push/RegistrationToken.cs
  • src/Ably.PubSub.Shared/QueryDirection.cs
  • src/Ably.PubSub.Shared/Realtime/AttemptsHelpers.cs
  • src/Ably.PubSub.Shared/Realtime/ChannelAwaiter.cs
  • src/Ably.PubSub.Shared/Realtime/ChannelErrorEventArgs.cs
  • src/Ably.PubSub.Shared/Realtime/ChannelEvent.cs
  • src/Ably.PubSub.Shared/Realtime/ChannelMessageProcessor.cs
  • src/Ably.PubSub.Shared/Realtime/ChannelProperties.cs
  • src/Ably.PubSub.Shared/Realtime/ChannelState.cs
  • src/Ably.PubSub.Shared/Realtime/ChannelStateChangedEventArgs.cs
  • src/Ably.PubSub.Shared/Realtime/Connection.cs
  • src/Ably.PubSub.Shared/Realtime/ConnectionEvent.cs
  • src/Ably.PubSub.Shared/Realtime/ConnectionState.cs
  • src/Ably.PubSub.Shared/Realtime/ConnectionStateChangedEventArgs.cs
  • src/Ably.PubSub.Shared/Realtime/Handlers.cs
  • src/Ably.PubSub.Shared/Realtime/IRealtimeChannel.cs
  • src/Ably.PubSub.Shared/Realtime/LastMessageIds.cs
  • src/Ably.PubSub.Shared/Realtime/MessageHandlerAction.cs
  • src/Ably.PubSub.Shared/Realtime/Presence.GetParams.cs
  • src/Ably.PubSub.Shared/Realtime/Presence.QueuedPresenceMessage.cs
  • src/Ably.PubSub.Shared/Realtime/Presence.cs
  • src/Ably.PubSub.Shared/Realtime/PresenceMap.cs
  • src/Ably.PubSub.Shared/Realtime/RealtimeChannel.cs
  • src/Ably.PubSub.Shared/Realtime/RealtimeChannels.cs
  • src/Ably.PubSub.Shared/Realtime/RealtimeTransportData.cs
  • src/Ably.PubSub.Shared/Realtime/RecoveryKeyContext.cs
  • src/Ably.PubSub.Shared/Realtime/Workflows/ChannelCommands.cs
  • src/Ably.PubSub.Shared/Realtime/Workflows/IQueueCommand.cs
  • src/Ably.PubSub.Shared/Realtime/Workflows/PingRequest.cs
  • src/Ably.PubSub.Shared/Realtime/Workflows/RealtimeCommand.cs
  • src/Ably.PubSub.Shared/Realtime/Workflows/RealtimeCommands.cs
  • src/Ably.PubSub.Shared/Realtime/Workflows/RealtimeState.cs
  • src/Ably.PubSub.Shared/Realtime/Workflows/RealtimeWorkflow.cs
  • src/Ably.PubSub.Shared/Result.cs
  • src/Ably.PubSub.Shared/Statistics.cs
  • src/Ably.PubSub.Shared/TaskConstants.cs
  • src/Ably.PubSub.Shared/TokenDetails.cs
  • src/Ably.PubSub.Shared/TokenParams.cs
  • src/Ably.PubSub.Shared/TokenRequest.cs
  • src/Ably.PubSub.Shared/TokenResponse.cs
  • src/Ably.PubSub.Shared/Transport/AttemptFailedState.cs
  • src/Ably.PubSub.Shared/Transport/ConnectionAttempt.cs
  • src/Ably.PubSub.Shared/Transport/ConnectionAttemptsInfo.cs
  • src/Ably.PubSub.Shared/Transport/ConnectionHeartbeatHandler.cs
  • src/Ably.PubSub.Shared/Transport/ConnectionInfo.cs
  • src/Ably.PubSub.Shared/Transport/ConnectionManager.cs
  • src/Ably.PubSub.Shared/Transport/IConnectionContext.cs
  • src/Ably.PubSub.Shared/Transport/IConnectionManager.cs
  • src/Ably.PubSub.Shared/Transport/ITransport.cs
  • src/Ably.PubSub.Shared/Transport/MessageAndCallback.cs
  • src/Ably.PubSub.Shared/Transport/MsWebSocketConnection.cs
  • src/Ably.PubSub.Shared/Transport/MsWebSocketTransport.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ConnectionClosedState.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ConnectionClosingState.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ConnectionConnectedState.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ConnectionConnectingState.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ConnectionDisconnectedState.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ConnectionFailedState.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ConnectionInitializedState.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ConnectionStateBase.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ConnectionSuspendedState.cs
  • src/Ably.PubSub.Shared/Transport/States/Connection/ICountdownTimer.cs
  • src/Ably.PubSub.Shared/Transport/TaskWrapper.cs
  • src/Ably.PubSub.Shared/Transport/TransportParams.cs
  • src/Ably.PubSub.Shared/Types/AuthDetails.cs
  • src/Ably.PubSub.Shared/Types/ChannelModes.cs
  • src/Ably.PubSub.Shared/Types/ChannelParams.cs
  • src/Ably.PubSub.Shared/Types/ConnectionDetails.cs
  • src/Ably.PubSub.Shared/Types/ErrorCodes.cs
  • src/Ably.PubSub.Shared/Types/ErrorInfo.cs
  • src/Ably.PubSub.Shared/Types/IMessage.cs
  • src/Ably.PubSub.Shared/Types/LockedList.cs
  • src/Ably.PubSub.Shared/Types/Message.cs
  • src/Ably.PubSub.Shared/Types/MessageExtras.cs
  • src/Ably.PubSub.Shared/Types/OperatingSystem.cs
  • src/Ably.PubSub.Shared/Types/PresenceMessage.cs
  • src/Ably.PubSub.Shared/Types/ProtocolMessage.cs
  • src/Ably.PubSub.Shared/Types/SemanticVersion.cs
  • src/Ably.PubSub.Shared/Unity/UnityAdapter.cs
  • src/Ably.PubSub.Shared/Unity/UnityHelper.cs
  • src/Ably.PubSub.Shared/Utils/ActionOnDispose.cs
  • src/Ably.PubSub.Shared/Utils/ActionUtils.cs
  • src/Ably.PubSub.Shared/Utils/ConnectionChangeAwaiter.cs
  • src/Ably.PubSub.Shared/Utils/ErrorPolicy.cs
  • src/Ably.PubSub.Shared/Utils/ReconnectionStrategy.cs
  • src/Ably.PubSub.Shared/Utils/StringUtils.cs
  • src/Ably.PubSub.Shared/Utils/TaskUtils.cs
  • src/Ably.PubSub.Side/Side.cs
  • src/Ably.PubSub.Tests.DotNET/Ably.PubSub.Tests.DotNET.csproj
  • src/Ably.PubSub.Tests.DotNET/MsgPackStatsTest.json
  • src/Ably.PubSub.Tests.DotNET/PubSub/ClientOptionsCloneSpecs.cs
  • src/Ably.PubSub.Tests.DotNET/PubSub/PackagingSpecs.cs
  • src/Ably.PubSub.Tests.DotNET/PubSub/PubSubDoorSandboxSpecs.cs
  • src/Ably.PubSub.Tests.DotNET/PubSub/PubSubPackageSpecs.cs
  • src/Ably.PubSub.Tests.DotNET/StatsFixture.json
  • src/Ably.PubSub.Tests.DotNET/StatsInterval.json
  • src/Ably.PubSub.Tests.DotNET/xunit.runner.json
  • src/Ably.PubSub.Tests.NETFramework/Ably.PubSub.Tests.NETFramework.csproj
  • src/Ably.PubSub.Tests.NETFramework/App.config
  • src/Ably.PubSub.Tests.NETFramework/MsgPackStatsTest.json
  • src/Ably.PubSub.Tests.NETFramework/Properties/AssemblyInfo.cs
  • src/Ably.PubSub.Tests.NETFramework/StatsFixture.json
  • src/Ably.PubSub.Tests.NETFramework/StatsInterval.json
  • src/Ably.PubSub.Tests.Shared/Ably.PubSub.Tests.Shared.projitems
  • src/Ably.PubSub.Tests.Shared/Ably.PubSub.Tests.Shared.shproj
  • src/Ably.PubSub.Tests.Shared/AblyInsecureRequestExceptionTests.cs
  • src/Ably.PubSub.Tests.Shared/AblyResponseTests.cs
  • src/Ably.PubSub.Tests.Shared/AgentTests.cs
  • src/Ably.PubSub.Tests.Shared/ApiKeyTests.cs
  • src/Ably.PubSub.Tests.Shared/AuthTests/AuthOptionsTests.cs
  • src/Ably.PubSub.Tests.Shared/AuthTests/AuthSandboxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/AuthTests/AuthorizationTests.cs
  • src/Ably.PubSub.Tests.Shared/AuthTests/AuthorizeTests.cs
  • src/Ably.PubSub.Tests.Shared/AuthTests/RequestTokenSpecs.cs
  • src/Ably.PubSub.Tests.Shared/AuthTests/ServerTimeTests.cs
  • src/Ably.PubSub.Tests.Shared/AuthTests/TestAblyAuth.cs
  • src/Ably.PubSub.Tests.Shared/CapabilityTests.cs
  • src/Ably.PubSub.Tests.Shared/CipherParamsTests.cs
  • src/Ably.PubSub.Tests.Shared/ClientOptionsTests.cs
  • src/Ably.PubSub.Tests.Shared/CustomSerializers/DateTimeOffsetConverterTests.cs
  • src/Ably.PubSub.Tests.Shared/CustomSerializers/MessageDataConverterTests.cs
  • src/Ably.PubSub.Tests.Shared/CustomSerializers/MessageExtrasConverterTests.cs
  • src/Ably.PubSub.Tests.Shared/DataRequestQueryParseTests.cs
  • src/Ably.PubSub.Tests.Shared/DataRequestQueryTests.cs
  • src/Ably.PubSub.Tests.Shared/DateHelper.cs
  • src/Ably.PubSub.Tests.Shared/DefaultTests.cs
  • src/Ably.PubSub.Tests.Shared/EncryptionSpecs.cs
  • src/Ably.PubSub.Tests.Shared/ErrorInfoTests.cs
  • src/Ably.PubSub.Tests.Shared/Extensions/ChannelOptionsExtensions.cs
  • src/Ably.PubSub.Tests.Shared/Extensions/StringExtensionsTests.cs
  • src/Ably.PubSub.Tests.Shared/Helpers/JAssert.cs
  • src/Ably.PubSub.Tests.Shared/Helpers/JDiff.cs
  • src/Ably.PubSub.Tests.Shared/Http/AblyHttpRequesterSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/ChannelOptionsDefaultsTests.cs
  • src/Ably.PubSub.Tests.Shared/Http/ChannelSandboxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/ChannelSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/HttpInitSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/HttpSandBoxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/HttpSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/JwtSandboxSpec.cs
  • src/Ably.PubSub.Tests.Shared/Http/MockHttpRestSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/PresenceSandboxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/PresenceSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/RequestSandBoxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/SandboxSpecExtension.cs
  • src/Ably.PubSub.Tests.Shared/Http/SandboxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/StatsSandBoxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/StatsSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Http/TM3Spec.cs
  • src/Ably.PubSub.Tests.Shared/HttpProtocolTests.cs
  • src/Ably.PubSub.Tests.Shared/ImplicitTokenAuthWithClientId.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/AblyCollectionFixture.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/AblyRealtimeSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/AblySandboxFixture.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/AblySpecs.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/ConditionalAwaiter.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/ConnectionAwaiter.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/FakeConnectionContext.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/FakeHttpMessageHandler.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/FakeTimer.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/FakeTransport.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/FakeTransportFactory.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/InteroperabilityMessagePayloadDataAttribute.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/MiscUtils.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/Now.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/NowTests.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/ProtocolDataAttribute.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/ResourceHelper.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TaskCompleterAwaiterTests.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TaskCompletionAwaiter.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TaskCountAwaiter.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TestExtensions.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TestHelpers.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TestLogger.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TestTransportFactory.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TestTransportWrapper.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TimeoutCallback.cs
  • src/Ably.PubSub.Tests.Shared/Infrastructure/TimeoutCallbackTests.cs
  • src/Ably.PubSub.Tests.Shared/JsonMessageSerializerTests.cs
  • src/Ably.PubSub.Tests.Shared/LoggerTests.cs
  • src/Ably.PubSub.Tests.Shared/MessageEncodes/Base64EncoderTests.cs
  • src/Ably.PubSub.Tests.Shared/MessageEncodes/CipherEncoderTests.cs
  • src/Ably.PubSub.Tests.Shared/MessageEncodes/JsonEncoderTests.cs
  • src/Ably.PubSub.Tests.Shared/MessageEncodes/MessageDecodingAcceptanceTests.cs
  • src/Ably.PubSub.Tests.Shared/MessageEncodes/MessageEncodersAcceptanceTests.cs
  • src/Ably.PubSub.Tests.Shared/MessageEncodes/ProtocolMessageSpecs.cs
  • src/Ably.PubSub.Tests.Shared/MessageEncodes/Utf8EncoderTests.cs
  • src/Ably.PubSub.Tests.Shared/MessagePack/SerializationTests.cs
  • src/Ably.PubSub.Tests.Shared/MsgPackMessageSerializerTests.cs
  • src/Ably.PubSub.Tests.Shared/Push/ActivationStateMachineTests.cs
  • src/Ably.PubSub.Tests.Shared/Push/FakeMobileDevice.cs
  • src/Ably.PubSub.Tests.Shared/Push/ListDeviceDetailsRequestTests.cs
  • src/Ably.PubSub.Tests.Shared/Push/ListSubscriptionsRequestTests.cs
  • src/Ably.PubSub.Tests.Shared/Push/LocalDeviceTests.cs
  • src/Ably.PubSub.Tests.Shared/Push/PushAdminSandboxTests.cs
  • src/Ably.PubSub.Tests.Shared/Push/PushAdminTests.cs
  • src/Ably.PubSub.Tests.Shared/Push/PushChannelTests.cs
  • src/Ably.PubSub.Tests.Shared/Push/PushRealtimeTests.cs
  • src/Ably.PubSub.Tests.Shared/Push/PushTestHelpers.cs
  • src/Ably.PubSub.Tests.Shared/Push/RegistrationTokenTest.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ChannelSandboxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ChannelSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ChannelsSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionAttemptsInfoSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSandBoxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSandboxOperatingSystemEventsForNetworkSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSandboxTransportSideEffectsSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/AblyRealtimeTestExtensions.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/ConnectionFailureSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/ConnectionFailuresOnceConnectedSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/ConnectionFallbackSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/ConnectionIdSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/ConnectionKeySpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/ConnectionParameterSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/ConnectionPingSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/ConnectionRecoverySpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/EventEmitterSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionSpecs/GeneralConnectionSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionStateTests/ClosedStateSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionStateTests/ClosingStateSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionStateTests/ConnectedStateSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionStateTests/ConnectingStateSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionStateTests/DisconnectedStateSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionStateTests/FailedStateSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionStateTests/InitializedStateSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ConnectionStateTests/SuspendedStateSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/CountDownTimerSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/DeltaLastMessageSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/DeltaSandboxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/DeltaSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ExtraSandboxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/MockHttpRealtimeSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/PresenceSandboxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/ProtocolMessageTests.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/RealtimeSandboxSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/RealtimeSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/RealtimeWorkflowSpecs.cs
  • src/Ably.PubSub.Tests.Shared/Realtime/RecoveryKeyContextSpec.cs
  • src/Ably.PubSub.Tests.Shared/Samples/DocumentationSamples.cs
  • src/Ably.PubSub.Tests.Shared/Samples/RealtimeSamples.cs
  • src/Ably.PubSub.Tests.Shared/StatsParsingTests.cs
  • src/Ably.PubSub.Tests.Shared/TestExtensions.cs
  • src/Ably.PubSub.Tests.Shared/TestLoggerSink.cs
  • src/Ably.PubSub.Tests.Shared/TokenDetailsTests.cs
  • src/Ably.PubSub.Tests.Shared/TokenParamsTests.cs
  • src/Ably.PubSub.Tests.Shared/TokenRequestPopulateTests.cs
  • src/Ably.PubSub.Tests.Shared/Transport/AttemptFailedStateTests.cs
  • src/Ably.PubSub.Tests.Shared/Transport/ConnectionAttemptTests.cs
  • src/Ably.PubSub.Tests.Shared/Types/OperatingSystemTests.cs
  • src/Ably.PubSub.Tests.Shared/Types/SemanticVersionTests.cs
  • src/Ably.PubSub.Tests.Shared/Utils/ErrorPolicyTests.cs
  • src/Ably.PubSub.Tests.Shared/Utils/ReconnectionStrategyTest.cs
  • src/Ably.PubSub.Tests.Shared/delta-test-messages/1
  • src/Ably.PubSub.Tests.Shared/delta-test-messages/1.vcdiff
  • src/Ably.PubSub.Tests.Shared/delta-test-messages/2
  • src/Ably.PubSub.Tests.Shared/delta-test-messages/2.vcdiff
  • src/Ably.PubSub.Tests.Shared/delta-test-messages/3
  • src/Ably.PubSub.Tests.Shared/delta-test-messages/3.vcdiff
  • src/Ably.PubSub.Tests.Shared/delta-test-messages/4
  • src/Ably.PubSub.sln
  • src/Ably.PubSub/CustomSerialisers/GeneratedSerializers/IO/Ably/CustomSerialisers/IO_Ably_CapabilityResourceSerializer.cs
  • src/Ably.PubSub/CustomSerialisers/GeneratedSerializers/IO/Ably/CustomSerialisers/IO_Ably_CapabilitySerializer.cs
  • src/Ably.PubSub/CustomSerialisers/GeneratedSerializers/IO/Ably/CustomSerialisers/IO_Ably_TokenRequestSerializer.cs
  • src/CommonAssemblyInfo.cs
  • src/IO.Ably.Android/IO.Ably.Android.csproj
  • src/IO.Ably.Android/Platform.cs
  • src/IO.Ably.Android/Properties/AssemblyInfo.cs
  • src/IO.Ably.Android/Resources/Resource.Designer.cs
  • src/IO.Ably.Android/app.config
  • src/IO.Ably.Android/packages.config
  • src/IO.Ably.DotNetPush.sln
  • src/IO.Ably.NETStandard20/Properties/AssemblyInfo.cs
  • src/IO.Ably.PackagePush.sln
  • src/IO.Ably.Push.Android/AndroidMobileDevice.cs
  • src/IO.Ably.Push.Android/IO.Ably.Push.Android.csproj
  • src/IO.Ably.Push.Android/IO.Ably.snk
  • src/IO.Ably.Push.Android/Properties/AssemblyInfo.cs
  • src/IO.Ably.Push.Android/Resources/AboutResources.txt
  • src/IO.Ably.Push.Android/Resources/Resource.Designer.cs
  • src/IO.Ably.Push.Android/Resources/values/strings.xml
  • src/IO.Ably.Push.Android/packages.config
  • src/IO.Ably.Push.iOS/AppleMobileDevice.cs
  • src/IO.Ably.Push.iOS/IO.Ably.Push.iOS.csproj
  • src/IO.Ably.Push.iOS/IO.Ably.snk
  • src/IO.Ably.Push.iOS/Properties/AssemblyInfo.cs
  • src/IO.Ably.Push.iOS/packages.config
  • src/IO.Ably.Tests.Shared/Infrastructure/TestExtensions.cs
  • src/IO.Ably.Xamarin.sln
  • src/IO.Ably.iOS/IO.Ably.iOS.csproj
  • src/IO.Ably.iOS/IO.Ably.snk
  • src/IO.Ably.iOS/Platform.cs
  • src/IO.Ably.iOS/Properties/AssemblyInfo.cs
  • src/IO.Ably.iOS/packages.config
  • src/IO.Ably.ruleset
  • tools/list-test-categories.fsx
  • unity-plugins-updater.cmd
  • unity-plugins-updater.sh
  • unity/Assets/Ably/Examples/Dashboard/AblyChannel.cs
  • unity/Assets/Ably/Examples/Dashboard/AblyMain.cs
  • unity/Assets/Ably/Examples/Dashboard/AblyPresence.cs
  • unity/Assets/Ably/Plugins/Ably.PubSub.Device.dll.meta
  • unity/Assets/Ably/Plugins/link.xml
  • unity/Assets/Ably/version.txt
  • unity/Assets/Tests/AblySandbox/AblyCollectionFixture.cs
  • unity/Assets/Tests/AblySandbox/AblyRealtimeExtensions.cs
  • unity/Assets/Tests/AblySandbox/AblySandbox.asmdef
  • unity/Assets/Tests/AblySandbox/AblySandbox.cs
  • unity/Assets/Tests/AblySandbox/AblySandboxFixture.cs
  • unity/Assets/Tests/AblySandbox/ConnectionAwaiter.cs
  • unity/Assets/Tests/AblySandbox/RealtimeChannelExtensions.cs
  • unity/Assets/Tests/AblySandbox/TestTransportFactory.cs
  • unity/Assets/Tests/AblySandbox/TestTransportWrapper.cs
  • unity/Assets/Tests/AblySandbox/TestUtils.cs
  • unity/Assets/Tests/EditMode/AblyRealtimeSpecs.cs
  • unity/Assets/Tests/EditMode/AuthSpecs.cs
  • unity/Assets/Tests/EditMode/EditMode.asmdef
  • unity/Assets/Tests/EditMode/StatsSpecs.cs
  • unity/Assets/Tests/PlayMode/AblyRealtimeSpecs.cs
  • unity/Assets/Tests/PlayMode/AuthSpecs.cs
  • unity/Assets/Tests/PlayMode/PlayMode.asmdef
  • unity/Assets/Tests/PlayMode/StatsSpecs.cs
  • unity/CONTRIBUTING.md
  • unity/README.md

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The M40 follow-up added an integration/** push trigger to features.yml to
match the six run-tests / release-dry-run workflows, but the Features
workflow is different: it delegates to the reusable ably/features action,
which only runs on a pull_request, a push to main, or a push of a tag, and
hard-fails on any other branch push ("this action can only be ran on a
pull_request, a push to the 'main' branch, or a push of a tag"). So every
push to integration/v2 produced a red Features run.

Remove the integration/** entry from the push branches (leaving main) and
add a comment explaining why this workflow, unlike the plain build/test
workflows, cannot list integration/**. Features coverage on the integration
branch already comes from the open integration/v2 -> main pull request via
the pull_request trigger, which stays in place, so this loses no coverage.

The six run-tests / release-dry-run workflows keep their integration/**
push triggers - they are plain build/test jobs with no such event
restriction.

Validation: features.yml parses; push branches is now [main]; pull_request
trigger retained; the other six workflows still carry integration/**.
The informational-version specs added with the M33 change used
column-alignment whitespace (multiple spaces to line up the [InlineData]
values and their trailing // comments) in DefaultTests.cs. The test
project's ruleset sets SA1025 ("Code should not contain multiple
whitespace characters in a row") to Error, so the CI test build
(_NetStandard_Build, Release) failed with SA1025 at DefaultTests.cs
(48,46), (49,49) and (50,39) before any tests ran. The earlier local
validation missed it because it built the solution in Debug and ran the
tests, rather than the Release build the CI check performs, where the
ruleset elevates SA1025 to an error.

Collapse the alignment whitespace to a single space on the affected
[InlineData] lines; the test data and assertions are unchanged. The
other C# files added in this review pass (ClientOptionsCloneSpecs and
Defaults) were checked and carry no equivalent violation.

Validation: reproduced the failure locally with
`dotnet build src/Ably.PubSub.Tests.DotNET/Ably.PubSub.Tests.DotNET.csproj -c Release`
(SA1025 error, build FAILED) and confirmed this change clears it (build
succeeded, 0 errors); the normalizer and Clone specs pass (9/9).
Document that CI runs through the Cake wrapper, which enforces StyleCop
analyzers as build errors via src/IO.Ably.ruleset and
src/IO.Ably.Tests.ruleset (specific rules such as SA1025 set to
Action=Error; product projects also treat warnings as errors) in the
Release configuration, so a bare dotnet build / IDE build / dotnet test
- especially in Debug, where the test project relaxes analysis - does not
surface these and is not sufficient validation. Recommend running the
Cake target CI runs (Build.NetStandard for build+lint including the test
projects; Test.NetStandard.Unit.WithRetry for the check legs) before
pushing. Also records the StyleCop SA1025 gotcha, EditorConfig rules, and
the integration/v2 no-rewrite branch discipline.

Prompted by a lint failure that passed a local Debug build/test but broke
the CI Cake build.
CLAUDE.md should read as evergreen guidance, not a snapshot of the
current release work. Neutralise the "What this is" section (drop the
"mid-migration to the 2.0 split layout" framing and the reference to the
integration branch; keep the plain package-architecture description) and
remove the rollout-specific branch-discipline section. The durable build
and lint guidance - Cake wrapper, StyleCop-as-error via the rulesets,
Build.NetStandard as the pre-push gate, and the lint gotchas - is
unchanged.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

One or more issues must be addressed before approval.

Review effort: Lite
Findings: None

What changed in this PR

Splits the .NET SDK into a shared core plus device/server door packages, updating Unity integration, packaging, release automation, tests, and documentation.

Changes:

  • Adds device/server package factories and side-specific agent identifiers.
  • Renames assemblies/projects and removes legacy Xamarin/push satellites.
  • Adds lockstep packaging, release verification, and updated examples/tests.
File Description
unity/​README.md Updated as part of this pull request.
unity/​CONTRIBUTING.md Updated as part of this pull request.
unity/​Assets/​Tests/​PlayMode/​PlayMode.asmdef Updated as part of this pull request.
unity/​Assets/​Tests/​PlayMode/​AblyRealtimeSpecs.cs Updated as part of this pull request.
unity/​Assets/​Tests/​EditMode/​EditMode.asmdef Updated as part of this pull request.
unity/​Assets/​Tests/​EditMode/​AblyRealtimeSpecs.cs Updated as part of this pull request.
unity/​Assets/​Tests/​AblySandbox/​AblySandbox.asmdef Updated as part of this pull request.
unity/​Assets/​Ably/​version.txt Updated as part of this pull request.
unity/​Assets/​Ably/​Plugins/​link.xml Updated as part of this pull request.
unity/​Assets/​Ably/​Plugins/​Ably.PubSub.Device.dll.meta Updated as part of this pull request.
unity/​Assets/​Ably/​Examples/​Dashboard/​AblyPresence.cs Updated as part of this pull request.
unity/​Assets/​Ably/​Examples/​Dashboard/​AblyChannel.cs Updated as part of this pull request.
unity-plugins-updater.sh Updated as part of this pull request.
unity-plugins-updater.cmd Updated as part of this pull request.
tools/​list-test-categories.fsx Updated as part of this pull request.
src/​IO.Ably.ruleset Updated as part of this pull request.
src/​IO.Ably.Push.iOS/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
src/​IO.Ably.Push.iOS/​packages.config Updated as part of this pull request.
src/​IO.Ably.Push.Android/​Resources/​values/​strings.xml Updated as part of this pull request.
src/​IO.Ably.Push.Android/​Resources/​AboutResources.txt Updated as part of this pull request.
src/​IO.Ably.Push.Android/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
src/​IO.Ably.iOS/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
src/​IO.Ably.iOS/​Platform.cs Updated as part of this pull request.
src/​IO.Ably.Android/​Resources/​Resource.Designer.cs Updated as part of this pull request.
src/​IO.Ably.Android/​Platform.cs Updated as part of this pull request.
src/​IO.Ably.Android/​app.config Updated as part of this pull request.
src/​CommonAssemblyInfo.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Utils/​ErrorPolicyTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Types/​SemanticVersionTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Types/​OperatingSystemTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Transport/​ConnectionAttemptTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Transport/​AttemptFailedStateTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​TestLoggerSink.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Rest/​PresenceSandboxSpecs.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Rest/​MockHttpRestSpecs.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Rest/​ChannelOptionsDefaultsTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Rest/​AblyHttpClientSpecs.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Realtime/​MockHttpRealtimeSpecs.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Realtime/​ConnectionSpecs/​ConnectionParameterSpecs.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Realtime/​ConnectionSpecs/​ConnectionIdSpecs.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Push/​RegistrationTokenTest.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Push/​PushTestHelpers.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Push/​PushRealtimeTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Push/​ListSubscriptionsRequestTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Push/​FakeMobileDevice.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​MessageEncodes/​ProtocolMessageSpecs.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​TimeoutCallbackTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​TimeoutCallback.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​TestTransportFactory.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​TestHelpers.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​TestExtensions.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​TaskCountAwaiter.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​TaskCompleterAwaiterTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​ResourceHelper.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​ProtocolDataAttribute.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​NowTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​Now.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​MiscUtils.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​InteroperabilityMessagePayloadDataAttribute.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​FakeTransportFactory.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​FakeTimer.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​FakeHttpMessageHandler.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Infrastructure/​AblySpecs.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Helpers/​JAssert.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Extensions/​StringExtensionsTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​DefaultTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​DateHelper.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​CipherParamsTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​AuthTests/​TestAblyAuth.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​ApiKeyTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​AblyResponseTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​AblyInsecureRequestExceptionTests.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Ably.PubSub.Tests.Shared.shproj Updated as part of this pull request.
src/​Ably.PubSub.Tests.Shared/​Ably.PubSub.Tests.Shared.projitems Updated as part of this pull request.
src/​Ably.PubSub.Tests.NETFramework/​StatsFixture.json Updated as part of this pull request.
src/​Ably.PubSub.Tests.NETFramework/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
src/​Ably.PubSub.Tests.NETFramework/​App.config Updated as part of this pull request.
src/​Ably.PubSub.Tests.DotNET/​xunit.runner.json Updated as part of this pull request.
src/​Ably.PubSub.Tests.DotNET/​StatsFixture.json Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Utils/​TaskUtils.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Utils/​ReconnectionStrategy.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Utils/​ErrorPolicy.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Utils/​ConnectionChangeAwaiter.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Utils/​ActionOnDispose.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Types/​OperatingSystem.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Types/​LockedList.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Types/​IMessage.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Types/​ChannelParams.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Types/​AuthDetails.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Transport/​States/​Connection/​ConnectionInitializedState.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Transport/​States/​Connection/​ConnectionFailedState.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Transport/​States/​Connection/​ConnectionClosedState.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Transport/​IConnectionManager.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Transport/​IConnectionContext.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Transport/​ConnectionAttempt.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​TokenResponse.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​Workflows/​RealtimeCommand.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​Workflows/​PingRequest.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​Workflows/​IQueueCommand.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​Workflows/​ChannelCommands.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​RecoveryKeyContext.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​Presence.QueuedPresenceMessage.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​Presence.GetParams.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​LastMessageIds.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​ConnectionEvent.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​ChannelProperties.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Realtime/​ChannelErrorEventArgs.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​QueryDirection.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Push/​RegistrationToken.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Push/​PushRest.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Push/​PushCallbacks.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Push/​PersistKeys.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Push/​DeviceFormFactor.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Protocol.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​MessageEncoders/​VcDiffErrorInfo.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​MessageEncoders/​Utf8Encoder.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​MessageEncoders/​ProcessedPayload.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​MessageEncoders/​MessageEncoder.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​MessageEncoders/​DecodingContext.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​MessageEncoders/​Base64Encoder.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​IPlatform.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​IoC.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​ILoggerSink.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​ILogger.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​IInternalLogger.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​IChannelCipher.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​IAblyHttpClient.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Extensions/​UriExtensions.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Extensions/​StringExtensions.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Extensions/​PresenceExtensions.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Extensions/​ObjectExtensions.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Extensions/​ChannelModeExtensions.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Defaults.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​DefaultLoggerSink.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​CustomSerialisers/​MessageExtrasConverter.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​CustomSerialisers/​MessageDataConverter.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​CustomSerialisers/​DateTimeOffsetJsonConverter.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​CustomSerialisers/​CapabilityJsonConverter.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​AuthMethod.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​AsyncHelper.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Agent.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​AblyInsecureRequestException.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Ably.PubSub.Shared.shproj Updated as part of this pull request.
src/​Ably.PubSub.Shared/​Ably.PubSub.Shared.projitems Updated as part of this pull request.
src/​Ably.PubSub.Shared.MsgPack/​CustomSerialisers/​TimespanMessagePackSerializer.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared.MsgPack/​CustomSerialisers/​DateTimeOffsetMessagePackSerializer.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared.MsgPack/​CustomSerialisers/​CapabilityMessagePackSerializer.cs Updated as part of this pull request.
src/​Ably.PubSub.Shared.MsgPack/​Ably.PubSub.Shared.MsgPack.shproj Updated as part of this pull request.
src/​Ably.PubSub.Shared.MsgPack/​Ably.PubSub.Shared.MsgPack.projitems Updated as part of this pull request.
src/​Ably.PubSub.Server.NETFramework/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
src/​Ably.PubSub.Server.NETFramework/​packages.config Updated as part of this pull request.
src/​Ably.PubSub.Core/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
src/​Ably.PubSub.Core.NETFramework/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
src/​Ably.PubSub.Core.NETFramework/​Platform.cs Updated as part of this pull request.
src/​Ably.PubSub.Core.NETFramework/​packages.config Updated as part of this pull request.
src/​Ably.PubSub.Core.NETFramework/​IO.Ably.snk Updated as part of this pull request.
src/​Ably.PubSub.Core.NETFramework/​app.config Updated as part of this pull request.
PushNotifications.md Updated as part of this pull request.
package.cmd Updated as part of this pull request.
package-unity.sh Updated as part of this pull request.
package-push.sh Updated as part of this pull request.
package-push.cmd Updated as part of this pull request.
nuget/​io.ably.push.ios.nuspec Updated as part of this pull request.
nuget.config Updated as part of this pull request.
examples/​NotificationsPublisher/​Program.cs Updated as part of this pull request.
examples/​NotificationsPublisher/​NotificationsPublisher.csproj Updated as part of this pull request.
examples/​DotnetPush/​Readme.md Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​Views/​SubscribePage.xaml.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​Views/​StatePage.xaml.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​Views/​NotificationsPage.xaml.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​Views/​NotificationsPage.xaml Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​Views/​LogPage.xaml.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​Views/​LogPage.xaml Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​Views/​ChannelsPage.xaml.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​ViewModels/​SubscribeViewModel.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​ViewModels/​NotificationsModel.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​PushNotificationReceiver.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​Models/​AblyChannel.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​Infrastructure/​Helpers.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​GettingStarted.txt Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​AssemblyInfo.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​AppShell.xaml.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​AppLoggerSink.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​App.xaml.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​App.xaml Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush/​AblySettings.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.iOS/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.iOS/​Info.plist Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.iOS/​Entitlements.plist Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.iOS/​Application.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.Android/​Resources/​values/​styles.xml Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.Android/​Resources/​values/​colors.xml Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.Android/​Resources/​mipmap-anydpi-v26/​logo.xml Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.Android/​Resources/​mipmap-anydpi-v26/​icon.xml Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.Android/​Resources/​mipmap-anydpi-v26/​icon_round.xml Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.Android/​Resources/​AboutResources.txt Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.Android/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.Android/​Properties/​AndroidManifest.xml Updated as part of this pull request.
examples/​DotnetPush/​DotnetPush.Android/​Assets/​AboutAssets.txt Updated as part of this pull request.
examples/​AndroidSample/​Resources/​values/​styles.xml Updated as part of this pull request.
examples/​AndroidSample/​Resources/​values/​Strings.xml Updated as part of this pull request.
examples/​AndroidSample/​Resources/​layout/​Toolbar.axml Updated as part of this pull request.
examples/​AndroidSample/​Resources/​layout/​Tabbar.axml Updated as part of this pull request.
examples/​AndroidSample/​Resources/​AboutResources.txt Updated as part of this pull request.
examples/​AndroidSample/​Properties/​AssemblyInfo.cs Updated as part of this pull request.
examples/​AndroidSample/​Properties/​AndroidManifest.xml Updated as part of this pull request.
examples/​AndroidSample/​MainViewModel.cs Updated as part of this pull request.
examples/​AndroidSample/​MainPage.xaml.cs Updated as part of this pull request.
examples/​AndroidSample/​MainPage.xaml Updated as part of this pull request.
examples/​AndroidSample/​MainActivity.cs Updated as part of this pull request.
examples/​AndroidSample/​LogPage.xaml.cs Updated as part of this pull request.
examples/​AndroidSample/​LogPage.xaml Updated as part of this pull request.
examples/​AndroidSample/​IAblyService.cs Updated as part of this pull request.
examples/​AndroidSample/​GettingStarted.Xamarin Updated as part of this pull request.
examples/​AndroidSample/​Class1.cs Updated as part of this pull request.
examples/​AndroidSample/​Assets/​AboutAssets.txt Updated as part of this pull request.
examples/​AndroidSample/​App.xaml.cs Updated as part of this pull request.
examples/​AndroidSample/​App.xaml Updated as part of this pull request.
examples/​AndroidSample/​app.config Updated as part of this pull request.
CHANGELOG.md Updated as part of this pull request.
cake-build/​unity-internalize-exclude.txt Updated as part of this pull request.
cake-build/​helpers/​test-execution.cake Updated as part of this pull request.
cake-build/​helpers/​paths.cake Updated as part of this pull request.
cake-build/​build.cake Updated as part of this pull request.
.gitignore Updated as part of this pull request.
.github/​workflows/​run-tests-windows.yml Updated as part of this pull request.
.github/​workflows/​run-tests-windows-netframework.yml Updated as part of this pull request.
.github/​workflows/​run-tests-macos.yml Updated as part of this pull request.
.github/​workflows/​run-tests-macos-mono.yml Updated as part of this pull request.
.github/​workflows/​run-tests-linux.yml Updated as part of this pull request.
.github/​workflows/​features.yml Updated as part of this pull request.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Aligns the 2.0 core with the SDK-family end state (java split-6 parity,
with .NET-specific choices where the platforms differ):

- Delete Auth.Authorise/AuthoriseAsync (British-spelling aliases;
  use Authorize/AuthorizeAsync).
- Delete Connection.RecoveryKey; use CreateRecoveryKey().
- Delete ClientOptions.FallbackHostsUseDefault (default fallback hosts
  apply automatically); also removes the dead internal AblyHttpOptions
  mirror of the flag.
- Hide the core client constructors: all five AblyRest/AblyRealtime
  constructors are now internal instead of public-and-obsolete. The two
  door assemblies are granted access via InternalsVisibleTo (keyless in
  non-Package builds, PublicKey-qualified for signed Package builds), so
  the doors drop their obsolete-suppression pragmas. Direct construction
  is no longer part of the public API; construct through PubSubDevice or
  PubSubServer. The core remains consumable as a dependency by Ably's
  higher-level SDKs, which wrap a door-constructed client.
- Remove the remaining long-deprecated members: CreateTokenRequestObject
  and CreateTokenRequestObjectAsync, CaptureCurrentSynchronizationContext,
  AblyRest.Request(string, ...), HistoryRequestParams,
  IRealtimeChannel.HistoryAsync(untilAttach), Presence.IsSyncComplete.
  Presence.IsSyncInProgress is deliberately retained: its replacement is
  internal-only, so removal would drop public capability.
- Extend UPDATING.md with a "Removed -> Use instead" table covering all
  of the above; correct two sentences that described the constructors as
  still public. Remove the test heads' blanket NoWarn 618, now baseless.

Validated: Build.NetStandard 0 warnings/0 errors (StyleCop-as-error),
Package-mode signed builds of both doors green (strong-named, IVT proven),
net6.0 unit leg 1250 tests / 0 failures. Cross-SDK derivation and the
per-item evidence are recorded in
SDK_ROLLOUT_V2/JAVA_REFACTORING_CHANGES_FOR_DOTNET.md.
The previous commit made the AblyRealtime/AblyRest constructors internal
and granted the door assemblies InternalsVisibleTo access in the SDK-style
core only. That missed the .NET Framework door head:
Ably.PubSub.Server.NETFramework compiles the shared door source
(PubSubServer.cs, Side.cs) under the same Ably.PubSub.Server assembly
identity against Ably.PubSub.Core.NETFramework, whose AssemblyInfo carried
no door grant - so the NetFramework build failed with CS1729 at the two
constructor call sites.

Add the same dual-mode grant to the net46 core, Server-only (there is no
net46 Device head): keyless under #if !PACKAGE, where nothing is signed,
and PublicKey-qualified from IO.Ably.snk under the PACKAGE arm, where the
package pipeline signs the core and the door in lockstep and
InternalsVisibleTo must name the consuming assembly's signed identity. The
PACKAGE symbol reaches this core the same way it reaches the SDK-style
core - the package pipeline injects DefineConstants=PACKAGE as a global
MSBuild property, which overrides project-level constants - so no csproj
change is needed. Ably.PubSub.Tests.NETFramework keeps its keyless-only
grant: it is not part of the package solution, so it never builds under
PACKAGE.

Validated under mono msbuild: the plain Release build of the net46 Server
head reproduces CS1729 before this change and compiles clean after it; the
Package=True build compiles and produces a strong-named door assembly; the
Cake Build.NetFramework target (the CI Mono leg's path) is green.
For the 2.0 line, rename the client-facing "REST" identifiers to "HTTP",
aligning .NET with the SDK-family convention: the java, php and python
Pub/Sub SDKs all ship PubSubHttpClient/PubSubRealtimeClient, and
ably-cocoa renamed ARTRest to ARTHttpClient. The class names describe
the transport the client speaks, not the service it talks to.

The rename map:

- AblyRest -> PubSubHttpClient, AblyRealtime -> PubSubRealtimeClient
  (classes and files)
- IRestClient -> IPubSubHttpClient, IRealtimeClient ->
  IPubSubRealtimeClient (interfaces and files)
- RestChannel -> HttpChannel, RestChannels -> HttpChannels,
  IRestChannel -> IHttpChannel (and files)
- the realtime client's RestClient property -> HttpClient (typed
  PubSubHttpClient)
- the internal transport AblyHttpClient -> AblyHttpRequester (and
  IAblyHttpClient -> IAblyHttpRequester), so the transport no longer
  collides with the renamed public client concept
- the Rest/ source and test folders fold into Http/, and the
  Rest*-prefixed test classes/files become Http*

Deliberately NOT renamed, because they name Ably's REST API service or
a wire option rather than our client layer: ClientOptions.RestHost /
FullRestHost, ClientOptions.IdempotentRestPublishing, Defaults.RestHost,
rest.ably.io literals, "Ably REST API" prose and spec-point comments.
Namespaces (including the IO.Ably.Rest sub-namespace on the moved
channel types), assembly names, NuGet IDs and InternalsVisibleTo
identities are unchanged. The committed Unity plugin DLL still carries
the old names; it is regenerated on the release pass.

Docs updated in step: UPDATING.md gains a Renamed-types table, the
CHANGELOG 2.0.0 entry states the renames and the internal-constructor
model, README and the nuspec descriptions name the new types.
PushNotifications.md is untouched: it documents the 1.x-only parked
device push-receive flow, where the old names are correct.

Validated with the Cake gates: Build.NetStandard (Release,
StyleCop-as-error) 0 warnings / 0 errors; Build.NetFramework under mono
green (the shared projitems carry every moved path); Package-mode
signed builds of the core and both doors clean; the net6.0 unit leg
1231 passed / 19 skipped / 0 failed; the net46 unit leg green under
mono with only the known mono-environment artifacts.
Two follow-through items on the REST-to-HTTP rename:

PushRest -> PushHttp (class and file). The rename rule is
"client-facing REST identifiers become HTTP", and PushRest - the type
of PubSubHttpClient.Push, paired with PushRealtime exactly as the old
AblyRest paired with AblyRealtime - had escaped it. With this, no
public type violating the rule remains (verified by sweep;
ClientOptions.RestHost, IdempotentRestPublishing and the "Ably REST
API" prose stay, per the retained-REST rule). PushRealtime is
untouched. UPDATING.md's rename table gains the row.

ClientConstructors_AreNotPublic (new spec in PubSubPackageSpecs). The
internal-constructor invariant is load-bearing: the door factories are
the only way application code can construct a client, which is what
guarantees every client carries the device/server classification that
Ably's platform behaviour and MAU billing depend on. Nothing enforced
that invariant, so an accidental future public constructor would ship
silently; the spec reflection-asserts that PubSubRealtimeClient and
PubSubHttpClient expose zero public instance constructors.

Also rewords the stale "Interface for a rest client" summary on
IPubSubHttpClient for the renamed type.
Mechanical namespace move for the 2.0 line. v1 (the released ably.io
package) keeps IO.Ably.*; v2 now lives entirely under Ably.PubSub.*, so
the two packages share no type names and a dependency graph containing
both compiles side-by-side - previously 148 public types collided,
making a mixed graph unbuildable without extern-alias gymnastics. The
new root also follows the .NET naming guidelines' Company.Product form
and agrees with the assembly names and package ids (Ably.PubSub.*), and
matches the family's intent (java io.ably.lib -> io.ably.pubsub, php
Ably\ -> Ably\PubSub\, python ably -> ably.pubsub) in the .NET-idiomatic
spelling.

The mapping: IO.Ably -> Ably.PubSub, sub-namespaces one-to-one
(IO.Ably.Realtime -> Ably.PubSub.Realtime, and so on), with two
deliberate exceptions - IO.Ably.Rest -> Ably.PubSub.Http (completing the
REST-to-HTTP rename for the moved channel types, mirroring java's
io.ably.lib.rest -> io.ably.pubsub.http) and the door namespaces
IO.Ably.PubSub.Device/Server -> Ably.PubSub.Device/Server (dropping the
vestigial IO. so each door's namespace equals its assembly and package
name). The test namespaces follow the same map, with the Tests.Rest
segments becoming Tests.Http to match their folders.

359 namespace declarations and every using directive across src, tests,
unity and examples move; the 7 RootNamespace/Import_RootNamespace hints
move with them (this supersedes the earlier decision that set those
hints to IO.Ably, which predates the namespace move). Two load-bearing
string literals are updated and pinned: IoC's platform lookup
asm.GetType("Ably.PubSub.Platform") - a silent runtime degradation if
missed, now guarded by the new AgentTests.IoC_ResolvesThePlatformClass
spec alongside the existing PlatformRuntime_ShouldDetectCorrectRuntime -
and the MsgPack serializer generator's Namespace/OutputDirectory
configuration (its orphaned generated-output directory src/IO.Ably is
renamed src/Ably.PubSub to keep the path real).

Unchanged on purpose: assembly names, package ids and every
InternalsVisibleTo grant (all name assembly identities); the wire agent
identifiers (ably-pubsub-dotnet, ably-pubsub-device, ably-pubsub-server)
and the Ably-Agent key, byte-identical; IO.Ably.snk / IO.Ably.ruleset
tool filenames and the IO.Ably.DeltaCodec submodule references; the
historical CHANGELOG entries and the 1.x-facing migration prose, where
IO.Ably correctly names the old API. Unity's link.xml is assembly-scoped
and untouched. UPDATING.md gains a "New root namespace" section - the
single biggest mechanical action for migrating 1.x code - and the
coexistence guidance in UPDATING.md and README.md is rewritten from
"both packages collide / unsupported" to "side-by-side compiles;
still migrate to avoid two connections and the 1.x billing treatment".
The REST-to-HTTP rename mechanically produced "an PubSubRealtimeClient"
(Connection.cs) and "an PubSubHttpClient" (AuthSandboxSpecs.cs); the
article is "a" for both. A branch-wide sweep confirms these were the
only two occurrences.
The namespace move mechanically over-applied to three comments whose
IO.Ably references were deliberate residuals:

- Both core AssemblyInfo files said Package builds sign with
  Ably.PubSub.snk; no such file exists - the signing key deliberately
  keeps its historical IO.Ably.snk name. Restored.
- IoC.cs's historical note claimed the assembly was "renamed from
  Ably.PubSub to Ably.PubSub.Core"; no assembly was ever named plain
  Ably.PubSub - the true history is a rename from IO.Ably to
  Ably.PubSub.Core. Restored.

The asm.GetType("Ably.PubSub.Platform") lookup and its doc comment are
correct for the new namespace (pinned by IoC_ResolvesThePlatformClass)
and are untouched.
The committed unity/Assets/Ably/Plugins/Ably.PubSub.Device.dll still
carried the pre-rename API (AblyRealtime, AblyRest, IO.Ably.*
namespaces), so the in-tree Unity examples and test assemblies - which
reference the new API - could not compile against it. Regenerated with
the sanctioned unity-plugins-updater.sh from this branch's sources.

The regeneration surfaced one missed rename site: the ILRepack
internalize-exclude pattern in cake-build/unity-internalize-exclude.txt
still read ^IO\.Ably\.PubSub\.Device\..* (its escaped dots kept it out
of every plain-text IO.Ably sweep), so the first regeneration
internalized the door class. The pattern now matches the moved
namespace, ^Ably\.PubSub\.Device\..*, and PubSubDevice is public in the
merged plugin again.

Verified with monodis and string scans: assembly identity
Ably.PubSub.Device 2.0.0.0 exactly once; the recorded
duplicate-attribute check matches the previously accepted baseline (one
Module-scope and one Assembly-scope row per attribute); 125 public
types, all under Ably.PubSub.* with the door public and
Newtonsoft/DeltaCodec/BCL shims internalized; the public type surface
equals the old plugin's modulo the shipped renames and deprecated-API
removals; the Ably.PubSub.Platform reflection literal present, no
IO.Ably user strings, and no non-DeltaCodec IO.Ably type names remain.
The plugin's .meta GUID and link.xml (assembly-scoped) are unchanged.

This retires the release-pass regeneration deferral recorded on the
rename PR; the Windows-side release checks (sn -v strong-name
verification, IL2CPP validation) remain release items.
Rename the REST naming to HTTP across the SDK
Move the root namespace from IO.Ably to Ably.PubSub

This branch was successfully deployed

1 active (outdated) deployment
staging/pull/1340/features — cbbddb87 Deployed Sep 23, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants