fix(local-feature-flag-evaluator): define presence operator semantics - #49
Conversation
|
found this by doing PostHog/posthog-elixir#192 |
|
Just so I’m clear, under this proposal, There would be no way to have If that’s so, that seems problematic. What if the local environment knows the property is not set? There’s no way to communicate that without a remote eval fallback. I would think we either allow null to represent unset OR have a special sentinel value that means unset. |
Correct Given the current API limitations, this PR defines the safest behavior:
The spec cannot safely make a missing key evaluate to false, because omission does not distinguish known absence from an incomplete property map. I would only add a clarification that known absence cannot currently be represented and requires a future SDK and /flags API extension To fix this we'd need API change, but I'd say it'd not be a blocker for this change until we have proper API support to distinguish present/missing example
Without the /flags change, explicit absence could safely affect only evaluations resolved locally. That would be issue for tracking this PostHog/posthog#88947 |
|
the goal of this spec is to choose the best/correct behavior based on the API limitation so that all SDKs would evaluate in the same way, right now they dont |
haacked
left a comment
There was a problem hiding this comment.
LGTM! As discussed, representing not set locally is out of scope of this PR.
|
Agree with your reasoning. Out of curiosity, how do we handle is not set locally? Does that evaluate to true when property is missing given as you pointed out we can’t tell the difference between incomplete property map and omission? |
|
@haacked Great question. The flags service itself distinguishes partial from complete property context. With partial properties, Current SDK property inputs have no completeness or known-absence signal, so they should be treated as partial. Therefore the safe local behavior is:
Current SDKs disagree. Node and Rust treat a missing key as true, while most SDKs make the operator entirely inconclusive. Elixir PR #192 currently has the behavior that best matches the flags service's partial-property mode.
The mobile/client SDKs and analytics wrappers do not run this server-side local-definition evaluator, so they are not applicable. No SDK currently exposes an explicit known-absent set or a property-map completeness marker. I'll align SDKs with this new change here e16ea0a |
|
i think PostHog/posthog#52747 is related to that as well |
Summary
is_setusing property-key presence, including an explicitly present null value.is_not_setfor partial SDK property maps: present properties definitively do not match, while omitted properties remain inconclusive./flagsAPI inputs.Why
The authoritative flags-service runtime implements
is_setwith key presence and explicitly tests that a present JSON null matches. Foris_not_set, it distinguishes partial from complete property context. A present key does not match, a missing key in partial context is inconclusive, and a missing key matches only when the context is known to be complete.Server SDKs currently disagree on both operators. Node.js and Rust treat an omitted property as matching
is_not_set, which assumes the SDK property map is complete. Python, Go, PHP, Ruby, .NET, and the Android server SDK keep the operator inconclusive even when a property is present. Pending posthog-elixir#192 implements the required partial-property behavior and serves as the reference implementation.A missing key cannot safely produce a definitive presence result with the current SDK inputs because omission does not distinguish known absence from unavailable context. Adding that distinction is outside this change and requires a separate SDK evaluation option plus a corresponding
/flagsrequest contract.Validation
openspec validate --all --strict --no-interactive- 62 passed, 0 failedacceptance/private/local-feature-flag-evaluator.featurewithgherkin-officialgit diff --checke16ea0awith no actionable findings