Share one AtCommandExecutorContext per connection - #429
Open
akafredperry wants to merge 1 commit into
Open
Conversation
Standardize the command layer on (AtCommandExecutor, AtCommandExecutorContext) as its leading arguments, and create exactly one context per connection in AtClients.createAtClient, passing it to both the executor builder and AtClientImpl. The context cannot be created by AtClientImpl, which receives an already-built executor, and AtCommandExecutors needs it to wire onReady - so AtClients creates it and shares it. AtCommandExecutors.resolveContext uses one when supplied, ANON when there is no atSign, and otherwise builds one - which keeps standalone builder callers working and stops a second clientId being minted. This also fixes a lost-metadata defect: every client built with withMonitoring(true) sent a from: carrying no clientId and no client version, because AtClients passed the raw config to Notifications.monitor while the context held the enriched one, and an explicit onReady replaced the context-based sequence. AtClientsTest pins this - confirmed to fail with the previous wiring restored. AtCommandExecutorContext gains a two-arg constructor, and its config is now never null and never modifiable - it is copied on construction, so a later change to the caller's map cannot alter what the connection sends. atSign and keys stay nullable because both states are load-bearing: a connection to the atDirectory / root server has no atSign, and one that only issues from: (or authenticates with CRAM before any keys exist) has no keys. A context with no atSign holds no challenge at all, so the shared ANON instance cannot leak one connection's state into another; setChallenge and consumeChallenge throw instead. Commands that need no client identity are unchanged - KeyCommands, PublicKeyCommands.getSharedByMe/ByOther, and SharedKeyCommands.getEncryptKey, whose atSign is the other party's - since an unread parameter would be worse than uniformity. AtClientImpl now holds the context instead of its own atSign/keys/config copies. No asserted command string changes; test edits are call sites only. Also fixes javadoc left mis-wrapped by the 100-column comment formatter, and two incorrect doc comments: SharedKeyCommands.put said the value would be "decrypted", and EnrollCommands.unrevoke was documented as "revoke". BREAKING CHANGE: the command signatures taking loose atSign / keys / config are removed rather than deprecated. SelfKeyCommands.get/put, SharedKeyCommands.get/put, PublicKeyCommands.get/put, Notifications.monitor, AuthenticationCommands.pkamAuthenticator and AuthenticationCommands.authenticateWithPkam now take an AtCommandExecutorContext; EnrollCommands.enroll, complete and approve likewise; and AtClientImpl.builder() takes context(...) in place of atSign(...), keys(...) and config(...). Callers using AtClients.builder() are unaffected. Closes #428 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jn2rsqSTPCBos8K9Xp2aAf
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.
- What I did
This is groundwork for porting the cryptographic agility changes.
Standardize the command layer on (AtCommandExecutor, AtCommandExecutorContext) as its leading arguments, and create exactly one context per connection in AtClients.createAtClient, passing it to both the executor builder and AtClientImpl.
The context cannot be created by AtClientImpl, which receives an already-built executor, and AtCommandExecutors needs it to wire onReady - so AtClients creates it and shares it. AtCommandExecutors.resolveContext uses one when supplied, ANON when there is no atSign, and otherwise builds one - which keeps standalone builder callers working and stops a second clientId being minted.
This also fixes a lost-metadata defect: every client built with withMonitoring(true) sent a from: carrying no clientId and no client version, because AtClients passed the raw config to Notifications.monitor while the context held the enriched one, and an explicit onReady replaced the context-based sequence. AtClientsTest pins this - confirmed to fail with the previous wiring restored.
- How I did it
AtCommandExecutorContext gains a two-arg constructor, and its config is now never null and never modifiable - it is copied on construction, so a later change to the caller's map cannot alter what the connection sends. atSign and keys stay nullable because both states are load-bearing: a connection to the atDirectory / root server has no atSign, and one that only issues from: (or authenticates with CRAM before any keys exist) has no keys. A context with no atSign holds no challenge at all, so the shared ANON instance cannot leak one connection's state into another; setChallenge and consumeChallenge throw instead.
Commands that need no client identity are unchanged - KeyCommands, PublicKeyCommands.getSharedByMe/ByOther, and SharedKeyCommands.getEncryptKey, whose atSign is the other party's - since an unread parameter would be worse than uniformity. AtClientImpl now holds the context instead of its own atSign/keys/config copies.
No asserted command string changes; test edits are call sites only.
Also fixes javadoc left mis-wrapped by the 100-column comment formatter, and two incorrect doc comments: SharedKeyCommands.put said the value would be "decrypted", and EnrollCommands.unrevoke was documented as "revoke".
BREAKING CHANGE: the command signatures taking loose atSign / keys / config are removed rather than deprecated. SelfKeyCommands.get/put, SharedKeyCommands.get/put, PublicKeyCommands.get/put, Notifications.monitor, AuthenticationCommands.pkamAuthenticator and AuthenticationCommands.authenticateWithPkam now take an AtCommandExecutorContext; EnrollCommands.enroll, complete and approve likewise; and AtClientImpl.builder() takes context(...) in place of atSign(...), keys(...) and config(...). Callers using AtClients.builder() are unaffected.
closes #428
- How to verify it
Run the unit tests and integration tests, review the new tests
- Description for the changelog
standardize the command layer on (AtCommandExecutor, AtCommandExecutorContext)