feat: auto-set anonymous for contexts without keys at build time#249
Open
kinyoklion wants to merge 4 commits intomainfrom
Open
feat: auto-set anonymous for contexts without keys at build time#249kinyoklion wants to merge 4 commits intomainfrom
kinyoklion wants to merge 4 commits intomainfrom
Conversation
Update documentation on LDAttributesBuilder.anonymous(), LDContextBuilder.kind(), LDClient.start(), and LDClient.identify() to explain that the SDK automatically generates and persists stable keys for anonymous contexts without keys. Co-Authored-By: rlamb@launchdarkly.com <kingdewman@gmail.com>
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
When a context kind is added without a key, the context is now
automatically set to anonymous at build time. This means
LDContextBuilder().kind('user').build() produces a valid anonymous
context rather than an invalid one. The SDK will generate and persist
a stable key for the context during start() or identify().
Updated documentation on anonymous(), kind(), start(), and identify()
to explain this behavior.
Co-Authored-By: rlamb@launchdarkly.com <kingdewman@gmail.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Address review feedback: _build() no longer mutates _anonymous as a side effect. Instead, an _anonymousExplicitlySet flag tracks whether anonymous() was called. When no key is provided and anonymous was not explicitly set, the context is automatically anonymous. When anonymous(false) was explicitly called with no key, the context remains invalid. Suppress 4 contract tests that expect invalid contexts for inputs without keys, as these now produce valid anonymous contexts per the new auto-anonymous behavior. Co-Authored-By: rlamb@launchdarkly.com <kingdewman@gmail.com>
Instead of suppressing contract tests, explicitly set anonymous(false) in _flattenedListToContext when the input doesn't have anonymous=true. This ensures the contract tests pass as before (keyless contexts without explicit anonymous=true remain invalid during JSON conversion), while the builder API auto-anonymous behavior is preserved for users who simply call kind() without a key. Co-Authored-By: rlamb@launchdarkly.com <kingdewman@gmail.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.
Requirements
Related issues
#222
Describe the solution you've provided
This PR makes a behavioral change to
LDAttributesBuilder._build()so that a context created without a key is automatically set to anonymous at build time (instead of being treated as invalid). The SDK will then generate and persist a stable UUID key duringstart()oridentify().This means
LDContextBuilder().kind('user').build()now produces a valid anonymous context rather than an invalid one.Behavioral logic in
_build():anonymousnever explicitly set → auto-anonymous (via localeffectiveAnonymous, no builder mutation).anonymous(false)explicitly called → invalid context (returns null).anonymous(true)explicitly called → anonymous as beforeAn
_anonymousExplicitlySetflag tracks whether.anonymous()was ever called, so_build()can distinguish "default false" from "explicitly set to false". The builder state is never mutated by_build().Contract test compatibility: Instead of suppressing contract tests, the contract test service (
_flattenedListToContext) now explicitly callsanonymous(false)when deserializing JSON contexts that don't haveanonymous: true. This preserves the existing contract test expectations (keyless JSON contexts remain invalid) while reserving the auto-anonymous behavior for the builder API.Documentation updates in four places:
LDAttributesBuilder.anonymous()— Explains auto-anonymous behavior when no key is provided, with code examples for both explicit and automatic anonymous contexts.LDContextBuilder.kind()— Corrected doc to explain that omitting the key makes the context automatically anonymous at build time.LDClient.start()— Notes that anonymous contexts without keys get auto-generated keys during startup.LDClient.identify()— Notes that anonymous contexts without keys get auto-generated keys before identify.Items for reviewer attention:
LDContextBuilder().kind('user').build()previously returned an invalid context; it now returns a valid anonymous context. Any code relying on this being invalid will behave differently._anonymousExplicitlySetlogic paths (auto-anonymous, explicit false + no key = invalid) are not covered by dedicated tests. Should tests be added?mergeContextpath:mergeContextcallsanonymous(attributes.anonymous)which will set_anonymousExplicitlySet = true. This means reconstructing a context from an existing one will always have anonymous explicitly set — verify this is acceptable.if (attributes['anonymous'] != true)check may callanonymous(false)redundantly aftersetValuealready processed it. This is harmless but could be cleaner.Describe alternatives you've considered
_anonymousdirectly in_build(), but per Bugbot and reviewer feedback, switched to a localeffectiveAnonymouscomputation to avoid side effects.anonymous(false)in the contract test service's JSON conversion path instead.Additional context
Verification was performed by:
ld_context_test.dart: 35 pass,anonymous_context_modifier_test.dart: 6 pass).LDContextBuilder().kind('user').build()(no explicit.anonymous(true)) against LaunchDarkly — the SDK successfully generated a UUID key and connected, confirming the auto-anonymous behavior works end-to-end.Note
Medium Risk
Behavioral change in core context validation/anonymous handling can alter analytics/indexing and any code that previously relied on keyless contexts being invalid; no new tests were added for the new branching logic.
Overview
Keyless contexts built via
LDContextBuilder.kind(...).build()now become valid by default: if no key is provided andanonymouswas never explicitly set,_build()treats the context asanonymous=trueso the SDK can later generate/persist a stable UUID key duringstart()/identify().To preserve JSON conversion semantics, the contract test service now explicitly applies
anonymous(false)when deserializing contexts unless the JSON setanonymous: true, preventing accidental auto-anonymous during JSON->builder reconstruction. Docs were updated onLDAttributesBuilder.anonymous,LDContextBuilder.kind, andLDClient.start/identifyto describe the new behavior.Written by Cursor Bugbot for commit 0615292. This will update automatically on new commits. Configure here.