feat(sync): add NexusKit.Modules.Sync, the client half of the sync stack - #35
Merged
Conversation
The REST transport against any server speaking NexusKit.Sync: RestSyncProtocol, API-key handling, keyed connection registration, and defensive Problem Details parsing. Registration is keyed rather than singular because talking to several servers is the normal case, not an exception: every author runs their own, so a plugin consuming somebody's published client bindings talks to that author's server and to its own. Retrofitting that later would mean partitioning the outbox, the cursors, the settings section and the key storage after the fact. ContractResolution decides which document a client works from. Where the key carries the built-in contract-reading scope the server's copy wins — a local file that has drifted then stops being a problem to diagnose. Where it does not, the server publishes nothing and the client falls back on what it ships. Plain HTTP is refused rather than upgraded. An API key is a bearer credential, and silently rewriting an address hides a misconfiguration that matters. No Dalamud reference: the transport has nothing to do with the game, and the same assembly is what a headless test harness uses. Also removes PlayerNexusTracker from the modules' API documentation, for the same reason as NexusKit: these are meant to be usable without knowing that plugin exists.
nxships
enabled auto-merge (squash)
August 11, 2026 11:37
A floor of 0.5.0 restores 0.5.1 and raises NU1603 for the substitution, which TreatWarningsAsErrors turns into a failed build. The library did not exist in 0.5.0, so that was never a version anyone could resolve.
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.
The client side of NexusKit.Sync: REST transport, API-key handling, connection registration.
Requires
NexusKit.Sync, published in NexusKit v0.5.1.What is here
RestSyncProtocolISyncProtocoloverHttpClient. Stateless beyond its configuration.SyncConnectionOptionsSyncServiceCollectionExtensionsContractResolutionProblemDetailsReaderThree decisions worth the review
Registration is keyed. Talking to several servers is the normal case: every author runs their own, so a plugin consuming somebody's published client bindings talks to that author's server and to its own. Retrofitting that later means partitioning the outbox, the cursors, the settings section and the key storage after the fact.
The server's contract wins, where the key may read it. A local file that has drifted then stops being something to diagnose. Where the key may not, the server publishes nothing and the client falls back on what it ships — the mode that scope exists to gate.
Plain HTTP is refused, not upgraded. An API key is a bearer credential; over plain HTTP everyone on the path has it. Silently rewriting the address would hide a misconfiguration that matters.
AllowInsecureTransportexists for a container on localhost and nothing else.Deliberately not here
No outbox, no downlink mirror, no cursor persistence, no background drainer — the parts that turn
PushAsyncinto fire-and-forget andGetAsyncinto an offline read. Until then a caller holdsISyncProtocoland drives it. Stated in the README rather than implied by absence.Verification
Builds clean, 0 warnings. 13 tests against a stubbed handler, plus a full end-to-end run against a live server: handshake, push, idempotency, validation refusals, direction and scope violations, all green.
Same caveat as NexusKit: those tests live in
localTools/and no CI runs them.Documentation
PlayerNexusTrackeris out of the modules' API docs, for the reason it left NexusKit's — these are meant to be usable without knowing that plugin exists.