[Split 4/4] Run the UTS through the server door's builders - #1235
umair-ably wants to merge 13 commits into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks 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 failed
Sandbox realtime already enforces that on token auth the agent entry alone may not claim the server side — the side must come from a signed Resolution here: token-auth tests call Programme-level implication worth escalating (cc D2's owner): as enforced today, any customer using the server package with token auth gets 40167 — if prod behaves like sandbox, the server door is effectively key-auth-only until D2 ships. That sequencing constraint (D2 before/with the pubsub GA) doesn't appear in the rollout plan. |
3130176 to
0ba802f
Compare
0ba802f to
e1b1150
Compare
|
No more skips on the server leg. The token-auth handling is now per token format:
|
591377d to
91d6930
Compare
Adds the two public artifacts of the PDR-091b split, following the ably-js reference implementation (ably-js#2293): - io.ably.pubsub:server (jar, on :core): PubSubServer.httpClientBuilder() and PubSubServer.realtimeClientBuilder(), each accepting everything the core constructors accept (ClientOptions, API key or token string). - io.ably.pubsub:device (aar, on :core-android): PubSubDevice.clientBuilder(), one door per PDR-091. - A shared side helper (shared/src/main/java, compiled into both door artifacts rather than published) owns the ably-pubsub-device and ably-pubsub-server agent identifiers and the stamping rules: caller entries preserved, side entry applied last and unoverridable, caller's options never mutated, null passing through to the core's own error. The -device/-server suffixes are load-bearing for MAU billing classification and documented as such. - Fixes ClientOptions.copy() to carry headers, fallbackHosts, transportParams and agents, which it previously dropped; the doors rely on copy() for non-mutating stamping. Covered by a new unit test. - Server tests include a wire-level assertion that the Ably-Agent HTTP header carries ably-pubsub-server/<version> alongside the ably-java base identifier; device instrumentation tests assert the same contract and run in the emulator matrix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mirrors ably-js#2297, matching the registry entries in ably-common#361: the side flags are registered versionless (like `browser`), because under lockstep versioning a side-flag version always duplicates the SDK entry beside it, and across SDKs a bare version cannot say what it versions. Identity, version and support status keep travelling on the SDK's own ably-java/<version> entry. Wire shape: ably-java/2.0.0 jre/17 ably-pubsub-server AgentHeaderCreator already emits a null-valued map entry as a bare token, so no core change is needed; the doors stamp null and drop their BuildConfig version plumbing. Tests now assert the flag is present as a bare token and fail if any /version form regresses. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The family identifier follows the package split, per the agent identifier convention proposed on PDR-091b2 and registered in ably/ably-common#361: because it flips exactly at the split and the maintenance branch is never touched, the identifier alone partitions the fleet - ably-java/* is legacy-package traffic, ably-pubsub-java/* is new-package traffic. It names the family rather than any one published artifact; the side a client declares travels as the separate versionless entry stamped by the door packages: ably-pubsub-java/2.0.0 jre/17.0.12 ably-pubsub-server Requires the ably-pubsub-java registry entry (ably/ably-common#361) before any release from this branch. Mirrors ably/ably-pubsub-js#2297. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comments describe the behavior in place (versionless registry entries, the load-bearing suffix) rather than citing decision-record or PR numbers; those references live in the PR descriptions and READMEs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ifier SdkWrapperAgentHeaderTest asserts the full agent header and still expected the pre-rename ably-java family identifier. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
91d6930 to
b99ea4c
Compare
[Split 2/3] Add io.ably.pubsub:device and :server door packages with side-declaring agents
PDR-091b requires core, core-android, device and server to release together on one version, with partial release impossible: - A verifyReleaseArtifacts task asserts the exact published artifact set, group and lockstep VERSION_NAME (catching module-local overrides), failing before anything is uploaded. The release workflow runs it ahead of publishAndReleaseToMavenCentral. - A release-dry-run job in check.yml runs the pre-flight plus publishToMavenLocal on every PR, so coordinate and version regressions surface continuously rather than on release day. - README gains a note describing the in-development 2.0 artifact set and that 1.x installation instructions still apply. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mirrors ably-js#2294: the UTS constructs every client through a single seam (TestRealtimeClient/TestRestClient in ClientFactories.kt), now selected by the uts.side system property — `core` (default) keeps the core constructors; `server` routes both client kinds through PubSubServer's side-stamping builders. The builders only stamp the side-declaring agent flag and pass everything else through (DebugOptions included, via its copy() override), so conformance must be identical on both legs; CI runs both for the UTS unit and integration tiers. A harness self-test (SideModesTest, mirroring ably-js's side_modes.test.ts) asserts each mode's stamp on the wire via the mock HTTP engine — bare versionless flag in server mode, none in core mode — so a broken seam cannot silently degrade the server leg into a duplicate core run. Unlike ably-js there is no device leg: io.ably.pubsub:device is an Android artifact and cannot run on the JVM this suite uses; its stamping contract is covered by the device module's instrumentation tests. Also completes DebugOptions.copy() with the same four fields the base ClientOptions.copy() was missing (headers, fallbackHosts, transportParams, agents) — the door stamping relies on the polymorphic copy() to carry the suite's mock hooks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The server-mode UTS leg surfaced a real platform behavior: realtime rejects a token-authenticated connection that declares the server side through the agent entry alone, with 40167 "a connection or request may only declare itself as a server via a signed x-ably-clientType token claim". The signed-claim mechanism is PDR-091 deferred decision D2 and does not exist yet, so nothing the test infrastructure can mint will authenticate a token-auth server client. Key-auth server clients are unaffected (verified against sandbox), so the two token-auth test classes (TokenRequestTest, AuthReauthTest) now call assumeSideSupportsTokenAuth() and are reported skipped, not failed, on the server leg; the core leg still runs them. When D2 lands, the test infra can mint the claim and the assumption gets deleted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The UTS spec authenticates this test with a JWT; the Java port had substituted a native TokenRequest for convenience. Restoring the JWT (AblyJwt: HS256 via JDK crypto, no external library) lets the test carry the signed x-ably-clientType=server claim on the server leg — the only server-side declaration realtime accepts on token auth — so it now runs on every leg instead of being skipped. Verified against sandbox: the claim-bearing JWT connects and re-authenticates where the bare agent flag was rejected with 40167. assumeSideSupportsTokenAuth stays for the native-token tests (TokenRequestTest): the native token format cannot carry the claim yet. Also drops DR/ticket numbers from code comments in this PR's files; the behavior is described in place instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ntifier The family identifier shares the ably-pubsub- prefix with the side flags, so the harness self-test now matches the side identifiers exactly (via the Side constants) rather than by prefix, and asserts the renamed family entry is always present. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
TokenRequestTest's two clients now sit on opposite sides of the seam, matching how native tokens are really used: the minting client — the createTokenRequest surface under test — goes through the door on every leg, so the server leg exercises token minting through the server package; the consuming client models the device the token was minted for and is always a plain core client, since a client may not authenticate itself with a native token while declaring the server side (realtime rejects that with 40167, and the native token format cannot carry the required signed claim). Nothing is skipped on any leg any more, so assumeSideSupportsTokenAuth is deleted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
b99ea4c to
dfc2b19
Compare
Fourth PR in the PDR-091b split stack (stacked on #1234; diff shows only this PR's changes). Mirrors ably/ably-js#2294.
What this PR does
uts.sidemode on the UTS's single construction seam (ClientFactories.kt, used by all 10 unit + integration test files):core(default) keeps the core constructors;serverroutes both client kinds throughPubSubServer.httpClientBuilder/realtimeClientBuilder. The builders only stamp the versionless side flag and pass everything else through, so every UTS behaviour must pass identically through the door — that's the conformance claim this PR adds.check.yml(UTS unit) andintegration-test.yml(check-uts) each gain a-Duts.side=serverinvocation.SideModesTest, the analogue of ably-js'sside_modes.test.ts): captures the actualAbly-Agentheader via the mock HTTP engine and asserts the selected mode's stamp — bareably-pubsub-servertoken in server mode (fails on any/versionregression, per ably-common#361), no side token in core mode,ably-java/always present. Exists so a broken seam can't silently turn the server leg into a duplicate core run.@Timeout(30)so a seam regression fails rather than hangs.DebugOptions.copy()with the four fields baseClientOptions.copy()was also missing (fixed in [Split 2/3] Add io.ably.pubsub:device and :server door packages with side-declaring agents #1233):headers,fallbackHosts,transportParams,agents. This matters here because the door stamping relies on the polymorphiccopy()to carry the suite's mock hooks (httpEngine,webSocketEngineFactory,clock, listeners) through construction — the full server-mode suite passing green is the proof.Where this differs from ably-js (deliberately)
deviceleg:io.ably.pubsub:deviceis an Android AAR and cannot run on the JVM the UTS uses (ably-js's device package runs fine in Node). The device door's stamping contract is covered by the instrumentation tests in thedevicemodule (emulate.yml). Recorded in the uts README.TestRealtimeClient {}) already is the ably-jssideConstructorin spirit, so the change is awhenon the mode.AblyRest(...)constructions (liveobjects REST provisioning, proxy token signer) stay on core constructors — they're test infrastructure, not the SDK under test.Verified locally: full
:uts:runUtsUnitTestsgreen in both modes;SideModesTestruns and asserts in both.🤖 Generated with Claude Code