Conversation
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.
|
Important Review skippedToo 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (62)
📒 Files selected for processing (577)
You can disable this status message by setting the 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. Comment |
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.
There was a problem hiding this comment.
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.
…espace-ably-pubsub
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
What this PR is
This merges the completed 2.0 "SDK split" line — the
integration/v2branch — intomain. It implementsthe PubSub SDK split (PDR-091b) for .NET: the single
ably.iopackage is split into an internal core plustwo "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
Ably.PubSub.Coreably.iocodebase,IO.Ablynamespace). Not intended for direct installation; its plainAblyRealtime/AblyRestconstructors are[Obsolete]and produce unclassified clients.Ably.PubSub.DevicePubSubDevice.CreateClient(...)— stamps the versionlessably-pubsub-deviceagent flag.Ably.PubSub.ServerPubSubServer.CreateRealtimeClient(...)/PubSubServer.CreateHttpClient(...)— stampsably-pubsub-server.ably.io(1.x)v1branch (cut from tag1.2.19). No furtherably.ioreleases frommain.The door packages pin the core exactly (
[2.0.x]) and the three packages version in lockstep. The sideflags are versionless agent entries read by Ably's billing pipeline.
How this was built and reviewed
The work landed on
integration/v2as three stacked, individually reviewed PRs, followed by review-feedbackcommits on the integration branch itself:
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
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
publish.ymlwith NuGet Trusted Publishing, releasepre-flight assertions, prerelease support, CHANGELOG/UPDATING docs):
[Split 3/3] Lockstep release pre-flight, release dry-run CI job, and publish workflow #1335
ClientIdfix landed pre-merge on theSplit 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-basedClientOptions.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 (
agentvsAbly-Agent),pending realtime-team confirmation — see the checklist below.
A
main→integration/v2sync was performed before the stack merged, so this branch already containseverything on
main(including the repository rename and the 1.2.19 release).Consumer impact and migration
Ably.PubSub.DeviceorAbly.PubSub.Serverand construct clientsthrough the door factories. The core is a transitive dependency; do not install or construct it directly.
ably.io1.x consumers migrate perUPDATING.mdin this tree: swap the package, constructthrough a door. The API surface is otherwise the familiar
IO.Ablynamespace.ably.ioandAbly.PubSub.*from the same project — the types collide by design(compile error). The transitive-dependency scenario is covered in
UPDATING.md.Ably.PubSub.Device.dll(door types public; core, Newtonsoft,and DeltaCodec internalized).
admin remains in the core. See
PushNotifications.mdfor the decision record.Do not merge until (gates)
v1maintenance branch cut from tag1.2.19(must carrypackage.ymlandnuget/io.ably.nuspec) — hard gate.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#361releaseGitHub environment configured with required reviewers and a branch restriction (the auto-created one is unprotected).ably-pubsub-dotnet.agentquery param vsAbly-Agent) and any resulting fix landed on this branch.monodis) check clean; Unity EditMode/PlayMode smoke pass.integration/v2at 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 perCONTRIBUTING.md— first real dispatch recommended as a2.0.0-rc.1prerelease rather than thename-claim placeholder.