fix: Disable client when project token is missing - #189
Conversation
posthog-dotnet Compliance ReportDate: 2026-05-06 09:19:40 UTC
|
| Test | Status | Duration |
|---|---|---|
| Request Payload.Request With Person Properties Device Id | ❌ | 33ms |
| Request Payload.Flags Request Uses V2 Query Param | ❌ | 16ms |
| Request Payload.Flags Request Hits Flags Path Not Decide | ❌ | 4ms |
| Request Payload.Flags Request Omits Authorization Header | ❌ | 3ms |
| Request Payload.Token In Flags Body Matches Init | ❌ | 4ms |
| Request Payload.Groups Round Trip | ❌ | 4ms |
| Request Payload.Groups Default To Empty Object | ❌ | 3ms |
| Request Payload.Person Properties Distinct Id Auto Populated When Caller Omits It | ❌ | 4ms |
| Request Payload.Disable Geoip False Propagates As Geoip Disable False | ❌ | 4ms |
| Request Payload.Disable Geoip Omitted Defaults To False | ❌ | 3ms |
| Request Payload.Flag Keys To Evaluate Contains Only Requested Key | ❌ | 4ms |
| Request Lifecycle.No Flags Request On Init Alone | ✅ | 2ms |
| Request Lifecycle.No Flags Request On Normal Capture | ✅ | 163ms |
| Request Lifecycle.Two Flag Calls Produce Two Remote Requests | ❌ | 5ms |
| Request Lifecycle.Mock Response Value Is Returned To Caller | ❌ | 4ms |
| Side Effect Events.Get Feature Flag Captures Feature Flag Called Event | ❌ | 3ms |
Failures
request_payload.request_with_person_properties_device_id
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.flags_request_uses_v2_query_param
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.flags_request_hits_flags_path_not_decide
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.flags_request_omits_authorization_header
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.token_in_flags_body_matches_init
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.groups_round_trip
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.groups_default_to_empty_object
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.person_properties_distinct_id_auto_populated_when_caller_omits_it
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.disable_geoip_false_propagates_as_geoip_disable_false
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.disable_geoip_omitted_defaults_to_false
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_payload.flag_keys_to_evaluate_contains_only_requested_key
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_lifecycle.two_flag_calls_produce_two_remote_requests
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
request_lifecycle.mock_response_value_is_returned_to_caller
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
side_effect_events.get_feature_flag_captures_feature_flag_called_event
404, message='Not Found', url='http://sdk-adapter:8080/get_feature_flag'
bed79fb to
1ea64e2
Compare
|
@PostHog/team-client-libraries and @haacked i think this is what SDKs should do |
|
caef5ff to
e8527fc
Compare
haacked
left a comment
There was a problem hiding this comment.
A few suggestions in-line.
| AllFeatureFlagsOptions? options, | ||
| CancellationToken cancellationToken) | ||
| { | ||
| if (IsDisabled(nameof(GetAllFeatureFlagsAsync))) |
There was a problem hiding this comment.
suggestion: This method is async Task<…> but the disabled path returns synchronously, so the C# compiler still allocates the async state machine and walks ExecutionContext. GroupIdentifyAsync (line 182) shows the pattern: Task return, no async, Task.FromResult(...) on the fast path, delegate to a private async core for the real work.
Same applies to AliasAsync (148), IdentifyAsync (163), CaptureException (277), IsFeatureEnabledAsync (369), GetFeatureFlagAsync (395), GetRemoteConfigPayloadAsync (545), LoadFeatureFlagsAsync (748), GetLocalEvaluatorAsync (798).
Pairs with the cached-result singletons above to make the disabled path truly zero-allocation.
There was a problem hiding this comment.
Partially addressed — cached the no-op return values. I kept the async method structure intact to keep this fix focused and avoid a large control-flow refactor.
e8527fc to
21104bc
Compare
21104bc to
2c39054
Compare
Thanks and done. |
haacked
left a comment
There was a problem hiding this comment.
Some nits, but nothing major.
Summary
PostHogOptions.Disableduser-configurable flag (defaultfalse) and compute the effective disabled state inPostHogClientpersonal_api_keywhen it is not configured, including local-only feature flag evaluation and remote config payloadsTests
dotnet test tests/UnitTests/UnitTests.csproj --framework net8.0 --filter "FullyQualifiedName~TheDisabledClient|FullyQualifiedName~ThePersonalApiKeyProtectedMethods|FullyQualifiedName~LogsWarningWhenPersonalApiKey|FullyQualifiedName~LogsErrorWhenProjectTokenIsMissing|FullyQualifiedName~LogsWarningWhenProjectApiKeyIsUsed"dotnet test tests/UnitTests/UnitTests.csproj --framework net8.0(fails in existing CaptureException tests:CaptureExceptionWithInvalidFilePathInStackFrame,CaptureExceptionCauseIOFailureEmptyContext)Note: requested context files
context.mdandplan.mdwere not present in this checkout.