Skip to content

FFESUPPORT-501: Fix subjectAttributes format and salt handling for precomputed flags#95

Merged
sameerank merged 4 commits intomainfrom
sameerank/FFESUPPORT-501-subject-attributes-and-salt-issues
Feb 5, 2026
Merged

FFESUPPORT-501: Fix subjectAttributes format and salt handling for precomputed flags#95
sameerank merged 4 commits intomainfrom
sameerank/FFESUPPORT-501-subject-attributes-and-salt-issues

Conversation

@sameerank
Copy link
Copy Markdown
Contributor

@sameerank sameerank commented Feb 5, 2026

🎟️ Fixes FFESUPPORT-501

Motivation and Context

EppoPrecomputedClient.initialize() was failing in production due to two issues:

  1. HTTP 400 errors: The API expects subjectAttributes in a nested format with numericAttributes and categoricalAttributes separated, but the iOS SDK was sending a flat dictionary
  2. Flags returning defaults: The SDK was base64-decoding the salt before MD5 hashing, but the API expects the salt to be used directly as a string, causing hash mismatches

Description

  • Added ContextAttributes struct that separates attributes into numericAttributes (integers/doubles) and categoricalAttributes (strings/booleans), matching the JS SDK implementation
  • Fixed salt handling in PrecomputedConfiguration.decode() to use salt directly without base64 decoding
  • Added wire format tests using shared test data from sdk-test-data
  • Added unit tests for ContextAttributes attribute separation logic

How has this been documented?

No documentation required - external API unchanged.

How has this been tested?

  • Added PrecomputedConfigurationWireTests that validates salt handling and flag assignments using shared test data from sdk-test-data/configuration-wire/precomputed-v1.json
Screenshot 2026-02-05 at 1 13 34 PM
  • Added ContextAttributes unit tests in PrecomputedRequestorTests to verify numeric/categorical attribute separation
Screenshot 2026-02-05 at 1 14 19 PM

…ed flags

- Send subjectAttributes as nested ContextAttributes with numericAttributes
  and categoricalAttributes separated
- Use salt directly as string for MD5 hashing instead of base64 decoding
- Update tests to use salt directly
- Add PrecomputedConfigurationWireTests using shared sdk-test-data
- Add ContextAttributes unit tests to PrecomputedRequestorTests
Copy link
Copy Markdown
Member

@leoromanovsky leoromanovsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool thanks for the follow up.


private func loadPrecomputedConfig() throws -> PrecomputedConfiguration {
let fileURL = Bundle.module.url(
forResource: "Resources/test-data/configuration-wire/precomputed-v1.json",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea testing against this 👍

Comment on lines +135 to +141
for (key, value) in attributes {
if value.isNumeric() {
numeric[key] = value
} else if !value.isNull() {
categorical[key] = value
}
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/// Tests the precomputed configuration wire format using shared test data from sdk-test-data.
class PrecomputedConfigurationWireTests: XCTestCase {

func testSaltUsedDirectlyForFlagKeyHashing() throws {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test I should have had using the shared test data to verify that we are using the salt as-is

XCTAssertTrue(decodingError.errorDescription?.contains("Failed to decode response") ?? false)
}

// MARK: - ContextAttributes Tests
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we have to do this with isolated unit tests instead of using the shared test data (which would typically be preferable) because there are cases where the SDKs cannot know if a numerical was meant to be categorical, e.g. "buildNumber"

// todo: make this a build argument (FF-1944)
public let sdkName = "ios"
public let sdkVersion = "5.3.1"
public let sdkVersion = "5.3.2"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No change to the public API, so I'm going with a patch bump here

@sameerank sameerank merged commit be98465 into main Feb 5, 2026
2 checks passed
@sameerank sameerank deleted the sameerank/FFESUPPORT-501-subject-attributes-and-salt-issues branch February 5, 2026 21:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants