feat(adcp): per-instance adcpVersion string API with cross-major validation (#16)#19
Merged
MichielDean merged 1 commit intoMay 19, 2026
Conversation
…validation Implements issue #16 — Stripe-model per-instance adcpVersion option. Changes: - AdcpVersion.of(String): parse release-precision string "3.0" / "3.1" into an AdcpVersion. Companion to the existing AdcpVersion(int, String) constructor; follows the TS/Python SDK convention for caller-site pinning. - Build-time AdcpSdkVersion.java: generated from ADCP_VERSION at build time (major=3, release="3.0" from "3.0.11"). Eliminates the manually-maintained COMPATIBLE_ADCP_VERSIONS list that the Python SDK got burned by — updating ADCP_VERSION automatically updates the compatibility constant. - AdcpClient.Builder.adcpVersion(String): convenience overload that calls AdcpVersion.of(). Cross-major pins (e.g. "2.0" on a major-3 SDK) throw ConfigurationError at build() time, before any network request. - AgentConfig.Builder.adcpVersion(String): same string-based overload. Tests: AdcpVersion.of() parsing, AdcpSdkVersion constant invariants, AdcpClient cross-major rejection, string-builder acceptance. Acceptance criteria from #16: ✓ AdcpClient.builder().adcpVersion("3.0").build() accepted ✓ Outbound requests carry adcp_version at release precision ✓ Cross-major mismatch raises ConfigurationError before send ✓ Compatibility derived from ADCP_VERSION at build time jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
MichielDean
added a commit
that referenced
this pull request
May 19, 2026
…3) (#18) * feat(transport): Phase 1+2 — AdcpHttpClient and error taxonomy Phase 1: SSRF-safe HTTP client - AdcpHttpClient with DNS-pin, body cap, redirect:NEVER - AdcpHttpResponse record with truncation tracking - DnsPinResolver for DNS resolution + SSRF validation - SsrfBlockedException for blocked requests Phase 2: Error taxonomy (14 sealed subclasses of AdcpError) - ProtocolError, AuthenticationRequiredError, TaskTimeoutError, TaskAbortedError, DeferredTaskError, ValidationError, ConfigurationError, VersionUnsupportedError, AgentNotFoundError, UnsupportedTaskError, FeatureUnsupportedError, ResponseTooLargeError, IdempotencyConflictError, IdempotencyExpiredError - AuthChallengeInfo + OAuthMetadataInfo records - WwwAuthenticateParser (RFC 9110 §11.6.1) - Package-info.java for error and auth packages Also updates ROADMAP.md Track 3 owner and tracks claimed. jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(transport): Phase 3 — AgentConfig, auth types, and token resolver - AgentConfig record with builder, auth exclusivity validation, and static MCP factory methods - Protocol enum (MCP, A2A) - AdcpVersion record with V3/V3_1 constants - BasicCredentials, OAuthClientCredentials, OAuthTokens records - AuthTokenResolver: Bearer, Basic, OAuth token → header resolution with x-adcp-auth backward compatibility header for static tokens jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(transport): Phase 4 — MCP caller, connection manager, version envelope - McpConnectionManager: LRU-cached MCP connections (max 20), StreamableHTTP → SSE fallback, evict-and-retry on transport errors - McpCaller: callTool dispatch, content extraction, deserialization - ProtocolClient: central dispatch point for all tool calls, SSRF URL validation, auth header injection, version envelope merge - VersionEnvelope: adcp_major_version + adcp_version injection, caller args win on collision (conformance override) - CallToolOptions: per-call timeout, body cap, validation toggle - DnsPinResolver: made public for cross-package SSRF validation - adcp/build.gradle.kts: added mcp-core + mcp-json-jackson2 (impl), excluded transitive json-schema-validator 2.x to keep pinned 1.5.x jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(transport): Phase 5 — AdcpClient with generic callTool dispatch - AdcpClient: single-agent client, builder pattern, AutoCloseable - Generic callTool(toolName, args, responseType) method - callNamedTool(toolName, typedRequest, responseType) for type safety - Builder: agent, adcpVersion, objectMapper, ssrfPolicy - Lifecycle: close() evicts cached MCP connections jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(server): add MCP server-side transport (AdcpPlatform SPI + builder) Implements Phase 6 of Track 3: the agent-side MCP server wiring. - AdcpContext: per-request context record (version, headers, principal) - AdcpPlatform: abstract SPI that agent adopters extend; supportedTools() + handleTool() dispatch. Only supported tools are advertised via MCP tools/list. - AdcpServerBuilder: wires AdcpPlatform to McpSyncServer via McpServer.sync(transport).toolCall(...). Extracts version envelope from inbound args, serialises responses as TextContent. - Tests for platform dispatch + supportedTools + error paths. jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(testing): add integration tests for server builder and client Phase 8 of Track 3: integration testing. - ServerBuilderRoundTripTest: 9 tests validating AdcpPlatform → AdcpServerBuilder wiring, tool dispatch, error handling, context propagation, and version extraction. - AdcpClientIntegrationTest: client integration tests against the @adcp/sdk/mock-server sidecar (enabled when ADCP_MOCK_SERVER_URL is set in CI). - Add adcp-server as testImplementation dep of adcp-testing module. jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(transport): audit fixes for security, thread safety, and correctness Address 22 findings from comprehensive code audit: CRITICAL: - McpConnectionManager: fix check-then-act race with ReentrantLock, pass auth headers via httpRequestCustomizer, pass connectTimeout to transport builders, add volatile closed flag, clean up knownStreamableUrls on evict/close - AdcpHttpClient.close(): call httpClient.close() (was no-op) - Credential records: override toString() to redact secrets in BasicCredentials, OAuthClientCredentials, OAuthTokens - SsrfBlockedException: remove host from getMessage() to prevent information leakage - AdcpHttpClient.pinUri(): stop rewriting URI with IP (broke HTTPS SNI/TLS); validate addresses but keep original hostname HIGH: - ProtocolClient.computeTokenHash(): use SHA-256 instead of String.hashCode() (32-bit collision risk) - AdcpServerBuilder: use ObjectMapper for error JSON serialization to prevent JSON injection; strip version envelope fields from args before passing to platform - AdcpClient.toArgs(): reuse ObjectMapper field instead of creating new instance per call - McpCaller.extractResponse(): check result.isError() before deserializing as success - AdcpHttpClient: filter protected headers (Host, User-Agent, Content-Length, Transfer-Encoding) from caller-supplied map - BasicCredentials: reject colon in username per RFC 7617 §2 - AuthChallengeInfo: add null validation on scheme - OAuthMetadataInfo: add null validation on required fields - AdcpHttpClient.pinUri(): use syntactic IP-literal check instead of DNS call for literal addresses MEDIUM: - ProtocolClient retry: only retry transport errors (IOException, timeout), chain original exception as suppressed - McpConnectionManager.isAuthError(): match specific patterns (HTTP 401, status: 401) instead of bare substring "401" jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(security): comprehensive security hardening across transport layer Address findings from deep security audit of Track 3 code: HIGH — Must Fix: - AgentConfig: override toString() to redact authToken and webhookSecret (CWE-532 info disclosure via auto-generated toString) - AgentConfig: reject authToken with CR/LF characters to prevent header injection (CWE-113) - AdcpObjectMapperFactory: reduce limits from 100MB/2000 depth to 10MB/200 depth to prevent DoS via oversized payloads (CWE-400) - McpConnectionManager: add CRLF sanitization and protected-header filtering on MCP transport headers (CWE-113) - ProtocolClient.validateUrl(): perform DNS resolution and SSRF policy validation for MCP transport path — was previously skipped entirely, allowing SSRF via private address hostnames (CWE-918) MEDIUM — Should Fix: - ProtocolClient.computeTokenHash(): use full SHA-256 output instead of truncated 8 bytes to prevent cache key collisions (CWE-328) - ProtocolClient: enforce auth-last header merge ordering so extraHeaders cannot override Authorization (CWE-287) - McpCaller: sanitize and truncate remote error text to 500 chars, strip control characters to prevent injection into LLM context - AdcpServerBuilder: split error handling into known (AdcpError → safe to surface) vs unknown (Exception → "internal error" only) to prevent internal details leaking to remote callers (CWE-209) - AdcpServerBuilder.extractVersion(): validate major version >= 3 to prevent protocol downgrade attacks (CWE-757) - AdcpHttpResponse: defensive clone of body byte[] in compact constructor to prevent mutation (CWE-374) - McpConnectionManager: move closed check inside lock to prevent connection creation race after close() (CWE-362) - AdcpHttpClient/McpConnectionManager: expand protected headers to include connection/upgrade - SsrfBlockedException.host(): restrict to package-private visibility to limit hostname exposure (CWE-209) LOW — Cleanup: - McpConnectionManager: replace ConcurrentHashMap-backed knownStreamableUrls with plain HashSet (always accessed under lock) jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(transport): comprehensive audit fixes for correctness and API design Address findings from deep code review of Track 3 implementation: CRITICAL: - McpConnectionManager.close(): move `closed = true` inside lock to prevent race where concurrent getOrConnect() sees inconsistent state (CWE-362) HIGH: - AdcpHttpResponse.body(): override record accessor to return defensive copy — the compact constructor cloned on construction but the accessor still leaked a reference to the internal array (CWE-374) - AdcpServerBuilder: use platform.toolDescriptions() for MCP tool descriptions instead of using tool name as description (hurts LLM tool selection) - AdcpServerBuilder: use safe constant in JSON fallback error path instead of string-concatenating e.code() (CWE-116 JSON injection) - AdcpClient: fail fast with FeatureUnsupportedError when constructed with Protocol.A2A instead of silently creating MCP infrastructure and failing at callTool() time MEDIUM: - AuthChallengeInfo: enforce lowercase scheme in compact constructor to match documented contract - AdcpVersion: validate minorVersion starts with majorVersion to prevent inconsistent version objects (e.g., major=3, minor="4.1") - AgentConfig.toString(): redact extraHeaders values (may contain API keys like X-Api-Key) - Extract shared ProtectedHeaders utility to eliminate duplicate PROTECTED_HEADERS constant between AdcpHttpClient and McpConnectionManager (drift risk) - McpConnectionManager.connectWithFallback: extract buildAndInit() helper to eliminate triple-duplicated transport construction code - McpCaller.extractResponse: track first parse error and attach as suppressed exception for better diagnostics - CallToolOptions.Builder.maxResponseBytes: add validation rejecting zero and negative values - McpConnectionManager.isAuthError: check McpError type first before falling back to string matching; add TODO for typed status exposure LOW: - McpConnectionManager.evictOldest: also clear knownStreamableUrls entry during LRU eviction to prevent stale transport preference Tests: 5 new tests (178 total, 168 passing — 10 pre-existing schema failures unrelated to Track 3). jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(transport): final audit fixes — locale, CRLF, resource leak, cause chain Address 4 findings from final comprehensive audit: - WwwAuthenticateParser: use Locale.ROOT in toLowerCase() to prevent Turkish-locale JVMs producing incorrect scheme strings like "basıc" instead of "basic" (CWE-178 improper case handling) - OAuthTokens: reject CR/LF in accessToken to match authToken validation parity — prevents silent header injection that would result in an unauthenticated request instead of a clear error - McpConnectionManager.buildAndInit: close McpSyncClient if initialize() throws to prevent resource leak of HttpClient thread pools on repeated connection failures - AuthenticationRequiredError: add cause-carrying constructor and pass original exception from McpConnectionManager auth detection so stack traces are preserved for debugging jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(security): second security audit — SSRF bypass, DoS cap, info leak - HIGH: Fix IPv4-compatible IPv6 SSRF bypass (::a.b.c.d form) StrictSsrfPolicy.unmapIpv4Mapped() now unwraps both ::ffff:a.b.c.d (mapped) and ::a.b.c.d (compatible) forms before range checking - MEDIUM: Add 10MB content size cap in McpCaller.extractResponse() to prevent OOM from malicious agents returning oversized TextContent - MEDIUM: Stop leaking AdcpError.getMessage() to remote callers — AdcpServerBuilder now returns only e.code() in error responses - LOW: Validate extraHeaders for CRLF at AgentConfig construction (fail-fast instead of relying solely on downstream sanitization) - LOW: Validate AdcpVersion.minorVersion format with regex + length cap to prevent log injection via crafted version strings - LOW: Warn via SLF4J when credentials are configured for plaintext HTTP agent URIs - Docs: CallToolOptions Javadoc documents which fields are reserved (timeout, maxResponseBytes not yet wired in v0.1) jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(transport): third code audit — MCP spec compliance, correctness, API design - HIGH: Add inputSchema to MCP tool registration (MCP spec requires it) - HIGH: Fix WwwAuthenticateParser Locale.ROOT on param key lowercasing - HIGH: Fix knownStreamableUrls state leak across different token hashes (now keyed on full cache key instead of URL alone) - HIGH: Remove unused imports and fix misleading Javadoc in DnsPinResolver - HIGH: Fix AdcpPlatform Javadoc (falsely claimed reflection-based discovery) - MEDIUM: Add AdcpHttpResponse.equals/hashCode using Arrays.equals for body - MEDIUM: Redact all credentials in AgentConfig.toString() (basicAuth, oauthClientCredentials, oauthTokens were previously shown in clear) - MEDIUM: Add authorization to ProtectedHeaders (prevent silent override) - MEDIUM: Fix error response shape (was {error:code, code:code}, now {error:code, message:msg}) for AdcpError cases - MEDIUM: Parse string major version values in extractVersion - MEDIUM: Include oauthClientCredentials in computeTokenHash - MEDIUM: Use ConfigurationError (not ProtocolError) for builder validation - MEDIUM: Log warning when non-default CallToolOptions are passed (v0.1) jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(security): fourth adversarial audit — cache isolation, stream leak, DoS cap - Include extraHeaders hash in MCP connection cache key to prevent cross-tenant header leakage in multi-tenant scenarios - Revert authorization from ProtectedHeaders (broke SDK auth path) - Fix InputStream leak in AdcpHttpClient when readBodyWithCap throws - Skip null TextContent.text() entries in McpCaller instead of NPE - Cap adcp_version string to 20 chars to prevent unbounded allocation - Reject major version > 99 as unsupported jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(transport): fifth adversarial audit — lock contention, OOM guard, retry logic - Replace global lock with per-key striped locking in McpConnectionManager so one slow/unreachable agent doesn't block all others (HEAD-OF-LINE fix) - Make knownStreamableKeys a ConcurrentHashMap.KeySetView for thread safety - Cap maxResponseBytes at 64 MB to prevent OOM from misconfigured caps - Replace fragile contains("Transport") with cause-chain IOException walk for correct retry decisions jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(transport): prevent unbounded keyLocks growth on token rotation Clean up per-key locks after connection attempt completes and clear the map on close(). Without this, each OAuth token rotation created an orphaned lock entry that persisted for process lifetime. jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(transport): sixth adversarial audit — lock race, close race, error leak - Guard keyLocks.remove() with hasQueuedThreads() to prevent duplicate connections when evict+reconnect races with a new per-key lock - Check closed flag after connecting before inserting into cache to prevent resource leak when close() races with connect - Sanitize server-side AdcpError messages (truncate 500 chars, strip control chars) before sending to remote callers (CWE-209) jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(transport): seventh adversarial audit — striped semaphores, request timeout, error sanitization Major concurrency redesign of McpConnectionManager: - Replace per-key ReentrantLock map with fixed-size striped Semaphore[32] pool, eliminating the keyLocks cleanup race and unbounded growth - Semaphore.acquire() is virtual-thread-friendly (no carrier pinning), fixing performance DoS under JDK 21 virtual threads - Add 30s request timeout via requestBuilder on both StreamableHTTP and SSE transports, preventing half-open connection DoS where a malicious agent accepts TCP but never responds to MCP initialize Server-side error handling: - Sanitize AdcpError messages before sending to remote callers: truncate to 500 chars and strip control characters to prevent info leakage (CWE-209) jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address bokelley PR review findings and fix CI lockfiles Blockers: - B1: DNS pinning via URI rewriting + Host header injection - B2: ProtectedHeaders for auth/cookie, filtered before auth merge - B3: McpCaller reads structuredContent first, falls back to content[] - B4: HEAD probe for WWW-Authenticate on auth errors - B5: OAuth CC throws FeatureUnsupportedError (not yet implemented) - B6: ServerBuilderRoundTripTest with StubMcpTransport - B7: AdcpClientIntegrationTest with stronger spec assertions Majors: - M1: WwwAuthenticateParser quoted-pair fix + 16-param cap - M2: IPv6 SSRF: 6to4, Teredo, NAT64, octal IP rejection - M3: AdcpPlatform.handleTool Object → Map<String,Object> - M5: invalidateForAgent for cache eviction on token rotation - M6: isAuthError word-bounded pattern matching - M7: toolSchemas() SPI on AdcpPlatform for typed input schemas - M8: ValidationError field → path list + schemaUri - M9: VersionEnvelope SDK wins over caller - M10: computeTokenHash HMAC with per-process random key Minors: - N1: null callerArgs handled in VersionEnvelope - N2: BasicCredentials allows blank password - N3: A2A rejection deduplication (kept in ProtocolClient only) CI: - Updated dependency lockfiles for 4 modules (MCP SDK transitives) - connectWithFallback TODO for content-type probe (M4 deferred) jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: guard MCP integration test behind ADCP_MCP_SERVER_URL The current mock-server sidecar is a REST stub, not an MCP server, so callTool tests fail when run against it. Guard the MCP-specific test behind a separate env var until the mock-server gains MCP support. jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * docs: add cosign as a build prerequisite The schema bundle fetch task shells out to `cosign verify-blob` to verify Sigstore signatures. Without cosign installed, all 10 schema tests fail with "Cannot run program cosign". Document the requirement in CONTRIBUTING.md and CLAUDE.md. jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address remaining bokelley review findings (M4, N4, N5, N6) M4: Replace exception-based StreamableHTTP→SSE fallback with a content-type probe (POST with initialize to detect transport). Known-good endpoints skip the probe. Falls back to SSE when the probe gets 405 or non-JSON response. N4: Add requireHttps(boolean) to AdcpHttpClient.Builder. When true, rejects plain http:// for non-loopback hosts with a clear error. Defaults to false for backward compat. Localhost is always exempt. N5: Harden ObjectMapper in McpCaller — defensively disables default typing on a copy to prevent polymorphic deserialization attacks when responseType is Object.class or Map.class. N6: Change extractVersion to default to v1 semantics for major<3 instead of throwing VersionUnsupportedError, matching Python adcp.server back-compat behavior. Also cleans up duplicate TODO comments in McpConnectionManager (B4). jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test(server): add handleToolCall unit tests for B6 completeness Extract handleToolCall and extractVersion to package-private visibility so they can be tested directly from AdcpServerBuilderTest. The new test class exercises: - Tool dispatch through the builder's handler - Version envelope stripping before platform dispatch - Version extraction into AdcpContext - AdcpError wrapping with stable error codes - Unexpected exception wrapping without detail leakage - Null arguments handling - extractVersion edge cases (string/int major, back-compat, oversized minor) This completes B6 from bokelley's review: the builder's handleToolCall code path (version-envelope strip, error wrapping, handler dispatch) is now fully exercised by tests, not just assertNotNull(server). jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: add null guard on AdcpClient.callTool args parameter callTool now accepts @nullable args — null is normalised to Map.of() before reaching ProtocolClient/VersionEnvelope. Adds a test verifying null args does not NPE. jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(adcp): add per-instance adcpVersion string API with cross-major validation (#19) Implements issue #16 — Stripe-model per-instance adcpVersion option. Changes: - AdcpVersion.of(String): parse release-precision string "3.0" / "3.1" into an AdcpVersion. Companion to the existing AdcpVersion(int, String) constructor; follows the TS/Python SDK convention for caller-site pinning. - Build-time AdcpSdkVersion.java: generated from ADCP_VERSION at build time (major=3, release="3.0" from "3.0.11"). Eliminates the manually-maintained COMPATIBLE_ADCP_VERSIONS list that the Python SDK got burned by — updating ADCP_VERSION automatically updates the compatibility constant. - AdcpClient.Builder.adcpVersion(String): convenience overload that calls AdcpVersion.of(). Cross-major pins (e.g. "2.0" on a major-3 SDK) throw ConfigurationError at build() time, before any network request. - AgentConfig.Builder.adcpVersion(String): same string-based overload. Tests: AdcpVersion.of() parsing, AdcpSdkVersion constant invariants, AdcpClient cross-major rejection, string-builder acceptance. Acceptance criteria from #16: ✓ AdcpClient.builder().adcpVersion("3.0").build() accepted ✓ Outbound requests carry adcp_version at release precision ✓ Cross-major mismatch raises ConfigurationError before send ✓ Compatibility derived from ADCP_VERSION at build time jira-issue: ADCP-0017 Co-authored-by: Bugher-Michiel-1124273_TDX <Michiel.Bugher@Tritondigital.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(transport): address B1 DNS pinning regression from bokelley review Remove URI rewriting that broke TLS hostname verification: - DnsPinResolver no longer rewrites URIs to IP literals; validates at resolve time and returns the original URI so HTTPS SNI works correctly - AdcpHttpClient.pinUri() renamed to validateUri(), scheme check added - Host header injection removed (no longer needed without rewriting) Route all MCP probes through AdcpHttpClient for SSRF defense: - McpConnectionManager accepts AdcpHttpClient via new constructor - probeSupportsStreamableHttp uses adcpHttpClient.post() with ping payload instead of raw HttpClient with initialize (avoids half-handshake) - probeAndBuildAuthError routes through adcpHttpClient.send() with OPTIONS fallback when HEAD returns 405 - MCP transports use clientBuilder(adcpHttpClient.newMcpClientBuilder()) instead of customizeClient Additional fixes from review: - ProtocolClient.validateUrl rejects non-http/https schemes - AdcpClient.Builder exposes requestTimeout(Duration) for long-poll calls - AuthenticationRequiredError.challenge javadoc documents null semantics - AdcpClient.close() properly cascades to AdcpHttpClient jira-issue: ADCP-0017 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Bugher-Michiel-1124273_TDX <Michiel.Bugher@Tritondigital.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #16
What this does
Implements the Stripe-model per-instance
adcpVersionoption so a single process can talk to agents running different protocol versions.API surface
AdcpVersion.of(String)
New static factory parses
"3.0"/"3.1"(release precision) into the existingAdcpVersionrecord. Follows the same convention as the TS and Python SDKs'adcpVersionconstructor option.Build-time AdcpSdkVersion.java
Generated from
ADCP_VERSIONat build time — no manually-maintained compatibility list.ADCP_VERSION = "3.0.11"→SDK_MAJOR_VERSION = 3,SDK_RELEASE_VERSION = "3.0". When the protocol bumps to v4, updatingADCP_VERSIONautomatically updates the validation constant; no code change needed.Cross-major validation
AdcpClient.Builder.build()checksadcpVersion.majorVersion() == AdcpSdkVersion.SDK_MAJOR_VERSION. Mismatch throwsConfigurationErrorwith a clear message before any network activity.Acceptance criteria from #16
AdcpClient.builder().adcpVersion("3.0").build()acceptedadcp_versionat release precision ("3.0","3.1")ConfigurationErrorbefore sendADCP_VERSIONat build time (not hardcoded)Notes
track3/transportbecauseAdcpClientdoesn't exist onmainyetAdcpSdkVersion.javais generated intobuild/generated/and not checked in