Repository navigation
Releases: caplaz/PatternSpaceSDK
Releases · caplaz/PatternSpaceSDK
Release list
1.1.0
Added
- Optional
device.signalSnapshotread route andDeviceNamespace.signalSnapshot()returning schema-1 immutable evidence separately from connection-bound probe authorization. The delegate receives the authenticatedOutputRequestContext; reads remain available while the JSON source is inactive. - Optional
pattern.displayProberoute andPatternNamespace.displayProbe(_:)carrying the existing patch shape plus a bounded opaqueexpectedContextGuard. The SDK reuses ordinary patch validation and forwards guard/context to the host for atomic authorization and admission. It never falls back todisplayPatch. - Typed source samples, scalar stage observations, separate accepted/published identities, draw/mapping/presentation identities, capture intervals, explicit unknown/omission reasons, and forward-compatible open tokens. Evidence excludes guard and packed frame buffers. Encoded responses are bounded to 256 KiB; each stage retains at most 64 samples with explicit omitted counts. Oversized optional details are marked omitted; oversized identity fails safely.
- Default unsupported delegate hooks and
supportsSignalSnapshot/supportsSignalProbeopt-ins preserve 1.0.0 conformers. OptionalCapabilityFeatures.signalSnapshot/signalProbehave trailing initializer defaults and decode absent from older hosts.
Changed
capabilities.listfilters only unsupported new routes/flags, preserving all existing namespace entries. Unsupported new methods return method-not-found.PatternSpaceProtocolMetadata.sdkVersionis now1.1.0; JSON protocol remains1.3. Existing routes, device bit-depth meaning, ACK behavior and global session timeout behavior remain unchanged.
Fixed
- Both client transports now accept the full 256 KiB SDK response bound, so valid signal snapshots larger than 64 KiB work on native Network.framework endpoints as well as URLSession endpoints. Server incoming request limits remain unchanged.
- Invalid mandatory capture timestamps fail validation rather than being replaced with zero. Unsupported evidence schema versions fail typed validation before evidence or probe authorization is decoded.
Host integration
- Guards belong to the authenticated connection and stable expected target/configuration/ownership context, independent of snapshot revisions and new patches. Historical responses must have no authorization; stable Refresh must not rotate a current guard. Stale context uses
displayError, a different connection usesnotAuthorized, inactive source usessourceNotActive, malformed guard usesinvalidParams. - Share only evidence and apply host export redaction to identifiers/optional descriptions. The SDK does not inspect OS profiles, calculate SDI packing, attest physical transport, or supply a per-request timeout.
1.0.0
Added
output.blankandoutput.resumeserver routes under a newoutputnamespace (listed inJSONRPCDispatcher.routeManifestand therefore incapabilities.list), with required delegate hooksblankOutput(context:)andresumeOutput(context:). Both return the resultingOutputStatus; both require an authenticated connection and an active JSON source (sourceNotActiveotherwise), exactly like thepattern.*write methods.OutputStatusschema withowner,ownerConnected,blankRequester,blanked,blankPending,failure,idleBlankSeconds,epoch, andrevision, plus the enumsPSOutputOwner,PSOutputBlankReason, andPSOutputFailure. Absent optional fields are encoded as explicit JSONnull; decoders accept either a missing key ornull.- Optional
output: OutputStatus?onDeviceStatus(device.status),DeviceSnapshot(device.statusChanged), andConnectionReadyParams(connectionReady). It decodes asnilfrom hosts that do not report it. CapabilitiesResult.outputBlank: Bool?so clients can detect blank support before callingoutput.*;nilfrom older hosts.PSErrorCode.outputNotConfirmed(-32013) for a blank that failed or an output whose state is unknown.OutputRequestContextcarrying the server-mintedclientIDof the authenticated connection that sent an output-write request. It is captured at dispatch and never read from JSON params.PatternSpaceServer.onClientConnected: (UUID) -> Void, delivered once per authenticated client when it becomes the active client, with the same identity carried by itsOutputRequestContext.ClientDisconnectReason(closed,evicted,serverStopped).- Client
client.output.blank()andclient.output.resume()via the newOutputNamespace.
Changed
- BREAKING: The six output-write delegate methods are now required context-bearing methods with no default implementations and no context-free overloads:
displayPattern(id:context:),displayColor(_:bitDepth:context:),displayPatch(_:context:),clearDisplay(context:),blankOutput(context:), andresumeOutput(context:). Hosts must compare the context with their current connection before mutating output so requests from an evicted or closed client cannot change output. Hosts without blank support must throwPSDispatchError(.methodNotFound)fromblankOutput/resumeOutputand omitCapabilitiesResult.outputBlank. - BREAKING:
JSONRPCDispatcher.dispatch(_:)is nowdispatch(_:context:); output writes forward the context to the delegate and read handlers ignore it. - BREAKING:
PatternSpaceServer.onClientDisconnectedis now(UUID, ClientDisconnectReason) -> Voidand is delivered exactly once for every client previously reported toonClientConnected, regardless of how many clients remain. On replacement the evicted client's.evictedcallback is delivered before the replacement'sonClientConnected;stop()reports.serverStoppedfor every client not yet reported. Rejected (unauthenticated) sockets never produce either callback, and connections accepted afterstop()are fenced out. - Lifecycle callbacks are serialized on an internal queue in lifecycle order. Callbacks triggered by
stop()run synchronously on the thread callingstop()after any in-progress callback finishes. Keep callbacks short and non-blocking (hop to your own actor or queue) and never callDispatchQueue.main.syncfrom one, or astop()on the main thread will deadlock. output.blankandoutput.resumeaccept absent params,{}, or[]; non-empty params,null, and scalar params returninvalidParams.- The client transport now fences message delivery by connection: connection replacement, identity validation, disconnect reporting, and message delivery share one serialization boundary, so no event from an old socket can be yielded after the new connection's
connectionReady. This applies to both the URLSession and Network.framework transports. PatternSpaceProtocolMetadata.sdkVersionis now1.0.0; PatternSpace JSON protocol remains1.3(theoutputnamespace is additive and discoverable throughcapabilities.listandoutputBlank).
Fixed
- Pending JSON-RPC calls now fail asynchronously when the connection drops, including when the
PatternSpaceClienthas already been released, instead of leaving awaiting callers suspended. - Native WebSocket close frames and send errors now end the socket and trigger auto-reconnect, rather than leaving the client attached to a dead connection.
Migration
- Add a
context: OutputRequestContextparameter todisplayPattern,displayColor,displayPatch, andclearDisplay, and implementblankOutput(context:)andresumeOutput(context:)(throwmethodNotFoundif unsupported). - Replace
onClientDisconnected = { ... }closures with the(UUID, ClientDisconnectReason)signature and track the active client withonClientConnected. - Pass a context to direct
JSONRPCDispatcher.dispatchcallers (for example in tests):dispatch(data, context: OutputRequestContext(clientID: UUID())).
0.7.6
Fixed
- Made the WebSocket client integration test compatible with the Swift Testing version used by GitHub Actions.
TaskGroup.next()is mutating and cannot be passed through that runner's#requiremacro; the test now unwraps its result with ordinaryguardhandling.
Changed
PatternSpaceProtocolMetadata.sdkVersionis now0.7.6; PatternSpace JSON protocol remains1.3.
0.7.5
Fixed
- Explicit host/IP connections now use
URLSessionWebSocketTaskrather thanNWProtocolWebSocket. On macOS 26, the latter could abort during the WebSocket upgrade against the PatternSpace server even while the server was listening and standards-compliant WebSocket clients connected successfully. Bonjour-discovered services retain the native Network.framework transport, which continues to resolve and connect correctly. - Explicit
PatternSpaceClient.disconnect()now fails pending JSON-RPC requests, rather than leaving an awaiting caller suspended after the transport has been closed.
Changed
- Added a client/server integration test that exercises an authenticated
device.statusrequest over a real loopback WebSocket connection. PatternSpaceProtocolMetadata.sdkVersionis now0.7.5; PatternSpace JSON protocol remains1.3.
0.7.4
Fixed
WebSocketFrameCodec.decodenow decodes the second and later frames on a connection. It indexed with absoluteDataoffsets while comparing againstData.count, and returnedconsumedas an absolute index rather than a byte count. BecauseDatakeeps a non-zerostartIndexafterremoveFirst(_:), every frame after the first decoded as perpetually.incomplete, so a client sending more than one request on a single connection would hang waiting for a response that was never dispatched. Decoding is now fully relative tostartIndexandconsumedis a true byte count. Single-request connections were unaffected (their buffers always started at index 0), which is why this only surfaced with multi-request sessions.
Changed
PatternSpaceProtocolMetadata.sdkVersionis now0.7.4; PatternSpace JSON protocol remains1.3.
0.7.3
Fixed
PatternSpaceClientnow emits.connectionFailedfor clean server-side closes (WebSocket close frame, nil error), not only for transport errors. Previously a clean close was silent — the event stream yielded nothing, leaving UI consumers (e.g. the iOS Remote tab) stuck showing "Connected" while the client was silently retrying. With this fix any unintentional disconnect, clean or error, surfaces as.connectionFailedso consumers can transition to a failure state immediately. Auto-reconnect still fires; if the server comes back the nextconnectionReadynotification returns the consumer to connected.PatternSpaceClientErrornow conforms toLocalizedError, providing a readableerrorDescription("The server closed the connection") instead of the default Swift error description.
Changed
PatternSpaceProtocolMetadata.sdkVersionis now0.7.3; PatternSpace JSON protocol remains1.3.
0.7.2
Fixed
PatternSpaceServernow firesonClientDisconnectedwhen the last active (upgraded) client disconnects. Previously the server silently removed the client from its tracking dict with no notification to the host, leaving the host app stuck in a "connected" state until a new client connected or the server restarted. The callback is suppressed whenstop()drives the close (server shutdown already sets status to idle) and when a client is evicted by a new one (the new client is already active).
Changed
PatternSpaceProtocolMetadata.sdkVersionis now0.7.2; PatternSpace JSON protocol remains1.3.
0.7.1
Fixed
PatternSpaceServernow responds to WebSocket upgrade requests. Each incoming connection was released as soon as it was accepted — before its HTTP upgrade was processed — so the handshake never completed and clients timed out with no response. Connections are now retained until they upgrade or close.- WebSocket upgrades are accepted on any resource path.
NWProtocolWebSocketclients connecting through a hostPort or Bonjour service endpoint upgrade against/(such endpoints cannot carry a path), which the server previously rejected with400 Bad Request. The canonical path remains/patternspace, and the bearer token — not the path — stays the authentication boundary.
Changed
PatternSpaceProtocolMetadata.sdkVersionis now0.7.1; PatternSpace JSON protocol remains1.3.
0.7.0
Added
display.setMeasurementRangeserver route, delegate hook, client method, params, and result schemas- Additive
selectedMeasurementRangefields onDisplayEntryandDeviceStatus
Changed
PatternSpaceProtocolMetadata.sdkVersionis now0.7.0; PatternSpace JSON protocol is now1.3
Removed
- Per-preset
measurementRangefromOutputColorPresetConfig; measurement range is host-global runtime state
0.6.0
Added
- Preset ID constants for three Linear HDR presets:
extLinearSRGBHDR,linearHDRP3D65,linearHDRBT2020 OutputColorPresetFamily.linearHDRconvenience constant for clients reading Linear HDR preset metadata
Changed
PatternSpaceProtocolMetadata.sdkVersionis now0.6.0; PatternSpace JSON protocol remains1.2- Protocol documentation and README examples now describe Linear HDR presets and Peak White gating semantics