From 2848d34a8e868adf36c9a13174415e212bf64d6a Mon Sep 17 00:00:00 2001 From: "linear-code[bot]" <222613912+linear-code[bot]@users.noreply.github.com> Date: Wed, 21 Oct 2026 17:22:14 +0000 Subject: [PATCH 1/2] feat(Flag Dependency): Evaluate flags that depend on other flags in local evaluation Port flagsmith-engine's context evaluator, including flag dependency, and run identity flags through it. Bump engine-test-data to v3.12.1 and run all of its test cases. Generated with [Linear](https://linear.app/flagsmith/agent-session/51c26f09-5fe3-44a8-8e3d-be2cf9ac50ff) Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com> --- .gitmodules | 4 +- lib/engine/evaluator.ex | 630 + lib/engine/json_path.ex | 132 + lib/engine/mappers.ex | 152 + lib/flagsmith_engine.ex | 186 +- lib/schemas/environment.ex | 3 +- .../environment_n9fbf9h3v4fFgH3U3ngWhb.json | 12086 ++++++++++++++++ test/support/engine-test-data | 2 +- test/unit/engine_test_data_test.exs | 66 + test/unit/environment_suite_test.exs | 2 +- test/unit/flag_dependency_test.exs | 106 + 11 files changed, 13198 insertions(+), 171 deletions(-) create mode 100644 lib/engine/evaluator.ex create mode 100644 lib/engine/json_path.ex create mode 100644 lib/engine/mappers.ex create mode 100644 test/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json create mode 100644 test/unit/engine_test_data_test.exs create mode 100644 test/unit/flag_dependency_test.exs diff --git a/.gitmodules b/.gitmodules index 2f5331f..84b8ac0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "test/support/engine-test-data"] path = test/support/engine-test-data - url = git@github.com:Flagsmith/engine-test-data.git - branch = v1.0.0 + url = https://github.com/Flagsmith/engine-test-data.git + branch = v3.12.1 diff --git a/lib/engine/evaluator.ex b/lib/engine/evaluator.ex new file mode 100644 index 0000000..281776f --- /dev/null +++ b/lib/engine/evaluator.ex @@ -0,0 +1,630 @@ +defmodule Flagsmith.Engine.Evaluator do + @moduledoc false + + alias Flagsmith.Engine.JSONPath + + @type context :: map() + @type flag_result :: %{String.t() => term()} + @type result :: %{String.t() => term()} + + @circular_dependency_reason "ERROR; code=CIRCULAR_DEPENDENCY" + + @doc """ + Get the flags and matching segments for an evaluation context, as specified by + https://github.com/Flagsmith/engine-test-data. + + Contexts and results are maps with string keys, matching their JSON form. + `features` and `segments` may also be given as lists of `{key, value}` tuples, + to keep the order that decides override ties and the order of segment results. + + Segment conditions may read other flags, e.g. `$.flags..enabled`. A flag + read this way is resolved with its own segment overrides, and features in a + dependency cycle are reported as `ERROR; code=CIRCULAR_DEPENDENCY`. + """ + @spec get_evaluation_result(context()) :: result() + def get_evaluation_result(context) do + context = enrich_context(context) + features = entries(context["features"]) + segments = entries(context["segments"]) + + evaluation = %{ + context: + Map.merge(context, %{"features" => Map.new(features), "segments" => Map.new(segments)}), + features: Map.new(features), + segments: Map.new(segments), + identity_key: get_in(context, ["identity", "key"]), + segment_keys_by_feature_name: segment_keys_by_feature_name(segments) + } + + state = %{ + resolved: %{}, + cyclic: MapSet.new(), + used: false, + cycle_hits: 0, + # most recent first + resolving: [], + segment_matches: %{} + } + + {segment_results, segment_overrides, state} = evaluate_segments(evaluation, segments, state) + flags = evaluate_features(evaluation, features, segment_overrides) + + flags = + case state.used do + false -> + flags + + true -> + # flags resolved for conditions are cycle-guarded, so take precedence + state.cyclic + |> Enum.reduce(Map.merge(flags, state.resolved), fn feature_name, flags -> + case flags do + %{^feature_name => flag} -> + Map.put(flags, feature_name, %{flag | "reason" => @circular_dependency_reason}) + + _ -> + flags + end + end) + end + + %{"flags" => flags, "segments" => segment_results} + end + + defp enrich_context(%{"identity" => %{"identifier" => identifier} = identity} = context) do + case identity["key"] do + key when key in [nil, ""] -> + put_in(context, ["identity", "key"], "#{context["environment"]["key"]}_#{identifier}") + + _ -> + context + end + end + + defp enrich_context(context), do: context + + defp entries(nil), do: [] + defp entries(map) when is_map(map), do: Enum.to_list(map) + defp entries(list) when is_list(list), do: list + + defp segment_keys_by_feature_name(segments) do + segments + |> Enum.flat_map(fn {segment_key, segment} -> + Enum.map(overrides(segment), &{&1["name"], segment_key}) + end) + |> Enum.group_by(&elem(&1, 0), &elem(&1, 1)) + end + + defp overrides(segment), do: segment["overrides"] || [] + + defp evaluate_segments(evaluation, segments, state) do + {results, overrides, state, _cycle_hits} = + Enum.reduce(segments, {[], %{}, state, state.cycle_hits}, fn {_key, segment}, + {results, overrides, state, + cycle_hits} -> + {matches, state} = context_in_segment?(evaluation, state, segment) + + cond do + state.cycle_hits != cycle_hits -> + # a verdict resting on an unresolvable flag is unsound either way + {results, overrides, state, state.cycle_hits} + + not matches -> + {results, overrides, state, cycle_hits} + + true -> + overrides = + Enum.reduce(overrides(segment), overrides, fn override, overrides -> + name = override["name"] + + case wins_over?(override, overrides[name]) do + true -> Map.put(overrides, name, {override, segment["name"]}) + false -> overrides + end + end) + + {[segment_result(segment) | results], overrides, state, cycle_hits} + end + end) + + {Enum.reverse(results), overrides, state} + end + + defp segment_result(%{"name" => name} = segment) do + case segment["metadata"] do + metadata when metadata in [nil, %{}] -> %{"name" => name} + metadata -> %{"name" => name, "metadata" => metadata} + end + end + + # lower priority wins, the first seen wins a tie + defp wins_over?(_candidate, nil), do: true + + defp wins_over?(candidate, {incumbent, _segment_name}), + do: priority(candidate) < priority(incumbent) + + defp priority(%{"priority" => :negative_infinity}), do: {0, 0} + defp priority(%{"priority" => priority}) when is_number(priority), do: {1, priority} + defp priority(_), do: {2, 0} + + defp evaluate_features(evaluation, features, segment_overrides) do + Map.new(features, fn {_key, %{"name" => name} = feature} -> + flag = + case segment_overrides do + %{^name => {override, segment_name}} -> + flag_result(evaluation, override, "TARGETING_MATCH; segment=#{segment_name}") + + _ -> + flag_result(evaluation, feature, fallback_reason(evaluation, name)) + end + + {name, flag} + end) + end + + defp fallback_reason(%{segment_keys_by_feature_name: keys}, name) + when is_map_key(keys, name), + do: "DEFAULT" + + defp fallback_reason(_, _), do: "STATIC" + + defp flag_result(evaluation, feature, reason) do + {value, variant, reason} = + case {evaluation.identity_key, feature["variants"]} do + {key, [_ | _] = variants} when not is_nil(key) -> + select_variant(feature, key, variants, reason) + + _ -> + {feature["value"], nil, reason} + end + + result = %{ + "enabled" => feature["enabled"], + "name" => feature["name"], + "reason" => reason, + "value" => value, + "variant" => variant + } + + case feature["metadata"] do + metadata when metadata in [nil, %{}] -> result + metadata -> Map.put(result, "metadata", metadata) + end + end + + defp select_variant(feature, identity_key, variants, reason) do + percentage = Flagsmith.Engine.percentage_from_ids([to_str(feature["key"]), identity_key]) + + variants + |> Enum.sort_by(& &1["priority"]) + |> Enum.reduce_while(0, fn %{"weight" => weight} = variant, start -> + limit = weight + start + + case start <= percentage and percentage < limit do + true -> + {:halt, {variant["value"], variant["key"], "SPLIT; weight=#{to_str(weight)}"}} + + false -> + {:cont, limit} + end + end) + |> case do + limit when is_number(limit) -> {feature["value"], "control", reason} + selected -> selected + end + end + + defp read_flag(evaluation, state, feature_name) do + case state.resolved do + %{^feature_name => flag} -> + {flag, state} + + _ -> + state = resolve_feature(evaluation, %{state | used: true}, feature_name) + {state.resolved[feature_name], state} + end + end + + defp resolve_feature(evaluation, %{resolving: resolving} = state, feature_name) do + cond do + feature_name in resolving -> + cycle = [feature_name | Enum.take_while(resolving, &(&1 != feature_name))] + + %{ + state + | cyclic: MapSet.union(state.cyclic, MapSet.new(cycle)), + cycle_hits: state.cycle_hits + 1 + } + + not is_map_key(evaluation.features, feature_name) -> + state + + true -> + {override, state} = + segment_override( + evaluation, + %{state | resolving: [feature_name | resolving]}, + feature_name + ) + + state = %{state | resolving: resolving} + + cond do + feature_name in state.cyclic -> + state + + override -> + {feature, segment_name} = override + flag = flag_result(evaluation, feature, "TARGETING_MATCH; segment=#{segment_name}") + put_in(state, [:resolved, feature_name], flag) + + true -> + feature = evaluation.features[feature_name] + flag = flag_result(evaluation, feature, fallback_reason(evaluation, feature_name)) + put_in(state, [:resolved, feature_name], flag) + end + end + end + + defp segment_override(evaluation, state, feature_name) do + evaluation.segment_keys_by_feature_name + |> Map.get(feature_name, []) + |> Enum.reduce({nil, state}, fn segment_key, {override, state} -> + case matches_segment?(evaluation, state, segment_key) do + {false, state} -> + {override, state} + + {true, state} -> + segment = evaluation.segments[segment_key] + + override = + segment + |> overrides() + |> Enum.filter(&(&1["name"] == feature_name)) + |> Enum.reduce(override, fn candidate, override -> + case wins_over?(candidate, override) do + true -> {candidate, segment["name"]} + false -> override + end + end) + + {override, state} + end + end) + end + + defp matches_segment?(evaluation, state, segment_key) do + case state.segment_matches do + %{^segment_key => matches} -> + {matches, state} + + _ -> + cycle_hits = state.cycle_hits + segment = evaluation.segments[segment_key] + {matches, state} = context_in_segment?(evaluation, state, segment) + + case state.cycle_hits != cycle_hits do + # a verdict resting on an unresolvable flag is not a match, nor memoised + true -> {false, state} + false -> {matches, put_in(state, [:segment_matches, segment_key], matches)} + end + end + end + + defp context_in_segment?(evaluation, state, %{"rules" => [_ | _] = rules} = segment) do + all(rules, state, &rule_matches?(evaluation, &2, &1, segment["key"])) + end + + defp context_in_segment?(_evaluation, state, _segment), do: {false, state} + + defp rule_matches?(evaluation, state, rule, segment_key) do + case matching_function(rule["type"]) do + nil -> + {false, state} + + matching_function -> + {matches_conditions, state} = + case rule["conditions"] do + [_ | _] = conditions -> + matching_function.( + conditions, + state, + &condition_matches?(evaluation, &2, &1, segment_key) + ) + + _ -> + {true, state} + end + + {matches_rules, state} = + case rule["rules"] do + [_ | _] = rules -> + matching_function.(rules, state, &rule_matches?(evaluation, &2, &1, segment_key)) + + _ -> + {true, state} + end + + {matches_conditions and matches_rules, state} + end + end + + defp matching_function("ALL"), do: &all/3 + defp matching_function("ANY"), do: &any/3 + defp matching_function("NONE"), do: &none/3 + defp matching_function(_), do: nil + + defp all(items, state, fun) do + Enum.reduce_while(items, {true, state}, fn item, {_, state} -> + case fun.(item, state) do + {true, state} -> {:cont, {true, state}} + {false, state} -> {:halt, {false, state}} + end + end) + end + + defp any(items, state, fun) do + Enum.reduce_while(items, {false, state}, fn item, {_, state} -> + case fun.(item, state) do + {true, state} -> {:halt, {true, state}} + {false, state} -> {:cont, {false, state}} + end + end) + end + + defp none(items, state, fun) do + {matches, state} = any(items, state, fun) + {not matches, state} + end + + defp condition_matches?(evaluation, state, condition, segment_key) do + property = condition["property"] + operator = condition["operator"] + + {context_value, state} = + case operator == "PERCENTAGE_SPLIT" and property in [nil, ""] do + # legacy segments split on the identity key + true -> {evaluation.identity_key, state} + false -> get_context_value(evaluation, state, property || "") + end + + {matches_condition?(operator, condition["value"], context_value, segment_key), state} + end + + defp matches_condition?("IN", segment_value, context_value, _segment_key) do + # Guard against comparing boolean values to numeric strings. + context_value = + case is_integer(context_value) do + true -> Integer.to_string(context_value) + false -> context_value + end + + is_binary(context_value) and MapSet.member?(in_values(segment_value), context_value) + end + + defp matches_condition?("PERCENTAGE_SPLIT", _segment_value, nil, _segment_key), do: false + + defp matches_condition?("PERCENTAGE_SPLIT", segment_value, context_value, segment_key) do + case parse_float(segment_value) do + {:ok, float} -> + Flagsmith.Engine.percentage_from_ids([to_str(segment_key), to_str(context_value)]) <= + float + + :error -> + false + end + end + + defp matches_condition?("IS_NOT_SET", _segment_value, context_value, _segment_key), + do: is_nil(context_value) + + defp matches_condition?("IS_SET", _segment_value, context_value, _segment_key), + do: not is_nil(context_value) + + defp matches_condition?(_operator, _segment_value, nil, _segment_key), do: false + + defp matches_condition?("NOT_CONTAINS", segment_value, context_value, _segment_key), + do: is_binary(context_value) and not String.contains?(context_value, to_str(segment_value)) + + defp matches_condition?("REGEX", segment_value, context_value, _segment_key) do + case :re.compile(to_str(segment_value), [:unicode, :ucp]) do + {:ok, regex} -> + :re.run(to_str(context_value), regex, [:anchored, capture: :none]) == :match + + {:error, _} -> + false + end + end + + defp matches_condition?("MODULO", segment_value, context_value, _segment_key) + when is_number(context_value) and is_binary(segment_value) do + with [divisor, remainder] <- String.split(segment_value, "|"), + {:ok, divisor} when divisor != 0 <- parse_float(divisor), + {:ok, remainder} <- parse_float(remainder) do + modulo(context_value, divisor) == remainder + else + _ -> false + end + end + + defp matches_condition?(operator, segment_value, context_value, _segment_key) + when operator in [ + "EQUAL", + "NOT_EQUAL", + "GREATER_THAN", + "GREATER_THAN_INCLUSIVE", + "LESS_THAN", + "LESS_THAN_INCLUSIVE", + "CONTAINS" + ] do + case is_binary(context_value) and semver?(segment_value) do + true -> + with {:ok, context_version} <- Version.parse(context_value), + {:ok, segment_version} <- + Version.parse(String.replace_suffix(segment_value, ":semver", "")) do + compare_versions(operator, Version.compare(context_version, segment_version)) + else + _ -> false + end + + false -> + case cast_to_type_of(context_value, segment_value) do + {:ok, match_value} -> compare(operator, context_value, match_value) + :error -> false + end + end + end + + defp matches_condition?(_operator, _segment_value, _context_value, _segment_key), do: false + + defp compare_versions("EQUAL", order), do: order == :eq + defp compare_versions("NOT_EQUAL", order), do: order != :eq + defp compare_versions("GREATER_THAN", order), do: order == :gt + defp compare_versions("GREATER_THAN_INCLUSIVE", order), do: order in [:gt, :eq] + defp compare_versions("LESS_THAN", order), do: order == :lt + defp compare_versions("LESS_THAN_INCLUSIVE", order), do: order in [:lt, :eq] + defp compare_versions(_, _), do: false + + defp compare("EQUAL", context_value, match_value), do: context_value == match_value + defp compare("NOT_EQUAL", context_value, match_value), do: context_value != match_value + defp compare("GREATER_THAN", context_value, match_value), do: context_value > match_value + + defp compare("GREATER_THAN_INCLUSIVE", context_value, match_value), + do: context_value >= match_value + + defp compare("LESS_THAN", context_value, match_value), do: context_value < match_value + + defp compare("LESS_THAN_INCLUSIVE", context_value, match_value), + do: context_value <= match_value + + defp compare("CONTAINS", context_value, match_value) + when is_binary(context_value) and is_binary(match_value), + do: String.contains?(context_value, match_value) + + defp compare(_, _, _), do: false + + defp cast_to_type_of(context_value, segment_value) when is_boolean(context_value), + do: {:ok, segment_value not in ["False", "false"]} + + defp cast_to_type_of(context_value, segment_value) when is_integer(context_value), + do: parse_integer(segment_value) + + defp cast_to_type_of(context_value, segment_value) when is_float(context_value), + do: parse_float(segment_value) + + defp cast_to_type_of(_context_value, segment_value), do: {:ok, to_str(segment_value)} + + defp semver?(value), do: is_binary(value) and String.ends_with?(value, ":semver") + + defp in_values(values) when is_list(values), do: MapSet.new(values, &to_str/1) + + defp in_values("[" <> _ = values) do + case Jason.decode(values) do + {:ok, decoded} when is_list(decoded) -> MapSet.new(decoded, &to_str/1) + _ -> MapSet.new(String.split(values, ",")) + end + end + + defp in_values(values) when is_binary(values), do: MapSet.new(String.split(values, ",")) + defp in_values(_), do: MapSet.new() + + # floored, as in Python + defp modulo(dividend, divisor) do + remainder = :math.fmod(dividend, divisor) + + case remainder != 0 and remainder < 0 != divisor < 0 do + true -> remainder + divisor + false -> remainder + end + end + + defp get_context_value(evaluation, state, "$." <> _ = property) do + with nil <- trait_value(evaluation, property), + {:ok, segments} <- JSONPath.compile(property) do + {value, state} = query(evaluation, state, segments) + {to_context_value(value), state} + else + :error -> {nil, state} + value -> {to_context_value(value), state} + end + end + + defp get_context_value(evaluation, state, property), + do: {to_context_value(trait_value(evaluation, property)), state} + + defp trait_value(%{context: context}, trait_key) do + case context do + %{"identity" => %{"traits" => %{^trait_key => value}}} -> value + _ -> nil + end + end + + defp query(evaluation, state, [{:name, "flags"}, {:name, feature_name} | segments]) do + {flag, state} = read_flag(evaluation, state, feature_name) + {find_value(flag, segments), state} + end + + defp query(_evaluation, state, [{:name, "flags"} | segments]), + do: {find_value(state.resolved, segments), state} + + defp query(evaluation, state, segments), + do: {find_value(evaluation.context, segments), state} + + defp find_value(nil, _segments), do: nil + + defp find_value(data, segments) do + case JSONPath.find_one(data, segments) do + {:ok, value} when is_binary(value) or is_number(value) or is_boolean(value) -> value + _ -> nil + end + end + + @doc """ + Coerce a value to a context value: a string, number, boolean or nil. + Number-like strings are coerced to numbers. + """ + @spec to_context_value(term()) :: String.t() | number() | boolean() | nil + def to_context_value(value) when is_binary(value) do + cond do + Regex.match?(~r/^-?[0-9]+$/, value) -> String.to_integer(value) + Regex.match?(~r/^-?[0-9]+\.[0-9]+$/, value) -> String.to_float(value) + true -> value + end + end + + def to_context_value(value) when is_number(value) or is_boolean(value) or is_nil(value), + do: value + + def to_context_value(%Decimal{exp: 0} = value), do: Decimal.to_integer(value) + def to_context_value(%Decimal{} = value), do: Decimal.to_float(value) + def to_context_value(value), do: to_str(value) + + defp parse_integer(value) when is_binary(value) do + case Integer.parse(String.trim(value)) do + {integer, ""} -> {:ok, integer} + _ -> :error + end + end + + defp parse_integer(_), do: :error + + defp parse_float(value) when is_binary(value) do + case Float.parse(String.trim(value)) do + {float, ""} -> {:ok, float} + _ -> :error + end + end + + defp parse_float(_), do: :error + + # as Python's `str` + defp to_str(value) when is_binary(value), do: value + defp to_str(true), do: "True" + defp to_str(false), do: "False" + defp to_str(nil), do: "None" + defp to_str(value) when is_integer(value), do: Integer.to_string(value) + defp to_str(value) when is_float(value), do: Float.to_string(value) + defp to_str(value) when is_atom(value), do: Atom.to_string(value) + defp to_str(%Version{} = value), do: Version.to_string(value) + defp to_str(value), do: inspect(value) +end diff --git a/lib/engine/json_path.ex b/lib/engine/json_path.ex new file mode 100644 index 0000000..99c3a26 --- /dev/null +++ b/lib/engine/json_path.ex @@ -0,0 +1,132 @@ +defmodule Flagsmith.Engine.JSONPath do + @moduledoc false + + # RFC 9535 subset: name, wildcard and index selectors, one per segment + + @type segment :: {:name, String.t()} | {:index, integer()} | :wildcard + + @blank [?\s, ?\t, ?\n, ?\r] + + @doc """ + Compile a JSONPath query into a list of segments. Returns `:error` for + queries that are invalid, or use syntax outside the supported subset. + """ + @spec compile(String.t()) :: {:ok, list(segment())} | :error + def compile("$" <> rest), do: segments(rest, []) + def compile(_), do: :error + + @doc """ + Find the first node selected by a compiled query in `data`. + """ + @spec find_one(term(), list(segment())) :: {:ok, term()} | :error + def find_one(data, []), do: {:ok, data} + + def find_one(data, [segment | rest]) do + data + |> select(segment) + |> Enum.find_value(:error, fn node -> + case find_one(node, rest) do + {:ok, _} = found -> found + :error -> nil + end + end) + end + + @doc """ + The nodes a single segment selects from `data`. + """ + @spec select(term(), segment()) :: list(term()) + def select(data, {:name, name}) when is_map(data) do + case Map.fetch(data, name) do + {:ok, value} -> [value] + :error -> [] + end + end + + def select(data, {:index, index}) when is_list(data) do + case Enum.fetch(data, index) do + {:ok, value} -> [value] + :error -> [] + end + end + + def select(data, :wildcard) when is_map(data), do: Map.values(data) + def select(data, :wildcard) when is_list(data), do: data + def select(_, _), do: [] + + defp segments("", acc), do: {:ok, Enum.reverse(acc)} + defp segments(<>, acc) when c in @blank, do: segments(rest, acc) + defp segments(".*" <> rest, acc), do: segments(rest, [:wildcard | acc]) + defp segments(".." <> _, _), do: :error + + defp segments("." <> rest, acc) do + case member_name(rest) do + {"", _} -> :error + {name, rest} -> segments(rest, [{:name, name} | acc]) + end + end + + defp segments("[" <> rest, acc) do + with {:ok, selector, rest} <- selector(skip_blank(rest)), + "]" <> rest <- skip_blank(rest) do + segments(rest, [selector | acc]) + else + _ -> :error + end + end + + defp segments(_, _), do: :error + + defp member_name(string), do: member_name(string, "") + + defp member_name(<>, name) + when c in ?a..?z or c in ?A..?Z or c == ?_ or c in 0x80..0xD7FF or + c in 0xE000..0x10FFFF or (c in ?0..?9 and name != ""), + do: member_name(rest, name <> <>) + + defp member_name(rest, name), do: {name, rest} + + defp selector("*" <> rest), do: {:ok, :wildcard, rest} + + defp selector(<>) when delimiter in [?', ?"], + do: string(rest, delimiter, "") + + defp selector(string) do + case Integer.parse(string) do + {index, rest} -> {:ok, {:index, index}, rest} + :error -> :error + end + end + + defp string(<>, delimiter, acc), do: {:ok, {:name, acc}, rest} + defp string("\\b" <> rest, delimiter, acc), do: string(rest, delimiter, acc <> "\b") + defp string("\\f" <> rest, delimiter, acc), do: string(rest, delimiter, acc <> "\f") + defp string("\\n" <> rest, delimiter, acc), do: string(rest, delimiter, acc <> "\n") + defp string("\\r" <> rest, delimiter, acc), do: string(rest, delimiter, acc <> "\r") + defp string("\\t" <> rest, delimiter, acc), do: string(rest, delimiter, acc <> "\t") + defp string("\\/" <> rest, delimiter, acc), do: string(rest, delimiter, acc <> "/") + defp string("\\\\" <> rest, delimiter, acc), do: string(rest, delimiter, acc <> "\\") + + defp string(<>, delimiter, acc), + do: string(rest, delimiter, acc <> <>) + + defp string(<<"\\u", hex::binary-size(4), rest::binary>>, delimiter, acc) do + case Integer.parse(hex, 16) do + {codepoint, ""} when codepoint not in 0xD800..0xDFFF -> + string(rest, delimiter, acc <> <>) + + _ -> + :error + end + end + + defp string("\\" <> _, _, _), do: :error + + defp string(<>, delimiter, acc), + do: string(rest, delimiter, acc <> <>) + + defp string(_, _, _), do: :error + + defp skip_blank(<>) when c in @blank, do: skip_blank(rest) + defp skip_blank(string), do: string +end diff --git a/lib/engine/mappers.ex b/lib/engine/mappers.ex new file mode 100644 index 0000000..856a9b2 --- /dev/null +++ b/lib/engine/mappers.ex @@ -0,0 +1,152 @@ +defmodule Flagsmith.Engine.Mappers do + @moduledoc false + + alias Flagsmith.Schemas.{Environment, Features, Identity, Segments, Traits} + + @identity_overrides_segment_key "identity_overrides" + + @doc """ + Map an environment, an identity, and optionally traits overriding those of + the identity, to an evaluation context for `Flagsmith.Engine.Evaluator`. + + Feature and segment contexts carry the feature state or segment they were + mapped from in their metadata, so that results can be mapped back to them. + """ + @spec map_environment_identity_to_context( + Environment.t(), + Identity.t(), + list(Traits.Trait.t()) + ) :: Flagsmith.Engine.Evaluator.context() + def map_environment_identity_to_context( + %Environment{ + api_key: api_key, + feature_states: feature_states, + project: %Environment.Project{segments: segments} + } = environment, + %Identity{identifier: identifier, identity_features: identity_features} = identity, + override_traits \\ [] + ) do + identity = Identity.set_env_key(identity, environment) + + traits = + case override_traits do + [_ | _] -> override_traits + _ -> identity.traits + end + + %{ + "environment" => %{"key" => api_key, "name" => environment.name}, + "identity" => %{ + "identifier" => identifier, + "key" => to_string(Identity.composite_key(identity)), + "traits" => Map.new(traits, &map_trait/1) + }, + "features" => Enum.map(feature_states, &{&1.feature.name, map_feature_state(&1)}), + "segments" => + Enum.map(segments, &{to_string(&1.id), map_segment(&1)}) ++ + map_identity_overrides(identifier, identity_features) + } + end + + defp map_trait(%Traits.Trait{trait_key: key, trait_value: %Traits.Trait.Value{value: value}}), + do: {key, map_trait_value(value)} + + defp map_trait(%Traits.Trait{trait_key: key, trait_value: value}), + do: {key, map_trait_value(value)} + + defp map_trait_value(%Version{} = value), do: Version.to_string(value) + defp map_trait_value(value), do: value + + defp map_segment(%Segments.Segment{id: id, name: name} = segment) do + %{ + "key" => to_string(id), + "name" => name, + "rules" => Enum.map(segment.rules, &map_rule/1), + "overrides" => Enum.map(segment.feature_states, &map_feature_state/1), + "metadata" => %{segment: segment} + } + end + + defp map_rule(%Segments.Segment.Rule{type: type, rules: rules, conditions: conditions}) do + %{ + "type" => to_string(type), + "rules" => Enum.map(rules, &map_rule/1), + "conditions" => + Enum.map(conditions, fn %Segments.Segment.Condition{} = condition -> + %{ + "property" => condition.property_ || "", + "operator" => to_string(condition.operator), + "value" => condition.value + } + end) + } + end + + defp map_feature_state(%Environment.FeatureState{} = feature_state) do + feature_context = %{ + "key" => Environment.FeatureState.get_hashing_id(feature_state), + "name" => feature_state.feature.name, + "enabled" => feature_state.enabled, + "value" => feature_state.feature_state_value, + "metadata" => %{feature_state: feature_state} + } + + feature_context = + case feature_state.multivariate_feature_state_values do + [_ | _] = values -> Map.put(feature_context, "variants", Enum.map(values, &map_variant/1)) + _ -> feature_context + end + + case feature_state.feature_segment do + %Environment.FeatureState.FeatureSegment{priority: priority} -> + Map.put(feature_context, "priority", priority) + + nil -> + feature_context + end + end + + defp map_variant(%Environment.MultivariateFeatureStateValue{} = value) do + %{ + "value" => value.multivariate_feature_option.value, + "weight" => value.percentage_allocation, + "priority" => value.id || value.mv_fs_value_uuid + } + end + + # a segment matching the identity alone, taking precedence over any other + defp map_identity_overrides(_identifier, []), do: [] + + defp map_identity_overrides(identifier, identity_features) do + [ + {@identity_overrides_segment_key, + %{ + "key" => @identity_overrides_segment_key, + "name" => @identity_overrides_segment_key, + "rules" => [ + %{ + "type" => "ALL", + "conditions" => [ + %{ + "property" => "$.identity.identifier", + "operator" => "IN", + "value" => [identifier] + } + ] + } + ], + "overrides" => + Enum.map(identity_features, fn %Features.FeatureState{} = feature_state -> + %{ + "key" => "", + "name" => feature_state.feature.name, + "enabled" => feature_state.enabled, + "value" => feature_state.feature_state_value, + "priority" => :negative_infinity, + "metadata" => %{feature_state: feature_state} + } + end) + }} + ] + end +end diff --git a/lib/flagsmith_engine.ex b/lib/flagsmith_engine.ex index 388103e..3e8c7cf 100644 --- a/lib/flagsmith_engine.ex +++ b/lib/flagsmith_engine.ex @@ -10,6 +10,7 @@ defmodule Flagsmith.Engine do } alias Traits.Trait + alias Flagsmith.Engine.{Evaluator, Mappers} alias Flagsmith.Schemas.Types @condition_operators Flagsmith.Schemas.Types.Operator.values(:atoms) @@ -61,24 +62,20 @@ defmodule Flagsmith.Engine do Environment.t(), Identity.t(), override_traits :: list(Traits.Trait.t()) - ) :: list(Environment.FeatureState.t()) + ) :: list(Environment.FeatureState.t() | Features.FeatureState.t()) def get_identity_feature_states( - %Environment{ - feature_states: fs, - project: %Environment.Project{segments: segments} - } = env, - %Identity{identity_features: identity_features} = identity, + %Environment{feature_states: fs} = env, + %Identity{} = identity, override_traits \\ [] ) do - with identity <- Identity.set_env_key(identity, env), - segment_features <- - get_identity_applicable_segments(segments, identity, override_traits), - prioritized <- clean_segments_by_priority(segment_features), - replaced <- replace_segment_features(fs, prioritized), - pre_features <- replace_identity_features(replaced, identity_features), - final_features <- replace_multivariates(pre_features, identity) do - final_features - end + %{"flags" => flags} = evaluate_identity(env, identity, override_traits) + + Enum.map(fs, fn %{feature: %{name: name}} -> + %{"enabled" => enabled, "value" => value, "metadata" => %{feature_state: feature_state}} = + Map.fetch!(flags, name) + + %{feature_state | enabled: enabled, feature_state_value: value} + end) end @doc """ @@ -90,160 +87,17 @@ defmodule Flagsmith.Engine do Identity.t(), override_traits :: list(Traits.Trait.t()) ) :: list(Segments.IdentitySegment.t()) - def get_identity_segments( - %Environment{ - project: %Environment.Project{segments: segments} - } = env, - identity, - override_traits \\ [] - ) do - with identity <- Identity.set_env_key(identity, env), - segments <- - get_identity_applicable_segments(segments, identity, override_traits), - replaced <- Enum.map(segments, &Segments.IdentitySegment.from_segment/1) do - replaced - end - end - - defp clean_segments_by_priority(segments) do - # keep an ordered table by index so we can retrieve the segments in order - # at the end when manipulating them - table_segments = :ets.new(:temp_segments, [:ordered_set]) - # keep a table to track the feature_states by name so we can compare in case - # of same name fs_s - table_features = :ets.new(:temp_track, []) - - # reduce through all the segments, using an accumulator for keeping track of the - # current index of the segment - Enum.reduce(segments, 0, fn %Segments.Segment{feature_states: segment_fs} = segment, index -> - # for each segment, iterate through those segment's feature states - Enum.each(segment_fs, fn %Environment.FeatureState{feature: feature} = fs -> - # lookup on the tracking table if we have an item by the feature name - case :ets.lookup(table_features, feature.name) do - [] -> - # if we don't, then we insert the initial one, keyed by name, and with - # the full feature_state, index, and an empty list - :ets.insert(table_features, {feature.name, fs, index, []}) - - # if we do then we check if the existing one in the table is higher - # priority than the current one being iterated - [{_, %Environment.FeatureState{} = existing, existing_index, to_rem}] -> - case Environment.FeatureState.is_higher_priority?(existing, fs) do - true -> - # if it's then it means the current one, will need to be removed - # and as such we add the current iteration index to the list to - # remove but keep the other tuple elements as they were - :ets.insert( - table_features, - {feature.name, existing, existing_index, [index | to_rem]} - ) - - false -> - # if it's not, then we re-insert the tuple (since it's a set table - # using the same key, feature.name, will replace the existing item) - # but we now substitute the feature state by the current one, - # the index by the current one, and instead add the existing one - # (the one that was previously the highest priority one) to the list - # to be removed - :ets.insert( - table_features, - {feature.name, fs, index, [existing_index | to_rem]} - ) - end - end - end) - - # finally we insert the segment, keyed by the index (so it keeps the order as - # the segments table is an ordered set), but unmodified - # this first iteration is just to find any duplicate feature states - :ets.insert(table_segments, {index, segment}) - - # lastly we increment the accumulator by one so next iteration has the correct - # index - index + 1 - end) - - # now we convert the tracking table into a list and iterate through it - :ets.tab2list(table_features) - |> Enum.each(fn - {_name, _, _index, []} -> - # feature state has no conflicting states because the to remove list is empty - :ok - - {name, %Environment.FeatureState{featurestate_uuid: uuid}, _index, to_remove} -> - # since we have the name, full feature state, and a list of indexes - # corresponding to segments that had this same feature state but with lower - # priority we iterate the list of the indexes - Enum.each(to_remove, fn index -> - # we grab the segment for that index from the segments table - [{_, %Segments.Segment{feature_states: segment_fs} = segment}] = - :ets.lookup(table_segments, index) - - # and now we filter the feature states of that segment, that match the name - # of this one, but not the uuid - new_segment_fs = - Enum.reject(segment_fs, fn %Environment.FeatureState{feature: feature} = fs -> - feature.name == name && uuid != fs.featurestate_uuid - end) - - # and lastly we replace that segment in the segments table, with the new - # filtered feature states - :ets.insert(table_segments, {index, %{segment | feature_states: new_segment_fs}}) - end) - end) - - # lastly we fold through the right side (since it's an ordered set, it will go - # from smaller to bigger, and folding through the right starts at the end) - # and we just accumulate all segments into a new list - # since the segments in this table were updated in the last step we get the - # "cleaned" of duplicate features list of segments in the same original order - final_segments = - :ets.foldr(fn {_index, segment}, acc -> [segment | acc] end, [], table_segments) - - :ets.delete(table_segments) - :ets.delete(table_features) - - final_segments - end - - defp replace_multivariates(features, %Identity{} = identity) do - features - |> Enum.map(fn %{feature: %{type: type}} = feature_state -> - case type do - "MULTIVARIATE" -> - uuid = Environment.FeatureState.get_hashing_id(feature_state) - - mv_fs = Map.get(feature_state, :multivariate_feature_state_values, []) - - percentage = percentage_from_ids([uuid, Identity.composite_key(identity)]) + def get_identity_segments(%Environment{} = env, identity, override_traits \\ []) do + %{"segments" => segments} = evaluate_identity(env, identity, override_traits) - case find_first_multivariate(mv_fs, percentage) do - {:ok, new_value} -> %{feature_state | feature_state_value: new_value} - _ -> feature_state - end - - _ -> - feature_state - end - end) + for %{"metadata" => %{segment: segment}} <- segments, + do: Segments.IdentitySegment.from_segment(segment) end - defp find_first_multivariate(mvs, percentage) do - mvs - |> Enum.sort_by(fn %{id: id, mv_fs_value_uuid: uuid} -> - case id do - nil -> uuid - _ -> id - end - end) - |> Enum.reduce_while(0, fn %{percentage_allocation: p_allot} = mv, start_perc -> - limit = p_allot + start_perc - - case start_perc <= percentage and percentage < limit do - true -> {:halt, Environment.FeatureState.extract_multivariate_value(mv)} - _ -> {:cont, limit} - end - end) + defp evaluate_identity(env, identity, override_traits) do + env + |> Mappers.map_environment_identity_to_context(identity, override_traits) + |> Evaluator.get_evaluation_result() end @doc """ diff --git a/lib/schemas/environment.ex b/lib/schemas/environment.ex index 007637d..f290dd8 100644 --- a/lib/schemas/environment.ex +++ b/lib/schemas/environment.ex @@ -9,6 +9,7 @@ defmodule Flagsmith.Schemas.Environment do @primary_key {:id, :id, autogenerate: false} typed_embedded_schema do field(:api_key, :string) + field(:name, :string) embeds_many(:feature_states, __MODULE__.FeatureState) embeds_many(:identity_overrides, Flagsmith.Schemas.Identity) embeds_one(:project, __MODULE__.Project) @@ -21,7 +22,7 @@ defmodule Flagsmith.Schemas.Environment do @spec changeset(__MODULE__.t(), map()) :: Ecto.Changeset.t() def changeset(struct \\ %__MODULE__{}, params) do struct - |> cast(params, [:api_key, :id]) + |> cast(params, [:api_key, :id, :name]) |> cast_embed(:feature_states) |> cast_embed(:identity_overrides) |> cast_embed(:project) diff --git a/test/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json b/test/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json new file mode 100644 index 0000000..9e5e7d4 --- /dev/null +++ b/test/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json @@ -0,0 +1,12086 @@ +{ + "environment": { + "project": { + "hide_disabled_flags": false, + "segments": [ + { + "name": "regular_segment", + "feature_states": [ + { + "feature_state_value": "segment_override", + "multivariate_feature_state_values": [], + "django_id": 81027, + "feature": { + "id": 15058, + "type": "STANDARD", + "name": "string_feature" + }, + "enabled": false + } + ], + "id": 4267, + "rules": [ + { + "type": "ALL", + "conditions": [], + "rules": [ + { + "type": "ANY", + "conditions": [ + { + "value": "40", + "property_": "age", + "operator": "LESS_THAN" + } + ], + "rules": [] + }, + { + "type": "ANY", + "conditions": [ + { + "value": "21", + "property_": "age", + "operator": "GREATER_THAN_INCLUSIVE" + } + ], + "rules": [] + }, + { + "type": "ANY", + "conditions": [ + { + "value": "green", + "property_": "favourite_colour", + "operator": "EQUAL" + }, + { + "value": "blue", + "property_": "favourite_colour", + "operator": "EQUAL" + } + ], + "rules": [] + } + ] + } + ] + }, + { + "name": "10_percent", + "feature_states": [ + { + "feature_state_value": "", + "multivariate_feature_state_values": [], + "django_id": 81026, + "feature": { + "id": 15060, + "type": "STANDARD", + "name": "basic_flag" + }, + "enabled": true + } + ], + "id": 4268, + "rules": [ + { + "type": "ALL", + "conditions": [], + "rules": [ + { + "type": "ANY", + "conditions": [ + { + "value": "0.1", + "property_": "", + "operator": "PERCENTAGE_SPLIT" + } + ], + "rules": [] + } + ] + } + ] + }, + { + "feature_states": [ + { + "feature_state_value": "segment_two_override_priority_0", + "multivariate_feature_state_values": [], + "django_id": 78978, + "feature": { + "id": 15058, + "type": "STANDARD", + "name": "string_feature" + }, + "enabled": true, + "feature_segment": { "priority": 0 }, + "featurestate_uuid": "1545809c-e97f-4a1f-9e67-8b4f2b396aa6" + } + ], + "id": 16, + "name": "segment_two", + "rules": [ + { + "conditions": [], + "rules": [ + { + "conditions": [ + { + "operator": "EQUAL", + "property_": "two", + "value": "2" + } + ], + "rules": [], + "type": "ANY" + } + ], + "type": "ALL" + } + ] + }, + { + "feature_states": [ + { + "feature_state_value": "segment_three_override_priority_1", + "multivariate_feature_state_values": [], + "django_id": 78977, + "feature": { + "id": 15058, + "type": "STANDARD", + "name": "string_feature" + }, + "enabled": true, + "feature_segment": { + "priority": 1 + }, + "featurestate_uuid": "1545809c-e97f-4a1f-9e67-8b4f2b396aa7" + } + ], + "id": 17, + "name": "segment_three", + "rules": [ + { + "conditions": [], + "rules": [ + { + "conditions": [ + { + "operator": "EQUAL", + "property_": "three", + "value": "3" + } + ], + "rules": [], + "type": "ANY" + } + ], + "type": "ALL" + } + ] + } + ], + "name": "Edge API Test Project", + "id": 5359, + "organisation": { + "persist_trait_data": true, + "name": "Flagsmith", + "feature_analytics": false, + "stop_serving_flags": false, + "id": 13 + } + }, + "api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "feature_states": [ + { + "feature_state_value": "foo", + "multivariate_feature_state_values": [], + "django_id": 78978, + "feature": { + "id": 15058, + "type": "STANDARD", + "name": "string_feature" + }, + "enabled": true + }, + { + "feature_state_value": 1234, + "multivariate_feature_state_values": [], + "django_id": 78980, + "feature": { + "id": 15059, + "type": "STANDARD", + "name": "integer_feature" + }, + "enabled": true + }, + { + "feature_state_value": null, + "multivariate_feature_state_values": [], + "django_id": 78982, + "feature": { + "id": 15060, + "type": "STANDARD", + "name": "basic_flag" + }, + "enabled": false + }, + { + "feature_state_value": "12.34", + "multivariate_feature_state_values": [], + "django_id": 78984, + "feature": { + "id": 15061, + "type": "STANDARD", + "name": "float_feature" + }, + "enabled": true + }, + { + "feature_state_value": "foo", + "multivariate_feature_state_values": [ + { + "id": 3404, + "multivariate_feature_option": { + "value": "baz" + }, + "percentage_allocation": 30 + }, + { + "id": 3402, + "multivariate_feature_option": { + "value": "bar" + }, + "percentage_allocation": 30 + } + ], + "django_id": 78986, + "feature": { + "id": 15062, + "type": "MULTIVARIATE", + "name": "mv_feature" + }, + "enabled": true + } + ], + "id": 12561 + }, + "identities_and_responses": [ + { + "identity": { + "identity_uuid": "10f435fb-66fa-4e5e-9787-75729a4e8373", + "identifier": "identity_in_two_segments", + "created_date": "2021-12-15T14:40:00.880997", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_identity_in_two_segments", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "two", + "trait_value": "2" + }, + { + "trait_key": "three", + "trait_value": "3" + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32102998 + }, + "response": { + "traits": [ + { + "trait_key": "two", + "trait_value": "2" + }, + { + "trait_key": "three", + "trait_value": "3" + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "segment_two_override_priority_0", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "10f435fb-66fa-4e5e-9787-75729a4e8372", + "identifier": "54463d93-392f-493a-90b5-a1d3afe60f4b", + "created_date": "2021-12-15T14:40:00.880997", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_54463d93-392f-493a-90b5-a1d3afe60f4b", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 49 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32102998 + }, + "response": { + "traits": [ + { + "id": 26678015, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678016, + "trait_key": "age", + "trait_value": 49 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "275b5d01-6ffb-4183-9c4e-b031a4b4af56", + "identifier": "7765d342-16c5-4c1c-a461-459d39f65b85", + "created_date": "2021-12-15T14:40:00.881011", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_7765d342-16c5-4c1c-a461-459d39f65b85", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 93 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103670 + }, + "response": { + "traits": [ + { + "id": 26678279, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678280, + "trait_key": "age", + "trait_value": 93 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "baebd517-e00e-4d53-843d-8e3db194c6aa", + "identifier": "ce99d7bb-2fbd-4fb3-8c4d-0f4a11c5a9aa", + "created_date": "2021-12-15T14:40:00.881018", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_ce99d7bb-2fbd-4fb3-8c4d-0f4a11c5a9aa", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 56 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103671 + }, + "response": { + "traits": [ + { + "id": 26678281, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678282, + "trait_key": "age", + "trait_value": 56 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "6e707eed-851d-487c-996b-4fc207c8b95d", + "identifier": "7fb675cf-91fc-439e-8e5f-896bbaa46319", + "created_date": "2021-12-15T14:40:00.881024", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_7fb675cf-91fc-439e-8e5f-896bbaa46319", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 71 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103674 + }, + "response": { + "traits": [ + { + "id": 26678283, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678284, + "trait_key": "age", + "trait_value": 71 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "8e3fe9c7-5ec7-4547-a4d1-6b90a0b25cd4", + "identifier": "f0ca10b8-7088-4336-ae8c-5332e91f1554", + "created_date": "2021-12-15T14:40:00.881031", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_f0ca10b8-7088-4336-ae8c-5332e91f1554", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 88 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103676 + }, + "response": { + "traits": [ + { + "id": 26678285, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678286, + "trait_key": "age", + "trait_value": 88 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "dfb7b7ec-510c-4367-8a00-a5692cb53fb9", + "identifier": "ef981b6d-22d8-4daa-ab2d-f3f26db80a86", + "created_date": "2021-12-15T14:40:00.881037", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_ef981b6d-22d8-4daa-ab2d-f3f26db80a86", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 84 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103677 + }, + "response": { + "traits": [ + { + "id": 26678287, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678288, + "trait_key": "age", + "trait_value": 84 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "639b6c09-c52d-4b57-ab5a-aac5d0b5a3f7", + "identifier": "a2f85378-ea82-44c0-8998-be477402379c", + "created_date": "2021-12-15T14:40:00.881045", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_a2f85378-ea82-44c0-8998-be477402379c", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 78 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103679 + }, + "response": { + "traits": [ + { + "id": 26678290, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678291, + "trait_key": "age", + "trait_value": 78 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "a1862f60-16f4-4658-b495-f05c6ff3c6f5", + "identifier": "64ebc978-1f6a-4c22-8f5b-8b0f83478ef1", + "created_date": "2021-12-15T14:40:00.881051", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_64ebc978-1f6a-4c22-8f5b-8b0f83478ef1", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 85 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103681 + }, + "response": { + "traits": [ + { + "id": 26678292, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678293, + "trait_key": "age", + "trait_value": 85 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "0133a745-c508-436c-b142-6fb214e6984a", + "identifier": "2db1db6a-2dab-4416-8510-b2a99db4f05a", + "created_date": "2021-12-15T14:40:00.881058", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_2db1db6a-2dab-4416-8510-b2a99db4f05a", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 60 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103682 + }, + "response": { + "traits": [ + { + "id": 26678294, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678295, + "trait_key": "age", + "trait_value": 60 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "fd9ebd93-4acb-4402-b923-92f74dda62fa", + "identifier": "9f7d2eb7-e01c-4bec-9738-5eaeaa6bf776", + "created_date": "2021-12-15T14:40:00.881064", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_9f7d2eb7-e01c-4bec-9738-5eaeaa6bf776", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 51 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103683 + }, + "response": { + "traits": [ + { + "id": 26678296, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678297, + "trait_key": "age", + "trait_value": 51 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "8e619996-500f-430e-b234-3cf8c7f83161", + "identifier": "e5af06dd-d3a1-4f53-9185-8989b6eaa848", + "created_date": "2021-12-15T14:40:00.881070", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_e5af06dd-d3a1-4f53-9185-8989b6eaa848", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 6 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103684 + }, + "response": { + "traits": [ + { + "id": 26678298, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678299, + "trait_key": "age", + "trait_value": 6 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "f22be96e-d364-4017-8929-7771446a861e", + "identifier": "81b634c1-fde0-4d32-af2b-2ddd08d5dee6", + "created_date": "2021-12-15T14:40:00.881076", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_81b634c1-fde0-4d32-af2b-2ddd08d5dee6", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 66 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103685 + }, + "response": { + "traits": [ + { + "id": 26678300, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678301, + "trait_key": "age", + "trait_value": 66 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "601bb6b9-8e55-4b3c-8709-9f047dc30711", + "identifier": "dbcc4f61-44c2-4117-a5fd-16237b66f46d", + "created_date": "2021-12-15T14:40:00.881082", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_dbcc4f61-44c2-4117-a5fd-16237b66f46d", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 35 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103686 + }, + "response": { + "traits": [ + { + "id": 26678302, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678303, + "trait_key": "age", + "trait_value": 35 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "fa5753f0-3e0e-4b4b-9386-a8ed5fb60322", + "identifier": "388b793f-5843-46c9-af6b-a942b52527b2", + "created_date": "2021-12-15T14:40:00.881088", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_388b793f-5843-46c9-af6b-a942b52527b2", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 30 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103688 + }, + "response": { + "traits": [ + { + "id": 26678304, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678305, + "trait_key": "age", + "trait_value": 30 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 81027, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "segment_override", + "enabled": false, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "bd2749dd-4026-4d79-83c3-3882df2643f8", + "identifier": "3719f827-9c23-4956-b82a-7c2f5102479f", + "created_date": "2021-12-15T14:40:00.881095", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_3719f827-9c23-4956-b82a-7c2f5102479f", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 77 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103689 + }, + "response": { + "traits": [ + { + "id": 26678306, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678307, + "trait_key": "age", + "trait_value": 77 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "448ee1bf-6417-4688-a2a2-d2172773a94a", + "identifier": "db0436cb-ede2-42e4-b2d5-65af13e0852a", + "created_date": "2021-12-15T14:40:00.881100", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_db0436cb-ede2-42e4-b2d5-65af13e0852a", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 48 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103690 + }, + "response": { + "traits": [ + { + "id": 26678308, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678309, + "trait_key": "age", + "trait_value": 48 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "8b4a3afc-4d75-456c-b6d2-542170cd068b", + "identifier": "397cd01d-c6a1-451c-8795-4c9686c22a3b", + "created_date": "2021-12-15T14:40:00.881106", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_397cd01d-c6a1-451c-8795-4c9686c22a3b", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 86 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103692 + }, + "response": { + "traits": [ + { + "id": 26678310, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678311, + "trait_key": "age", + "trait_value": 86 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "871d212c-6b59-4c23-b3e3-e7a695ebc3c9", + "identifier": "32fd6b46-69d0-4123-8e35-ca4401e8bc3e", + "created_date": "2021-12-15T14:40:00.881112", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_32fd6b46-69d0-4123-8e35-ca4401e8bc3e", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 63 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103693 + }, + "response": { + "traits": [ + { + "id": 26678312, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678313, + "trait_key": "age", + "trait_value": 63 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "b428ae53-8688-452e-ad9d-450ed99aa4b1", + "identifier": "31f5d2d7-3736-478c-a887-e77c16cc8dfd", + "created_date": "2021-12-15T14:40:00.881118", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_31f5d2d7-3736-478c-a887-e77c16cc8dfd", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 37 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103695 + }, + "response": { + "traits": [ + { + "id": 26678314, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678315, + "trait_key": "age", + "trait_value": 37 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "82fd8c76-9943-454d-9c35-1f68af410aea", + "identifier": "15ef44aa-34b5-4366-a201-c80e33d9f169", + "created_date": "2021-12-15T14:40:00.881124", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_15ef44aa-34b5-4366-a201-c80e33d9f169", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 32 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103696 + }, + "response": { + "traits": [ + { + "id": 26678316, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678317, + "trait_key": "age", + "trait_value": 32 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "6e04dd89-0028-4f2c-b87f-17e71e414085", + "identifier": "2d6d8b94-504c-437e-afd2-c84cc4e72b8b", + "created_date": "2021-12-15T14:40:00.881130", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_2d6d8b94-504c-437e-afd2-c84cc4e72b8b", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 83 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103699 + }, + "response": { + "traits": [ + { + "id": 26678318, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678319, + "trait_key": "age", + "trait_value": 83 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "c49440f9-1b03-464b-8d98-4cdd7bd8480d", + "identifier": "20e6204b-e396-4d4b-a861-bb136c276ac2", + "created_date": "2021-12-15T14:40:00.881135", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_20e6204b-e396-4d4b-a861-bb136c276ac2", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 68 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103700 + }, + "response": { + "traits": [ + { + "id": 26678320, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678321, + "trait_key": "age", + "trait_value": 68 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "575cac45-a94d-4b91-ae86-10f692c30aa2", + "identifier": "c8159d13-3b99-4355-84df-c8e541d55384", + "created_date": "2021-12-15T14:40:00.881142", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_c8159d13-3b99-4355-84df-c8e541d55384", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 76 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103702 + }, + "response": { + "traits": [ + { + "id": 26678322, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678323, + "trait_key": "age", + "trait_value": 76 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "fd29ee25-7b53-4947-8910-a7e261ae9ef7", + "identifier": "42c798b6-1a36-4cf3-8df0-b6347020323a", + "created_date": "2021-12-15T14:40:00.881148", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_42c798b6-1a36-4cf3-8df0-b6347020323a", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 62 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103703 + }, + "response": { + "traits": [ + { + "id": 26678324, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678325, + "trait_key": "age", + "trait_value": 62 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "491088a0-337c-4ebb-a6f0-d116ebaf5d0f", + "identifier": "170effbe-4388-49a5-9872-700688b628b9", + "created_date": "2021-12-15T14:40:00.881153", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_170effbe-4388-49a5-9872-700688b628b9", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 69 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103704 + }, + "response": { + "traits": [ + { + "id": 26678326, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678327, + "trait_key": "age", + "trait_value": 69 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "aa5a77b1-241d-4af4-a580-370d85965f03", + "identifier": "042b3a46-4575-419a-8a2f-62baa3226668", + "created_date": "2021-12-15T14:40:00.881161", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_042b3a46-4575-419a-8a2f-62baa3226668", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 20 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103705 + }, + "response": { + "traits": [ + { + "id": 26678328, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678329, + "trait_key": "age", + "trait_value": 20 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "40cdc7cd-765b-4f71-8b1e-7fa723116201", + "identifier": "83295382-6d39-4db1-ac66-1ebb6e98b70e", + "created_date": "2021-12-15T14:40:00.881167", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_83295382-6d39-4db1-ac66-1ebb6e98b70e", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 91 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103706 + }, + "response": { + "traits": [ + { + "id": 26678330, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678331, + "trait_key": "age", + "trait_value": 91 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "c136ba1f-1bdb-43d3-af72-c1a7e33677de", + "identifier": "3debf4d7-3aff-4a8e-98fe-35d3add7f9fb", + "created_date": "2021-12-15T14:40:00.881173", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_3debf4d7-3aff-4a8e-98fe-35d3add7f9fb", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 92 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103707 + }, + "response": { + "traits": [ + { + "id": 26678332, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678333, + "trait_key": "age", + "trait_value": 92 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "b349658d-8aac-4fc7-bd64-c48a4d143c14", + "identifier": "fc300e2a-b1b8-4408-8830-676e47abaf2c", + "created_date": "2021-12-15T14:40:00.881178", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_fc300e2a-b1b8-4408-8830-676e47abaf2c", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 34 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103708 + }, + "response": { + "traits": [ + { + "id": 26678334, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678335, + "trait_key": "age", + "trait_value": 34 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 81027, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "segment_override", + "enabled": false, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "24e4d0fa-6ea5-4773-8abb-44f79048d2a9", + "identifier": "56a8c68b-5015-47dd-97ee-0d727eb16266", + "created_date": "2021-12-15T14:40:00.881184", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_56a8c68b-5015-47dd-97ee-0d727eb16266", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 78 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103709 + }, + "response": { + "traits": [ + { + "id": 26678336, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678337, + "trait_key": "age", + "trait_value": 78 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "5de2cf7f-93f4-4d08-8aa3-381d9b1e3d42", + "identifier": "8e660bf8-cffa-46e3-878a-111627965710", + "created_date": "2021-12-15T14:40:00.881190", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_8e660bf8-cffa-46e3-878a-111627965710", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 44 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103710 + }, + "response": { + "traits": [ + { + "id": 26678338, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678339, + "trait_key": "age", + "trait_value": 44 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "febef74c-1a54-4ca6-83c5-e205a8b570e2", + "identifier": "269c4565-50fa-4e4d-9d1b-e349545c9b1b", + "created_date": "2021-12-15T14:40:00.881196", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_269c4565-50fa-4e4d-9d1b-e349545c9b1b", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 56 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103712 + }, + "response": { + "traits": [ + { + "id": 26678340, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678341, + "trait_key": "age", + "trait_value": 56 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "5077957d-8af4-4400-835d-8859017d4f19", + "identifier": "fe0b7a97-f9f9-4ec9-b1d8-142939493321", + "created_date": "2021-12-15T14:40:00.881202", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_fe0b7a97-f9f9-4ec9-b1d8-142939493321", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 56 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103714 + }, + "response": { + "traits": [ + { + "id": 26678342, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678343, + "trait_key": "age", + "trait_value": 56 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "6b06b383-bef7-40b6-9eb6-c94868b4e8f1", + "identifier": "efb574f7-091b-45fa-800d-ebec477efb51", + "created_date": "2021-12-15T14:40:00.881208", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_efb574f7-091b-45fa-800d-ebec477efb51", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 29 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103715 + }, + "response": { + "traits": [ + { + "id": 26678344, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678345, + "trait_key": "age", + "trait_value": 29 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "24ef7912-df97-4c1a-98d4-c9b3c0c294a0", + "identifier": "82cd7c27-6ae9-471e-9b8a-d9829383b489", + "created_date": "2021-12-15T14:40:00.881214", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_82cd7c27-6ae9-471e-9b8a-d9829383b489", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 52 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103716 + }, + "response": { + "traits": [ + { + "id": 26678346, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678347, + "trait_key": "age", + "trait_value": 52 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "77566c33-28ab-4e89-9eb0-782fc26aebeb", + "identifier": "727ae8b6-f421-453c-9310-408150fbe28c", + "created_date": "2021-12-15T14:40:00.881220", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_727ae8b6-f421-453c-9310-408150fbe28c", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 66 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103718 + }, + "response": { + "traits": [ + { + "id": 26678348, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678349, + "trait_key": "age", + "trait_value": 66 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "d27a61ad-300f-4f4c-b88f-d9c8b4eabdce", + "identifier": "b3305fe0-77ac-4a1b-995e-94c413c686d0", + "created_date": "2021-12-15T14:40:00.881226", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_b3305fe0-77ac-4a1b-995e-94c413c686d0", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 24 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103719 + }, + "response": { + "traits": [ + { + "id": 26678350, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678351, + "trait_key": "age", + "trait_value": 24 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "e3331902-c64e-49df-a1fc-a07226991f0c", + "identifier": "c99e2bda-f55d-4964-bdd2-80ecfd00297d", + "created_date": "2021-12-15T14:40:00.881232", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_c99e2bda-f55d-4964-bdd2-80ecfd00297d", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 75 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103722 + }, + "response": { + "traits": [ + { + "id": 26678352, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678353, + "trait_key": "age", + "trait_value": 75 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "fa599660-3914-465b-b2f4-b363fa9cd3c2", + "identifier": "67476160-7c89-4d5c-bc1a-22ef4a8b2168", + "created_date": "2021-12-15T14:40:00.881238", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_67476160-7c89-4d5c-bc1a-22ef4a8b2168", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 88 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103724 + }, + "response": { + "traits": [ + { + "id": 26678354, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678355, + "trait_key": "age", + "trait_value": 88 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "dcffa2e6-c6d5-41c0-a7d4-5123dd6f6f0e", + "identifier": "b1cc98db-4e99-4f2c-a364-ef6382864188", + "created_date": "2021-12-15T14:40:00.881244", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_b1cc98db-4e99-4f2c-a364-ef6382864188", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 12 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103725 + }, + "response": { + "traits": [ + { + "id": 26678356, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678357, + "trait_key": "age", + "trait_value": 12 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "70fdb139-3a53-46ae-8da3-ad0a3ab62313", + "identifier": "11586d45-02f1-48ac-b640-741447251909", + "created_date": "2021-12-15T14:40:00.881249", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_11586d45-02f1-48ac-b640-741447251909", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 22 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103727 + }, + "response": { + "traits": [ + { + "id": 26678359, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678360, + "trait_key": "age", + "trait_value": 22 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "032abbac-93de-4ae0-b2ef-41695bc28fa7", + "identifier": "9515c224-5adc-4e44-bc39-21942779c323", + "created_date": "2021-12-15T14:40:00.881255", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_9515c224-5adc-4e44-bc39-21942779c323", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 83 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103728 + }, + "response": { + "traits": [ + { + "id": 26678363, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678364, + "trait_key": "age", + "trait_value": 83 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "2f85e99a-8685-4ec3-896a-64cf36872c35", + "identifier": "dc6b85e3-e03b-4019-8b6d-97b1d7d25492", + "created_date": "2021-12-15T14:40:00.881261", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_dc6b85e3-e03b-4019-8b6d-97b1d7d25492", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 47 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103730 + }, + "response": { + "traits": [ + { + "id": 26678365, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678366, + "trait_key": "age", + "trait_value": 47 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "3da8f9a1-c795-4d66-babf-39f22432556e", + "identifier": "70f674c4-0474-46aa-ac39-0d7a373fafca", + "created_date": "2021-12-15T14:40:00.881267", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_70f674c4-0474-46aa-ac39-0d7a373fafca", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 62 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103731 + }, + "response": { + "traits": [ + { + "id": 26678367, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678368, + "trait_key": "age", + "trait_value": 62 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "dbb45f9e-a894-4acd-8127-fe0a370468be", + "identifier": "85457200-feeb-468a-91ac-e6397254429a", + "created_date": "2021-12-15T14:40:00.881273", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_85457200-feeb-468a-91ac-e6397254429a", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 60 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103733 + }, + "response": { + "traits": [ + { + "id": 26678369, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678370, + "trait_key": "age", + "trait_value": 60 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "c04d3ee7-1044-4d88-8deb-8e6ad4020d1b", + "identifier": "46e87d76-34ca-410d-ac4c-67400770c398", + "created_date": "2021-12-15T14:40:00.881279", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_46e87d76-34ca-410d-ac4c-67400770c398", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 64 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103735 + }, + "response": { + "traits": [ + { + "id": 26678371, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678372, + "trait_key": "age", + "trait_value": 64 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "f9590820-76bb-4979-8ee8-cb31a1c800af", + "identifier": "ff74f26a-e832-465b-a165-375b1f70905a", + "created_date": "2021-12-15T14:40:00.881287", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_ff74f26a-e832-465b-a165-375b1f70905a", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 33 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103737 + }, + "response": { + "traits": [ + { + "id": 26678374, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678375, + "trait_key": "age", + "trait_value": 33 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "5c7e29fa-e380-48e6-b721-f7b47a329966", + "identifier": "c2ff801e-e145-411d-ba68-9dd2b9871bfe", + "created_date": "2021-12-15T14:40:00.881293", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_c2ff801e-e145-411d-ba68-9dd2b9871bfe", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 97 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103738 + }, + "response": { + "traits": [ + { + "id": 26678376, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678377, + "trait_key": "age", + "trait_value": 97 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "5b945288-e15b-43a1-880f-c93ff6f4cffb", + "identifier": "5fd8e83e-bd87-42e7-8c2a-fd31960feb72", + "created_date": "2021-12-15T14:40:00.881299", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_5fd8e83e-bd87-42e7-8c2a-fd31960feb72", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 8 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103739 + }, + "response": { + "traits": [ + { + "id": 26678378, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678379, + "trait_key": "age", + "trait_value": 8 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "380a4595-2d3d-4d3c-aecd-861a4ff1b05f", + "identifier": "2dbbc953-31b3-4bf4-9f63-a09bd37baf78", + "created_date": "2021-12-15T14:40:00.881304", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_2dbbc953-31b3-4bf4-9f63-a09bd37baf78", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 85 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103741 + }, + "response": { + "traits": [ + { + "id": 26678380, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678381, + "trait_key": "age", + "trait_value": 85 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "3006cc06-24d3-4819-8722-e6e994c6878d", + "identifier": "2af98d3d-be2f-4bee-b7ae-83c53e1b2811", + "created_date": "2021-12-15T14:40:00.881310", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_2af98d3d-be2f-4bee-b7ae-83c53e1b2811", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 7 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103743 + }, + "response": { + "traits": [ + { + "id": 26678382, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678383, + "trait_key": "age", + "trait_value": 7 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "e40de32b-bf2b-4ed4-b5a4-a5883a30adb6", + "identifier": "b21bd1e2-bb87-4135-aca7-e30f465de632", + "created_date": "2021-12-15T14:40:00.881316", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_b21bd1e2-bb87-4135-aca7-e30f465de632", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 72 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103744 + }, + "response": { + "traits": [ + { + "id": 26678384, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678385, + "trait_key": "age", + "trait_value": 72 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "10c294e0-06b2-47b8-96c9-842a9d19410e", + "identifier": "96fbbd8f-b5f4-4267-a2db-9f6848dcb20a", + "created_date": "2021-12-15T14:40:00.881322", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_96fbbd8f-b5f4-4267-a2db-9f6848dcb20a", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 72 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103746 + }, + "response": { + "traits": [ + { + "id": 26678386, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678387, + "trait_key": "age", + "trait_value": 72 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "c5f06308-bf71-4f47-bcd1-baee81e9f0db", + "identifier": "b8f06d73-0430-438d-b788-d91851449908", + "created_date": "2021-12-15T14:40:00.881328", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_b8f06d73-0430-438d-b788-d91851449908", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 33 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103747 + }, + "response": { + "traits": [ + { + "id": 26678388, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678389, + "trait_key": "age", + "trait_value": 33 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "1d48c04d-879e-4554-a0bf-c50638ea7945", + "identifier": "430f2a5c-dc93-497f-be0c-859687126d95", + "created_date": "2021-12-15T14:40:00.881334", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_430f2a5c-dc93-497f-be0c-859687126d95", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 97 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103748 + }, + "response": { + "traits": [ + { + "id": 26678390, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678391, + "trait_key": "age", + "trait_value": 97 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "3c9392ec-4c55-45e9-a8ee-60f6e1cd053f", + "identifier": "c3483e1f-ac4e-4e1e-b398-bedde811f441", + "created_date": "2021-12-15T14:40:00.881339", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_c3483e1f-ac4e-4e1e-b398-bedde811f441", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 98 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103750 + }, + "response": { + "traits": [ + { + "id": 26678392, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678393, + "trait_key": "age", + "trait_value": 98 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "264fd0b7-d2ac-499b-8cb2-d5e321f28fea", + "identifier": "65e8ea3f-6f3f-4eee-8ad5-30c7a7c7bfe4", + "created_date": "2021-12-15T14:40:00.881345", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_65e8ea3f-6f3f-4eee-8ad5-30c7a7c7bfe4", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 16 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103754 + }, + "response": { + "traits": [ + { + "id": 26678394, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678395, + "trait_key": "age", + "trait_value": 16 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "c3adcad5-cee3-4c9b-a1bd-204767c426ac", + "identifier": "cbaa7fae-9453-448a-bff1-d571be7c8a6b", + "created_date": "2021-12-15T14:40:00.881351", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_cbaa7fae-9453-448a-bff1-d571be7c8a6b", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 76 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103757 + }, + "response": { + "traits": [ + { + "id": 26678396, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678397, + "trait_key": "age", + "trait_value": 76 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "1e4962d0-8dbe-48cf-a5a2-f91a3329d665", + "identifier": "3ecde417-838e-4469-90a9-d7e925200b51", + "created_date": "2021-12-15T14:40:00.881357", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_3ecde417-838e-4469-90a9-d7e925200b51", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 46 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103760 + }, + "response": { + "traits": [ + { + "id": 26678398, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678399, + "trait_key": "age", + "trait_value": 46 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "c9e9802c-1bfc-478e-8a13-48f4db8c4780", + "identifier": "555bb037-cc46-47de-b0fa-4bcab906f5e7", + "created_date": "2021-12-15T14:40:00.881362", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_555bb037-cc46-47de-b0fa-4bcab906f5e7", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 97 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103761 + }, + "response": { + "traits": [ + { + "id": 26678400, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678401, + "trait_key": "age", + "trait_value": 97 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "814cc5e7-d6e6-4cab-9f0d-2e023816bd2e", + "identifier": "57fd428e-b41c-4e5f-b47d-de9faed376e3", + "created_date": "2021-12-15T14:40:00.881368", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_57fd428e-b41c-4e5f-b47d-de9faed376e3", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 80 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103763 + }, + "response": { + "traits": [ + { + "id": 26678402, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678403, + "trait_key": "age", + "trait_value": 80 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "a56babd1-7c0d-4f29-ad0f-99905bc993a4", + "identifier": "933949d7-b731-4f3a-a2dc-3d83d0beb1ea", + "created_date": "2021-12-15T14:40:00.881374", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_933949d7-b731-4f3a-a2dc-3d83d0beb1ea", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 88 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103764 + }, + "response": { + "traits": [ + { + "id": 26678404, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678405, + "trait_key": "age", + "trait_value": 88 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "65571c7a-ff3c-45f9-9760-ba25d7460e9c", + "identifier": "a78cf315-d2d8-4d04-b075-e9aba7421706", + "created_date": "2021-12-15T14:40:00.881380", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_a78cf315-d2d8-4d04-b075-e9aba7421706", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 68 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103768 + }, + "response": { + "traits": [ + { + "id": 26678406, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678407, + "trait_key": "age", + "trait_value": 68 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "ad2cb625-4d07-4af6-9eba-18a7b3841fe8", + "identifier": "0d0eb3b4-aab5-4a2e-b82a-47e84c57c64d", + "created_date": "2021-12-15T14:40:00.881386", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_0d0eb3b4-aab5-4a2e-b82a-47e84c57c64d", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 28 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103770 + }, + "response": { + "traits": [ + { + "id": 26678408, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678409, + "trait_key": "age", + "trait_value": 28 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "4a9bb0c3-78e3-42ba-9389-c9d7e60606af", + "identifier": "7edcfe01-784c-4951-8c22-5f84f0569381", + "created_date": "2021-12-15T14:40:00.881392", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_7edcfe01-784c-4951-8c22-5f84f0569381", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 47 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103775 + }, + "response": { + "traits": [ + { + "id": 26678410, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678411, + "trait_key": "age", + "trait_value": 47 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "d7f49884-6c09-4072-879e-2739e819b93a", + "identifier": "c334969d-25bd-4ea2-9cd3-634fecdc542d", + "created_date": "2021-12-15T14:40:00.881398", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_c334969d-25bd-4ea2-9cd3-634fecdc542d", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 50 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103778 + }, + "response": { + "traits": [ + { + "id": 26678412, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678413, + "trait_key": "age", + "trait_value": 50 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "e518ad76-3358-41cc-a754-fa94ef3a9326", + "identifier": "28501e08-e978-4336-9ddd-d90d87983ab3", + "created_date": "2021-12-15T14:40:00.881404", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_28501e08-e978-4336-9ddd-d90d87983ab3", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 43 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103779 + }, + "response": { + "traits": [ + { + "id": 26678414, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678415, + "trait_key": "age", + "trait_value": 43 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "72cba3cd-0d49-4ba2-988e-cdbcda0190a8", + "identifier": "1b33fc3f-3c0e-480c-acce-1937779c743b", + "created_date": "2021-12-15T14:40:00.881410", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_1b33fc3f-3c0e-480c-acce-1937779c743b", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 4 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103782 + }, + "response": { + "traits": [ + { + "id": 26678416, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678417, + "trait_key": "age", + "trait_value": 4 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "9deeec31-7e48-4916-a788-2690f7bb6a67", + "identifier": "2269ea5c-4509-4b7e-acd8-1f7763837464", + "created_date": "2021-12-15T14:40:00.881417", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_2269ea5c-4509-4b7e-acd8-1f7763837464", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 14 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103784 + }, + "response": { + "traits": [ + { + "id": 26678418, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678419, + "trait_key": "age", + "trait_value": 14 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "07d47ed2-dc53-4966-b3f4-c1f2646cdf1d", + "identifier": "a4bc3ba0-7366-4bf2-b309-37baf2d0f45f", + "created_date": "2021-12-15T14:40:00.881423", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_a4bc3ba0-7366-4bf2-b309-37baf2d0f45f", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 62 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103786 + }, + "response": { + "traits": [ + { + "id": 26678420, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678421, + "trait_key": "age", + "trait_value": 62 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "ae780a18-9c46-4791-b455-6c33ac560257", + "identifier": "1969664e-a236-46e7-91af-84dca50a313b", + "created_date": "2021-12-15T14:40:00.881428", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_1969664e-a236-46e7-91af-84dca50a313b", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 43 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103787 + }, + "response": { + "traits": [ + { + "id": 26678422, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678423, + "trait_key": "age", + "trait_value": 43 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "5756015d-720f-485d-8816-027de60a7680", + "identifier": "7137c59d-0bc0-43d2-b1ad-492b0a03aa85", + "created_date": "2021-12-15T14:40:00.881434", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_7137c59d-0bc0-43d2-b1ad-492b0a03aa85", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 52 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103790 + }, + "response": { + "traits": [ + { + "id": 26678427, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678428, + "trait_key": "age", + "trait_value": 52 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "a2137b00-8448-44bd-9c57-ef894cdcc974", + "identifier": "f8fe67d7-958e-452c-a4d4-8249c8b9369c", + "created_date": "2021-12-15T14:40:00.881440", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_f8fe67d7-958e-452c-a4d4-8249c8b9369c", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 67 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103791 + }, + "response": { + "traits": [ + { + "id": 26678429, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678430, + "trait_key": "age", + "trait_value": 67 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "9a6fd956-9984-4584-8071-6a4d801cbd7b", + "identifier": "d2a57b07-3ee1-4b0a-8cd9-e572d14635ce", + "created_date": "2021-12-15T14:40:00.881445", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_d2a57b07-3ee1-4b0a-8cd9-e572d14635ce", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 90 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103792 + }, + "response": { + "traits": [ + { + "id": 26678431, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678432, + "trait_key": "age", + "trait_value": 90 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "f921a860-788b-4a5d-8074-e683b924cf0d", + "identifier": "65190952-1717-454b-bef2-b38ea62837c7", + "created_date": "2021-12-15T14:40:00.881450", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_65190952-1717-454b-bef2-b38ea62837c7", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 64 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103794 + }, + "response": { + "traits": [ + { + "id": 26678433, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678434, + "trait_key": "age", + "trait_value": 64 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "a71ee7df-89a6-48be-8307-231361e5010e", + "identifier": "fb098dba-4be6-4117-b95a-fd930c1598b0", + "created_date": "2021-12-15T14:40:00.881456", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_fb098dba-4be6-4117-b95a-fd930c1598b0", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 65 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103796 + }, + "response": { + "traits": [ + { + "id": 26678435, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678436, + "trait_key": "age", + "trait_value": 65 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "69d09c74-b19a-442a-8061-c7b0641b5642", + "identifier": "3e06036d-fa99-4b46-a843-9bd5b1cdf171", + "created_date": "2021-12-15T14:40:00.881462", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_3e06036d-fa99-4b46-a843-9bd5b1cdf171", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 51 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103797 + }, + "response": { + "traits": [ + { + "id": 26678437, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678438, + "trait_key": "age", + "trait_value": 51 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "f3b604bb-63f5-4b9f-bf41-b6584e7cccac", + "identifier": "29f66219-8344-4df4-a294-92efb44db0c5", + "created_date": "2021-12-15T14:40:00.881467", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_29f66219-8344-4df4-a294-92efb44db0c5", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 97 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103798 + }, + "response": { + "traits": [ + { + "id": 26678439, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678440, + "trait_key": "age", + "trait_value": 97 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "f7c290ed-649a-4ac6-9832-1f415baac78d", + "identifier": "1ccf1600-ca87-47f0-8cd9-225f9f8389a6", + "created_date": "2021-12-15T14:40:00.881473", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_1ccf1600-ca87-47f0-8cd9-225f9f8389a6", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 76 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103799 + }, + "response": { + "traits": [ + { + "id": 26678441, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678442, + "trait_key": "age", + "trait_value": 76 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "98ed8afd-e03d-4706-9443-55650ebc146a", + "identifier": "4f5a88b9-2b1b-4c0a-9f9f-a3fbeda05dfb", + "created_date": "2021-12-15T14:40:00.881479", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_4f5a88b9-2b1b-4c0a-9f9f-a3fbeda05dfb", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 68 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103800 + }, + "response": { + "traits": [ + { + "id": 26678443, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678444, + "trait_key": "age", + "trait_value": 68 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "89174521-10de-480f-a330-7051d1fbf30a", + "identifier": "742956df-236e-4cc9-8b55-634a7b1da4af", + "created_date": "2021-12-15T14:40:00.881505", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_742956df-236e-4cc9-8b55-634a7b1da4af", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 37 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103802 + }, + "response": { + "traits": [ + { + "id": 26678445, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678446, + "trait_key": "age", + "trait_value": 37 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 81027, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "segment_override", + "enabled": false, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "bee25dd0-765b-4451-85aa-977a0294b3d1", + "identifier": "923649a9-5850-4227-a965-32d34ebf9769", + "created_date": "2021-12-15T14:40:00.881511", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_923649a9-5850-4227-a965-32d34ebf9769", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 4 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103803 + }, + "response": { + "traits": [ + { + "id": 26678447, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678448, + "trait_key": "age", + "trait_value": 4 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "e95c0f65-6338-445d-9a5e-31cc10ed072c", + "identifier": "233de9e2-df63-49ca-9f5a-dca000db568d", + "created_date": "2021-12-15T14:40:00.881517", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_233de9e2-df63-49ca-9f5a-dca000db568d", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 19 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103804 + }, + "response": { + "traits": [ + { + "id": 26678449, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678450, + "trait_key": "age", + "trait_value": 19 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "b984486a-81ea-4ff9-8d4e-865b1e69fdc4", + "identifier": "2b051612-8a49-4e04-9500-5daedb8fec88", + "created_date": "2021-12-15T14:40:00.881523", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_2b051612-8a49-4e04-9500-5daedb8fec88", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 99 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103805 + }, + "response": { + "traits": [ + { + "id": 26678451, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678452, + "trait_key": "age", + "trait_value": 99 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "6f498939-34ef-4857-a575-e1411aeee122", + "identifier": "d73a7a70-a8b4-4f98-978a-ebd08cbf2542", + "created_date": "2021-12-15T14:40:00.881529", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_d73a7a70-a8b4-4f98-978a-ebd08cbf2542", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 58 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103806 + }, + "response": { + "traits": [ + { + "id": 26678453, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678454, + "trait_key": "age", + "trait_value": 58 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "e83f2397-43de-4b2f-ba5b-6ead257b4d52", + "identifier": "d9b9b9e5-36aa-406e-bda6-71cb99be60f5", + "created_date": "2021-12-15T14:40:00.881535", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_d9b9b9e5-36aa-406e-bda6-71cb99be60f5", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "trait_key": "age", + "trait_value": 28 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103808 + }, + "response": { + "traits": [ + { + "id": 26678455, + "trait_key": "favourite_colour", + "trait_value": "orange" + }, + { + "id": 26678456, + "trait_key": "age", + "trait_value": 28 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "1ab52980-b736-4207-bd0b-d068c6e78e83", + "identifier": "560cdbac-dfd9-4536-b65b-6654d575058a", + "created_date": "2021-12-15T14:40:00.881541", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_560cdbac-dfd9-4536-b65b-6654d575058a", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 85 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103811 + }, + "response": { + "traits": [ + { + "id": 26678457, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678458, + "trait_key": "age", + "trait_value": 85 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "65a9c511-177d-4d20-9dfb-6771efeb71f9", + "identifier": "be3348ec-6fd9-4b6d-a86a-fd69600855b2", + "created_date": "2021-12-15T14:40:00.881546", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_be3348ec-6fd9-4b6d-a86a-fd69600855b2", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 9 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103812 + }, + "response": { + "traits": [ + { + "id": 26678459, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678460, + "trait_key": "age", + "trait_value": 9 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "45dbc669-d3ba-45cc-b31e-67a4db3a9ea7", + "identifier": "0cfd0d72-4de4-4ed7-9cfb-d80dc3dacead", + "created_date": "2021-12-15T14:40:00.881552", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_0cfd0d72-4de4-4ed7-9cfb-d80dc3dacead", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 47 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103813 + }, + "response": { + "traits": [ + { + "id": 26678461, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678462, + "trait_key": "age", + "trait_value": 47 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "baz", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "79a61937-84b0-400a-b4c3-d5e4a0c61e85", + "identifier": "93f06180-cee7-428e-8385-1206895e4313", + "created_date": "2021-12-15T14:40:00.881557", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_93f06180-cee7-428e-8385-1206895e4313", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 42 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103814 + }, + "response": { + "traits": [ + { + "id": 26678463, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678464, + "trait_key": "age", + "trait_value": 42 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "18e33321-bb8b-4ed0-ab00-e01a19f64071", + "identifier": "18edb157-34cc-4896-aa35-76a7ee68fe68", + "created_date": "2021-12-15T14:40:00.881563", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_18edb157-34cc-4896-aa35-76a7ee68fe68", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 46 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103815 + }, + "response": { + "traits": [ + { + "id": 26678465, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678466, + "trait_key": "age", + "trait_value": 46 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "35596db0-cad3-4b34-8171-cb09b7576305", + "identifier": "e7656d90-7da5-4ce1-b647-36cd977d58fa", + "created_date": "2021-12-15T14:40:00.881568", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_e7656d90-7da5-4ce1-b647-36cd977d58fa", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 34 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103817 + }, + "response": { + "traits": [ + { + "id": 26678467, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678468, + "trait_key": "age", + "trait_value": 34 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "71c30607-114b-47cf-b956-33b2d190cbe2", + "identifier": "d5a54a43-625b-4878-b3fa-120a2bfdd86e", + "created_date": "2021-12-15T14:40:00.881574", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_d5a54a43-625b-4878-b3fa-120a2bfdd86e", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 56 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103818 + }, + "response": { + "traits": [ + { + "id": 26678469, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678470, + "trait_key": "age", + "trait_value": 56 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "1746ccce-f02f-410f-83ad-03856ceeeceb", + "identifier": "23edd289-5188-4af0-b0bf-64c42f73f2f4", + "created_date": "2021-12-15T14:40:00.881579", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_23edd289-5188-4af0-b0bf-64c42f73f2f4", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "trait_key": "age", + "trait_value": 77 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103819 + }, + "response": { + "traits": [ + { + "id": 26678471, + "trait_key": "favourite_colour", + "trait_value": "yellow" + }, + { + "id": 26678472, + "trait_key": "age", + "trait_value": 77 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "1a441f46-8d4b-4a81-9b42-ba5b392f20c9", + "identifier": "41f0b1f5-93a1-43c0-afb7-bce9dc20aac0", + "created_date": "2021-12-15T14:40:00.881585", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_41f0b1f5-93a1-43c0-afb7-bce9dc20aac0", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 48 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103820 + }, + "response": { + "traits": [ + { + "id": 26678473, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678474, + "trait_key": "age", + "trait_value": 48 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "8357857d-6166-4f7c-ac9c-6af97f703c3e", + "identifier": "d3f16e64-9cf8-477c-a09b-7b60723c1694", + "created_date": "2021-12-15T14:40:00.881591", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_d3f16e64-9cf8-477c-a09b-7b60723c1694", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "trait_key": "age", + "trait_value": 62 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103821 + }, + "response": { + "traits": [ + { + "id": 26678475, + "trait_key": "favourite_colour", + "trait_value": "green" + }, + { + "id": 26678476, + "trait_key": "age", + "trait_value": 62 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "d4ae7c03-814f-41f2-a6de-5a28ce044770", + "identifier": "957d39a5-6e97-4026-9d94-be68aa97bf1b", + "created_date": "2021-12-15T14:40:00.881596", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_957d39a5-6e97-4026-9d94-be68aa97bf1b", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 30 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103822 + }, + "response": { + "traits": [ + { + "id": 26678477, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678478, + "trait_key": "age", + "trait_value": 30 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "7e6dabdf-9e65-4949-8dd4-21fe0c297855", + "identifier": "53273d70-2f37-4c43-8979-e0426f7ac375", + "created_date": "2021-12-15T14:40:00.881602", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_53273d70-2f37-4c43-8979-e0426f7ac375", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 89 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103823 + }, + "response": { + "traits": [ + { + "id": 26678479, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678480, + "trait_key": "age", + "trait_value": 89 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "a050d1a1-d53a-49ad-b5a9-91ac82bb66c7", + "identifier": "4ab15967-c00b-4a6b-8da6-0a9ef67683fd", + "created_date": "2021-12-15T14:40:00.881607", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_4ab15967-c00b-4a6b-8da6-0a9ef67683fd", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "trait_key": "age", + "trait_value": 92 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103824 + }, + "response": { + "traits": [ + { + "id": 26678481, + "trait_key": "favourite_colour", + "trait_value": "blue" + }, + { + "id": 26678482, + "trait_key": "age", + "trait_value": 92 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + }, + { + "identity": { + "identity_uuid": "c6518ef6-1b38-4d01-a058-e98f701f6253", + "identifier": "2448af3b-bf5c-493b-9bce-13be5d6e697a", + "created_date": "2021-12-15T14:40:00.881614", + "composite_key": "n9fbf9h3v4fFgH3U3ngWhb_2448af3b-bf5c-493b-9bce-13be5d6e697a", + "identity_features": [], + "identity_traits": [ + { + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "trait_key": "age", + "trait_value": 43 + } + ], + "environment_api_key": "n9fbf9h3v4fFgH3U3ngWhb", + "django_id": 32103825 + }, + "response": { + "traits": [ + { + "id": 26678483, + "trait_key": "favourite_colour", + "trait_value": "red" + }, + { + "id": 26678484, + "trait_key": "age", + "trait_value": 43 + } + ], + "flags": [ + { + "id": 78982, + "feature": { + "id": 15060, + "name": "basic_flag", + "created_date": "2021-11-29T17:16:25.449058Z", + "description": null, + "initial_value": null, + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": null, + "enabled": false, + "environment": 12561, + "identity": null + }, + { + "id": 78984, + "feature": { + "id": 15061, + "name": "float_feature", + "created_date": "2021-11-29T17:16:43.961385Z", + "description": null, + "initial_value": "12.34", + "default_enabled": false, + "type": "STANDARD" + }, + "feature_state_value": "12.34", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78980, + "feature": { + "id": 15059, + "name": "integer_feature", + "created_date": "2021-11-29T17:16:11.288134Z", + "description": null, + "initial_value": "1234", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": 1234, + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78986, + "feature": { + "id": 15062, + "name": "mv_feature", + "created_date": "2021-11-29T17:17:23.645334Z", + "description": null, + "initial_value": "foo", + "default_enabled": false, + "type": "MULTIVARIATE" + }, + "feature_state_value": "bar", + "enabled": true, + "environment": 12561, + "identity": null + }, + { + "id": 78978, + "feature": { + "id": 15058, + "name": "string_feature", + "created_date": "2021-11-29T17:15:51.694223Z", + "description": null, + "initial_value": "foo", + "default_enabled": true, + "type": "STANDARD" + }, + "feature_state_value": "foo", + "enabled": true, + "environment": 12561, + "identity": null + } + ] + } + } + ] +} diff --git a/test/support/engine-test-data b/test/support/engine-test-data index 81e3037..cb06740 160000 --- a/test/support/engine-test-data +++ b/test/support/engine-test-data @@ -1 +1 @@ -Subproject commit 81e3037fbd3fcf6debcede424706fdbeb1b0c0a6 +Subproject commit cb067401093766e55c3354c1de7c73d9331334df diff --git a/test/unit/engine_test_data_test.exs b/test/unit/engine_test_data_test.exs new file mode 100644 index 0000000..e72c782 --- /dev/null +++ b/test/unit/engine_test_data_test.exs @@ -0,0 +1,66 @@ +defmodule Flagsmith.Engine.EngineTestData.Test do + use ExUnit.Case, async: true + + import Mox, only: [stub_with: 2] + + alias Flagsmith.Engine.Evaluator + + @test_cases_path Path.join([File.cwd!(), "test/support/engine-test-data/test_cases"]) + @test_case_paths @test_cases_path |> Path.join("*.json*") |> Path.wildcard() |> Enum.sort() + + setup do + stub_with(Flagsmith.Engine.MockHashing, Flagsmith.Engine.HashingUtils) + :ok + end + + test "engine test data submodule is checked out" do + # Given / When + test_case_paths = @test_case_paths + + # Then + assert test_case_paths != [], "Run `git submodule update --init` to fetch test data" + end + + for path <- @test_case_paths do + @external_resource path + + test "#{Path.basename(path)}" do + # Given + %{"context" => context, "result" => expected} = load_test_case(unquote(path)) + + # When + result = Evaluator.get_evaluation_result(context) + + # Then + assert result == expected + end + end + + defp load_test_case(path) do + test_case = + path + |> File.read!() + |> String.replace(~r/^\s*\/\/.*$/m, "") + |> Jason.decode!(objects: :ordered_objects) + + context = + test_case["context"] + |> to_map() + # declaration order decides override ties and segment result order + |> put_entries("features", test_case["context"]["features"]) + |> put_entries("segments", test_case["context"]["segments"]) + + %{"context" => context, "result" => to_map(test_case["result"])} + end + + defp put_entries(context, _key, nil), do: context + + defp put_entries(context, key, %Jason.OrderedObject{values: values}), + do: Map.put(context, key, Enum.map(values, fn {k, v} -> {k, to_map(v)} end)) + + defp to_map(%Jason.OrderedObject{values: values}), + do: Map.new(values, fn {key, value} -> {key, to_map(value)} end) + + defp to_map(list) when is_list(list), do: Enum.map(list, &to_map/1) + defp to_map(value), do: value +end diff --git a/test/unit/environment_suite_test.exs b/test/unit/environment_suite_test.exs index f6c795e..d9027d8 100644 --- a/test/unit/environment_suite_test.exs +++ b/test/unit/environment_suite_test.exs @@ -7,7 +7,7 @@ defmodule Flagsmith.Engine.EnvironmentSuite.Test do @path Path.join([ File.cwd!(), - "test/support/engine-test-data/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json" + "test/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json" ]) @json_env @path |> File.read!() |> Jason.decode!() diff --git a/test/unit/flag_dependency_test.exs b/test/unit/flag_dependency_test.exs new file mode 100644 index 0000000..4ba575e --- /dev/null +++ b/test/unit/flag_dependency_test.exs @@ -0,0 +1,106 @@ +defmodule Flagsmith.Engine.FlagDependency.Test do + use ExUnit.Case, async: true + + import Mox, only: [stub_with: 2] + + alias Flagsmith.Engine + alias Flagsmith.Schemas.{Identity, Segments} + + @environment %{ + "api_key" => "env-key", + "name" => "Environment", + "feature_states" => [ + %{ + "django_id" => 1, + "enabled" => false, + "feature" => %{"id" => 1, "name" => "prerequisite", "type" => "STANDARD"}, + "feature_state_value" => nil + }, + %{ + "django_id" => 2, + "enabled" => false, + "feature" => %{"id" => 2, "name" => "dependent", "type" => "STANDARD"}, + "feature_state_value" => "off" + } + ], + "identity_overrides" => [ + %{ + "identifier" => "prerequisite-user", + "identity_features" => [ + %{ + "enabled" => true, + "feature" => %{"id" => 1, "name" => "prerequisite", "type" => "STANDARD"}, + "feature_state_value" => nil + } + ] + } + ], + "project" => %{ + "hide_disabled_flags" => false, + "segments" => [ + %{ + "id" => 1, + "name" => "prerequisite_enabled", + "rules" => [ + %{ + "type" => "ALL", + "rules" => [], + "conditions" => [ + %{ + "operator" => "EQUAL", + "property_" => "$.flags.prerequisite.enabled", + "value" => "true" + } + ] + } + ], + "feature_states" => [ + %{ + "django_id" => 3, + "enabled" => true, + "feature" => %{"id" => 2, "name" => "dependent", "type" => "STANDARD"}, + "feature_state_value" => "on", + "feature_segment" => %{"priority" => 0} + } + ] + } + ] + } + } + + setup do + stub_with(Flagsmith.Engine.MockHashing, Flagsmith.Engine.HashingUtils) + {:ok, env} = Engine.parse_environment(@environment) + overrides = Map.new(env.identity_overrides, &{&1.identifier, &1}) + [env: env, overrides: overrides] + end + + test "dependent flag follows its prerequisite's identity override", %{ + env: env, + overrides: overrides + } do + # Given + identity = Map.fetch!(overrides, "prerequisite-user") + + # When + dependent = Engine.get_identity_feature_state(env, identity, "dependent") + segments = Engine.get_identity_segments(env, identity) + + # Then + assert %{enabled: true, feature_state_value: "on"} = dependent + assert [%Segments.IdentitySegment{id: 1, name: "prerequisite_enabled"}] = segments + end + + test "dependent flag keeps its default when its prerequisite is disabled", %{env: env} do + # Given + identity = Identity.from_id_traits("other-user", []) + + # When + dependent = Engine.get_identity_feature_state(env, identity, "dependent") + segments = Engine.get_identity_segments(env, identity) + + # Then + assert %{enabled: false, feature_state_value: "off"} = dependent + assert [] = segments + end +end From c58b7b39b99d0fbad2472b1b2705d074b3b6287d Mon Sep 17 00:00:00 2001 From: Evandro Myller <22429+emyller@users.noreply.github.com> Date: Wed, 21 Oct 2026 18:17:03 +0000 Subject: [PATCH 2/2] perf(Flag Dependency): Prepare environments once for identity evaluation Split the evaluator into a prepare step for the environment, with segment conditions compiled, and a per identity evaluation step. The prepared environment is kept per process for the environment last evaluated, and segments are evaluated without flags when only segments are asked for. Generated with [Linear](https://linear.app/flagsmith/agent-session/51c26f09-5fe3-44a8-8e3d-be2cf9ac50ff) Co-authored-by: linear-code[bot] <222613912+linear-code[bot]@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 (1M context) --- lib/engine/evaluator.ex | 609 +++++++++++++++--------- lib/engine/mappers.ex | 134 +++--- lib/flagsmith_engine.ex | 27 +- test/unit/prepared_environment_test.exs | 80 ++++ 4 files changed, 545 insertions(+), 305 deletions(-) create mode 100644 test/unit/prepared_environment_test.exs diff --git a/lib/engine/evaluator.ex b/lib/engine/evaluator.ex index 281776f..75827f4 100644 --- a/lib/engine/evaluator.ex +++ b/lib/engine/evaluator.ex @@ -4,11 +4,22 @@ defmodule Flagsmith.Engine.Evaluator do alias Flagsmith.Engine.JSONPath @type context :: map() + @type prepared :: map() @type flag_result :: %{String.t() => term()} @type result :: %{String.t() => term()} @circular_dependency_reason "ERROR; code=CIRCULAR_DEPENDENCY" + @comparison_operators [ + "EQUAL", + "NOT_EQUAL", + "GREATER_THAN", + "GREATER_THAN_INCLUSIVE", + "LESS_THAN", + "LESS_THAN_INCLUSIVE", + "CONTAINS" + ] + @doc """ Get the flags and matching segments for an evaluation context, as specified by https://github.com/Flagsmith/engine-test-data. @@ -23,18 +34,57 @@ defmodule Flagsmith.Engine.Evaluator do """ @spec get_evaluation_result(context()) :: result() def get_evaluation_result(context) do - context = enrich_context(context) - features = entries(context["features"]) - segments = entries(context["segments"]) + context + |> prepare() + |> evaluate(Map.get(context, "identity")) + end + + @doc """ + Prepare everything but the identity of a context for evaluation, so that the + work it takes is shared by every identity evaluated with `evaluate/3`. + """ + @spec prepare(context()) :: prepared() + def prepare(context) do + features = entries(Map.get(context, "features")) + segments = Enum.map(entries(Map.get(context, "segments")), &prepare_segment/1) - evaluation = %{ + %{ context: - Map.merge(context, %{"features" => Map.new(features), "segments" => Map.new(segments)}), - features: Map.new(features), - segments: Map.new(segments), - identity_key: get_in(context, ["identity", "key"]), + context + |> Map.delete("identity") + |> Map.merge(%{ + "features" => Map.new(features), + "segments" => Map.new(segments, fn {key, segment} -> {key, segment.context} end) + }), + environment_key: get_in(context, ["environment", "key"]), + features: features, + features_by_key: Map.new(features), + segments: segments, + segments_by_key: Map.new(segments), segment_keys_by_feature_name: segment_keys_by_feature_name(segments) } + end + + @doc """ + Evaluate a prepared context for an identity, or none. + + Options: + + * `:segments` - segments to evaluate after those of the prepared context, + as `{key, segment}` tuples + * `:flags` - whether to evaluate flags, or only segments. Defaults to `true` + """ + @spec evaluate(prepared(), map() | nil, keyword()) :: result() + def evaluate(prepared, identity, opts \\ []) do + evaluation = add_segments(prepared, Keyword.get(opts, :segments, [])) + identity = enrich_identity(identity, prepared.environment_key) + + evaluation = + Map.merge(evaluation, %{ + context: put_identity(evaluation.context, identity), + identity_key: identity && Map.get(identity, "key"), + traits: (identity && Map.get(identity, "traits")) || %{} + }) state = %{ resolved: %{}, @@ -46,62 +96,177 @@ defmodule Flagsmith.Engine.Evaluator do segment_matches: %{} } - {segment_results, segment_overrides, state} = evaluate_segments(evaluation, segments, state) - flags = evaluate_features(evaluation, features, segment_overrides) + {segment_results, segment_overrides, state} = evaluate_segments(evaluation, state) flags = - case state.used do - false -> - flags - - true -> - # flags resolved for conditions are cycle-guarded, so take precedence - state.cyclic - |> Enum.reduce(Map.merge(flags, state.resolved), fn feature_name, flags -> - case flags do - %{^feature_name => flag} -> - Map.put(flags, feature_name, %{flag | "reason" => @circular_dependency_reason}) - - _ -> - flags - end - end) + case Keyword.get(opts, :flags, true) do + true -> evaluate_features(evaluation, segment_overrides, state) + false -> %{} end %{"flags" => flags, "segments" => segment_results} end - defp enrich_context(%{"identity" => %{"identifier" => identifier} = identity} = context) do - case identity["key"] do - key when key in [nil, ""] -> - put_in(context, ["identity", "key"], "#{context["environment"]["key"]}_#{identifier}") + defp entries(nil), do: [] + defp entries(map) when is_map(map), do: Enum.to_list(map) + defp entries(list) when is_list(list), do: list + + defp add_segments(evaluation, []), do: evaluation - _ -> - context + defp add_segments(evaluation, segments) do + segments = Enum.map(segments, &prepare_segment/1) + + keys_by_feature_name = + Map.merge( + evaluation.segment_keys_by_feature_name, + segment_keys_by_feature_name(segments), + fn _name, keys, added_keys -> keys ++ added_keys end + ) + + %{ + evaluation + | context: + Map.update!(evaluation.context, "segments", fn context_segments -> + Enum.reduce(segments, context_segments, fn {key, segment}, context_segments -> + Map.put(context_segments, key, segment.context) + end) + end), + segments: evaluation.segments ++ segments, + segments_by_key: Map.merge(evaluation.segments_by_key, Map.new(segments)), + segment_keys_by_feature_name: keys_by_feature_name + } + end + + defp enrich_identity(%{"identifier" => identifier} = identity, environment_key) do + case Map.get(identity, "key") do + key when key in [nil, ""] -> Map.put(identity, "key", "#{environment_key}_#{identifier}") + _ -> identity end end - defp enrich_context(context), do: context + defp enrich_identity(identity, _environment_key), do: identity - defp entries(nil), do: [] - defp entries(map) when is_map(map), do: Enum.to_list(map) - defp entries(list) when is_list(list), do: list + defp put_identity(context, nil), do: context + defp put_identity(context, identity), do: Map.put(context, "identity", identity) defp segment_keys_by_feature_name(segments) do segments |> Enum.flat_map(fn {segment_key, segment} -> - Enum.map(overrides(segment), &{&1["name"], segment_key}) + Enum.map(segment.overrides, &{&1.name, segment_key}) end) |> Enum.group_by(&elem(&1, 0), &elem(&1, 1)) end - defp overrides(segment), do: segment["overrides"] || [] + defp prepare_segment({key, segment}) do + segment_key = Map.get(segment, "key") + + rules = + case Map.get(segment, "rules") do + [_ | _] = rules -> Enum.map(rules, &prepare_rule(&1, segment_key)) + _ -> nil + end + + overrides = + for override <- Map.get(segment, "overrides") || [] do + %{name: Map.get(override, "name"), priority: priority(override), feature: override} + end + + {key, + %{ + context: segment, + name: Map.get(segment, "name"), + rules: rules, + overrides: overrides, + result: segment_result(segment) + }} + end + + defp prepare_rule(rule, segment_key) do + conditions = + case Map.get(rule, "conditions") do + [_ | _] = conditions -> Enum.map(conditions, &prepare_condition(&1, segment_key)) + _ -> [] + end + + rules = + case Map.get(rule, "rules") do + [_ | _] = rules -> Enum.map(rules, &prepare_rule(&1, segment_key)) + _ -> [] + end + + case Map.get(rule, "type") do + type when type in ["ALL", "ANY", "NONE"] -> {type, conditions, rules} + _ -> :invalid + end + end + + defp prepare_condition(condition, segment_key) do + operator = Map.get(condition, "operator") + property = Map.get(condition, "property") + + property = + case operator == "PERCENTAGE_SPLIT" and property in [nil, ""] do + # legacy segments split on the identity key + true -> :identity_key + false -> prepare_property(property || "") + end + + {operator, property, prepare_value(operator, Map.get(condition, "value"), segment_key)} + end + + defp prepare_property("$." <> _ = property) do + case JSONPath.compile(property) do + {:ok, segments} -> {:path, property, segments} + :error -> {:trait, property} + end + end + + defp prepare_property(property), do: {:trait, property} + + defp prepare_value("IN", value, _segment_key), do: in_values(value) + + defp prepare_value("PERCENTAGE_SPLIT", value, segment_key), + do: {parse_float(value), to_str(segment_key)} + + defp prepare_value("NOT_CONTAINS", value, _segment_key), do: to_str(value) + + defp prepare_value("REGEX", value, _segment_key) do + case :re.compile(to_str(value), [:unicode, :ucp]) do + {:ok, regex} -> {:ok, regex} + {:error, _} -> :error + end + end + + defp prepare_value("MODULO", value, _segment_key) when is_binary(value) do + with [divisor, remainder] <- String.split(value, "|"), + {:ok, divisor} when divisor != 0 <- parse_float(divisor), + {:ok, remainder} <- parse_float(remainder) do + {:ok, divisor, remainder} + else + _ -> :error + end + end + + defp prepare_value("MODULO", _value, _segment_key), do: :error + + defp prepare_value(operator, value, _segment_key) when operator in @comparison_operators do + version = + case semver?(value) do + true -> Version.parse(String.replace_suffix(value, ":semver", "")) + false -> nil + end + + %{version: version, value: value, string: to_str(value)} + end + + defp prepare_value(_operator, value, _segment_key), do: value - defp evaluate_segments(evaluation, segments, state) do + defp evaluate_segments(evaluation, state) do {results, overrides, state, _cycle_hits} = - Enum.reduce(segments, {[], %{}, state, state.cycle_hits}, fn {_key, segment}, - {results, overrides, state, - cycle_hits} -> + Enum.reduce(evaluation.segments, {[], %{}, state, state.cycle_hits}, fn {_key, segment}, + {results, overrides, + state, + cycle_hits} -> {matches, state} = context_in_segment?(evaluation, state, segment) cond do @@ -114,16 +279,14 @@ defmodule Flagsmith.Engine.Evaluator do true -> overrides = - Enum.reduce(overrides(segment), overrides, fn override, overrides -> - name = override["name"] - - case wins_over?(override, overrides[name]) do - true -> Map.put(overrides, name, {override, segment["name"]}) + Enum.reduce(segment.overrides, overrides, fn %{name: name} = override, overrides -> + case wins_over?(override, overrides) do + true -> Map.put(overrides, name, {override, segment.name}) false -> overrides end end) - {[segment_result(segment) | results], overrides, state, cycle_hits} + {[segment.result | results], overrides, state, cycle_hits} end end) @@ -131,35 +294,59 @@ defmodule Flagsmith.Engine.Evaluator do end defp segment_result(%{"name" => name} = segment) do - case segment["metadata"] do + case Map.get(segment, "metadata") do metadata when metadata in [nil, %{}] -> %{"name" => name} metadata -> %{"name" => name, "metadata" => metadata} end end # lower priority wins, the first seen wins a tie - defp wins_over?(_candidate, nil), do: true - - defp wins_over?(candidate, {incumbent, _segment_name}), - do: priority(candidate) < priority(incumbent) + defp wins_over?(%{name: name, priority: priority}, overrides) do + case overrides do + %{^name => {incumbent, _segment_name}} -> priority < incumbent.priority + _ -> true + end + end defp priority(%{"priority" => :negative_infinity}), do: {0, 0} defp priority(%{"priority" => priority}) when is_number(priority), do: {1, priority} defp priority(_), do: {2, 0} - defp evaluate_features(evaluation, features, segment_overrides) do - Map.new(features, fn {_key, %{"name" => name} = feature} -> - flag = - case segment_overrides do - %{^name => {override, segment_name}} -> - flag_result(evaluation, override, "TARGETING_MATCH; segment=#{segment_name}") + defp evaluate_features(evaluation, segment_overrides, state) do + flags = + Map.new(evaluation.features, fn {_key, %{"name" => name} = feature} -> + flag = + case segment_overrides do + %{^name => {override, segment_name}} -> + flag_result( + evaluation, + override.feature, + "TARGETING_MATCH; segment=#{segment_name}" + ) - _ -> - flag_result(evaluation, feature, fallback_reason(evaluation, name)) - end + _ -> + flag_result(evaluation, feature, fallback_reason(evaluation, name)) + end - {name, flag} - end) + {name, flag} + end) + + case state.used do + false -> + flags + + true -> + # flags resolved for conditions are cycle-guarded, so take precedence + Enum.reduce(state.cyclic, Map.merge(flags, state.resolved), fn feature_name, flags -> + case flags do + %{^feature_name => flag} -> + Map.put(flags, feature_name, %{flag | "reason" => @circular_dependency_reason}) + + _ -> + flags + end + end) + end end defp fallback_reason(%{segment_keys_by_feature_name: keys}, name) @@ -170,46 +357,48 @@ defmodule Flagsmith.Engine.Evaluator do defp flag_result(evaluation, feature, reason) do {value, variant, reason} = - case {evaluation.identity_key, feature["variants"]} do + case {evaluation.identity_key, Map.get(feature, "variants")} do {key, [_ | _] = variants} when not is_nil(key) -> select_variant(feature, key, variants, reason) _ -> - {feature["value"], nil, reason} + {Map.get(feature, "value"), nil, reason} end result = %{ - "enabled" => feature["enabled"], - "name" => feature["name"], + "enabled" => Map.get(feature, "enabled"), + "name" => Map.get(feature, "name"), "reason" => reason, "value" => value, "variant" => variant } - case feature["metadata"] do + case Map.get(feature, "metadata") do metadata when metadata in [nil, %{}] -> result metadata -> Map.put(result, "metadata", metadata) end end defp select_variant(feature, identity_key, variants, reason) do - percentage = Flagsmith.Engine.percentage_from_ids([to_str(feature["key"]), identity_key]) + percentage = + Flagsmith.Engine.percentage_from_ids([to_str(Map.get(feature, "key")), identity_key]) variants - |> Enum.sort_by(& &1["priority"]) + |> Enum.sort_by(&Map.get(&1, "priority")) |> Enum.reduce_while(0, fn %{"weight" => weight} = variant, start -> limit = weight + start case start <= percentage and percentage < limit do true -> - {:halt, {variant["value"], variant["key"], "SPLIT; weight=#{to_str(weight)}"}} + {:halt, + {Map.get(variant, "value"), Map.get(variant, "key"), "SPLIT; weight=#{to_str(weight)}"}} false -> {:cont, limit} end end) |> case do - limit when is_number(limit) -> {feature["value"], "control", reason} + limit when is_number(limit) -> {Map.get(feature, "value"), "control", reason} selected -> selected end end @@ -236,7 +425,7 @@ defmodule Flagsmith.Engine.Evaluator do cycle_hits: state.cycle_hits + 1 } - not is_map_key(evaluation.features, feature_name) -> + not is_map_key(evaluation.features_by_key, feature_name) -> state true -> @@ -254,12 +443,12 @@ defmodule Flagsmith.Engine.Evaluator do state override -> - {feature, segment_name} = override + {%{feature: feature}, segment_name} = override flag = flag_result(evaluation, feature, "TARGETING_MATCH; segment=#{segment_name}") put_in(state, [:resolved, feature_name], flag) true -> - feature = evaluation.features[feature_name] + feature = evaluation.features_by_key[feature_name] flag = flag_result(evaluation, feature, fallback_reason(evaluation, feature_name)) put_in(state, [:resolved, feature_name], flag) end @@ -275,15 +464,14 @@ defmodule Flagsmith.Engine.Evaluator do {override, state} {true, state} -> - segment = evaluation.segments[segment_key] + segment = evaluation.segments_by_key[segment_key] override = - segment - |> overrides() - |> Enum.filter(&(&1["name"] == feature_name)) + segment.overrides + |> Enum.filter(&(&1.name == feature_name)) |> Enum.reduce(override, fn candidate, override -> - case wins_over?(candidate, override) do - true -> {candidate, segment["name"]} + case override == nil or candidate.priority < elem(override, 0).priority do + true -> {candidate, segment.name} false -> override end end) @@ -300,7 +488,7 @@ defmodule Flagsmith.Engine.Evaluator do _ -> cycle_hits = state.cycle_hits - segment = evaluation.segments[segment_key] + segment = evaluation.segments_by_key[segment_key] {matches, state} = context_in_segment?(evaluation, state, segment) case state.cycle_hits != cycle_hits do @@ -311,87 +499,54 @@ defmodule Flagsmith.Engine.Evaluator do end end - defp context_in_segment?(evaluation, state, %{"rules" => [_ | _] = rules} = segment) do - all(rules, state, &rule_matches?(evaluation, &2, &1, segment["key"])) - end + defp context_in_segment?(_evaluation, state, %{rules: nil}), do: {false, state} - defp context_in_segment?(_evaluation, state, _segment), do: {false, state} + defp context_in_segment?(evaluation, state, %{rules: rules}), + do: all(rules, state, &rule_matches?(evaluation, &2, &1)) - defp rule_matches?(evaluation, state, rule, segment_key) do - case matching_function(rule["type"]) do - nil -> - {false, state} - - matching_function -> - {matches_conditions, state} = - case rule["conditions"] do - [_ | _] = conditions -> - matching_function.( - conditions, - state, - &condition_matches?(evaluation, &2, &1, segment_key) - ) + defp rule_matches?(_evaluation, state, :invalid), do: {false, state} - _ -> - {true, state} - end - - {matches_rules, state} = - case rule["rules"] do - [_ | _] = rules -> - matching_function.(rules, state, &rule_matches?(evaluation, &2, &1, segment_key)) - - _ -> - {true, state} - end + defp rule_matches?(evaluation, state, {type, conditions, rules}) do + {matches_conditions, state} = + matching(type, conditions, state, &condition_matches?(evaluation, &2, &1)) - {matches_conditions and matches_rules, state} - end + {matches_rules, state} = matching(type, rules, state, &rule_matches?(evaluation, &2, &1)) + {matches_conditions and matches_rules, state} end - defp matching_function("ALL"), do: &all/3 - defp matching_function("ANY"), do: &any/3 - defp matching_function("NONE"), do: &none/3 - defp matching_function(_), do: nil + defp matching(_type, [], state, _fun), do: {true, state} + defp matching("ALL", items, state, fun), do: all(items, state, fun) + defp matching("ANY", items, state, fun), do: any(items, state, fun) - defp all(items, state, fun) do - Enum.reduce_while(items, {true, state}, fn item, {_, state} -> - case fun.(item, state) do - {true, state} -> {:cont, {true, state}} - {false, state} -> {:halt, {false, state}} - end - end) + defp matching("NONE", items, state, fun) do + {matches, state} = any(items, state, fun) + {not matches, state} end - defp any(items, state, fun) do - Enum.reduce_while(items, {false, state}, fn item, {_, state} -> - case fun.(item, state) do - {true, state} -> {:halt, {true, state}} - {false, state} -> {:cont, {false, state}} - end - end) - end + defp all([], state, _fun), do: {true, state} - defp none(items, state, fun) do - {matches, state} = any(items, state, fun) - {not matches, state} + defp all([item | items], state, fun) do + case fun.(item, state) do + {true, state} -> all(items, state, fun) + {false, _state} = result -> result + end end - defp condition_matches?(evaluation, state, condition, segment_key) do - property = condition["property"] - operator = condition["operator"] + defp any([], state, _fun), do: {false, state} - {context_value, state} = - case operator == "PERCENTAGE_SPLIT" and property in [nil, ""] do - # legacy segments split on the identity key - true -> {evaluation.identity_key, state} - false -> get_context_value(evaluation, state, property || "") - end + defp any([item | items], state, fun) do + case fun.(item, state) do + {true, _state} = result -> result + {false, state} -> any(items, state, fun) + end + end - {matches_condition?(operator, condition["value"], context_value, segment_key), state} + defp condition_matches?(evaluation, state, {operator, property, value}) do + {context_value, state} = get_context_value(evaluation, state, property) + {matches_condition?(operator, value, context_value), state} end - defp matches_condition?("IN", segment_value, context_value, _segment_key) do + defp matches_condition?("IN", values, context_value) do # Guard against comparing boolean values to numeric strings. context_value = case is_integer(context_value) do @@ -399,83 +554,49 @@ defmodule Flagsmith.Engine.Evaluator do false -> context_value end - is_binary(context_value) and MapSet.member?(in_values(segment_value), context_value) - end - - defp matches_condition?("PERCENTAGE_SPLIT", _segment_value, nil, _segment_key), do: false - - defp matches_condition?("PERCENTAGE_SPLIT", segment_value, context_value, segment_key) do - case parse_float(segment_value) do - {:ok, float} -> - Flagsmith.Engine.percentage_from_ids([to_str(segment_key), to_str(context_value)]) <= - float - - :error -> - false - end + is_binary(context_value) and MapSet.member?(values, context_value) end - defp matches_condition?("IS_NOT_SET", _segment_value, context_value, _segment_key), - do: is_nil(context_value) + defp matches_condition?("PERCENTAGE_SPLIT", _value, nil), do: false - defp matches_condition?("IS_SET", _segment_value, context_value, _segment_key), - do: not is_nil(context_value) + defp matches_condition?("PERCENTAGE_SPLIT", {{:ok, float}, segment_key}, context_value), + do: Flagsmith.Engine.percentage_from_ids([segment_key, to_str(context_value)]) <= float - defp matches_condition?(_operator, _segment_value, nil, _segment_key), do: false + defp matches_condition?("PERCENTAGE_SPLIT", _value, _context_value), do: false + defp matches_condition?("IS_NOT_SET", _value, context_value), do: is_nil(context_value) + defp matches_condition?("IS_SET", _value, context_value), do: not is_nil(context_value) + defp matches_condition?(_operator, _value, nil), do: false - defp matches_condition?("NOT_CONTAINS", segment_value, context_value, _segment_key), - do: is_binary(context_value) and not String.contains?(context_value, to_str(segment_value)) + defp matches_condition?("NOT_CONTAINS", value, context_value), + do: is_binary(context_value) and not String.contains?(context_value, value) - defp matches_condition?("REGEX", segment_value, context_value, _segment_key) do - case :re.compile(to_str(segment_value), [:unicode, :ucp]) do - {:ok, regex} -> - :re.run(to_str(context_value), regex, [:anchored, capture: :none]) == :match + defp matches_condition?("REGEX", {:ok, regex}, context_value), + do: :re.run(to_str(context_value), regex, [:anchored, capture: :none]) == :match - {:error, _} -> - false - end - end + defp matches_condition?("MODULO", {:ok, divisor, remainder}, context_value) + when is_number(context_value), + do: modulo(context_value, divisor) == remainder - defp matches_condition?("MODULO", segment_value, context_value, _segment_key) - when is_number(context_value) and is_binary(segment_value) do - with [divisor, remainder] <- String.split(segment_value, "|"), - {:ok, divisor} when divisor != 0 <- parse_float(divisor), - {:ok, remainder} <- parse_float(remainder) do - modulo(context_value, divisor) == remainder - else - _ -> false - end - end - - defp matches_condition?(operator, segment_value, context_value, _segment_key) - when operator in [ - "EQUAL", - "NOT_EQUAL", - "GREATER_THAN", - "GREATER_THAN_INCLUSIVE", - "LESS_THAN", - "LESS_THAN_INCLUSIVE", - "CONTAINS" - ] do - case is_binary(context_value) and semver?(segment_value) do + defp matches_condition?(operator, %{version: version} = value, context_value) + when operator in @comparison_operators do + case is_binary(context_value) and version != nil do true -> with {:ok, context_version} <- Version.parse(context_value), - {:ok, segment_version} <- - Version.parse(String.replace_suffix(segment_value, ":semver", "")) do + {:ok, segment_version} <- version do compare_versions(operator, Version.compare(context_version, segment_version)) else _ -> false end false -> - case cast_to_type_of(context_value, segment_value) do + case cast_to_type_of(context_value, value) do {:ok, match_value} -> compare(operator, context_value, match_value) :error -> false end end end - defp matches_condition?(_operator, _segment_value, _context_value, _segment_key), do: false + defp matches_condition?(_operator, _value, _context_value), do: false defp compare_versions("EQUAL", order), do: order == :eq defp compare_versions("NOT_EQUAL", order), do: order != :eq @@ -503,16 +624,16 @@ defmodule Flagsmith.Engine.Evaluator do defp compare(_, _, _), do: false - defp cast_to_type_of(context_value, segment_value) when is_boolean(context_value), - do: {:ok, segment_value not in ["False", "false"]} + defp cast_to_type_of(context_value, value) when is_boolean(context_value), + do: {:ok, value.value not in ["False", "false"]} - defp cast_to_type_of(context_value, segment_value) when is_integer(context_value), - do: parse_integer(segment_value) + defp cast_to_type_of(context_value, value) when is_integer(context_value), + do: parse_integer(value.value) - defp cast_to_type_of(context_value, segment_value) when is_float(context_value), - do: parse_float(segment_value) + defp cast_to_type_of(context_value, value) when is_float(context_value), + do: parse_float(value.value) - defp cast_to_type_of(_context_value, segment_value), do: {:ok, to_str(segment_value)} + defp cast_to_type_of(_context_value, value), do: {:ok, value.string} defp semver?(value), do: is_binary(value) and String.ends_with?(value, ":semver") @@ -538,23 +659,25 @@ defmodule Flagsmith.Engine.Evaluator do end end - defp get_context_value(evaluation, state, "$." <> _ = property) do - with nil <- trait_value(evaluation, property), - {:ok, segments} <- JSONPath.compile(property) do - {value, state} = query(evaluation, state, segments) - {to_context_value(value), state} - else - :error -> {nil, state} - value -> {to_context_value(value), state} - end - end + defp get_context_value(evaluation, state, :identity_key), do: {evaluation.identity_key, state} - defp get_context_value(evaluation, state, property), + defp get_context_value(evaluation, state, {:trait, property}), do: {to_context_value(trait_value(evaluation, property)), state} - defp trait_value(%{context: context}, trait_key) do - case context do - %{"identity" => %{"traits" => %{^trait_key => value}}} -> value + defp get_context_value(evaluation, state, {:path, property, segments}) do + case trait_value(evaluation, property) do + nil -> + {value, state} = query(evaluation, state, segments) + {to_context_value(value), state} + + value -> + {to_context_value(value), state} + end + end + + defp trait_value(%{traits: traits}, trait_key) do + case traits do + %{^trait_key => value} -> value _ -> nil end end @@ -579,25 +702,35 @@ defmodule Flagsmith.Engine.Evaluator do end end - @doc """ - Coerce a value to a context value: a string, number, boolean or nil. - Number-like strings are coerced to numbers. - """ - @spec to_context_value(term()) :: String.t() | number() | boolean() | nil - def to_context_value(value) when is_binary(value) do - cond do - Regex.match?(~r/^-?[0-9]+$/, value) -> String.to_integer(value) - Regex.match?(~r/^-?[0-9]+\.[0-9]+$/, value) -> String.to_float(value) - true -> value + # number-like strings are coerced to numbers + defp to_context_value(value) when is_binary(value) do + case number_kind(value) do + :integer -> String.to_integer(value) + :float -> String.to_float(value) + nil -> value end end - def to_context_value(value) when is_number(value) or is_boolean(value) or is_nil(value), + defp to_context_value(value) when is_number(value) or is_boolean(value) or is_nil(value), do: value - def to_context_value(%Decimal{exp: 0} = value), do: Decimal.to_integer(value) - def to_context_value(%Decimal{} = value), do: Decimal.to_float(value) - def to_context_value(value), do: to_str(value) + defp to_context_value(%Decimal{exp: 0} = value), do: Decimal.to_integer(value) + defp to_context_value(%Decimal{} = value), do: Decimal.to_float(value) + defp to_context_value(value), do: to_str(value) + + # as matching ~r/^-?[0-9]+(\.[0-9]+)?$/, without a trailing newline + defp number_kind("-" <> digits), do: number_kind(digits) + defp number_kind(<> = digits) when c in ?0..?9, do: integer_digits(digits) + defp number_kind(_), do: nil + + defp integer_digits(<>) when c in ?0..?9, do: integer_digits(rest) + defp integer_digits(""), do: :integer + defp integer_digits(<>) when c in ?0..?9, do: fraction_digits(rest) + defp integer_digits(_), do: nil + + defp fraction_digits(<>) when c in ?0..?9, do: fraction_digits(rest) + defp fraction_digits(""), do: :float + defp fraction_digits(_), do: nil defp parse_integer(value) when is_binary(value) do case Integer.parse(String.trim(value)) do diff --git a/lib/engine/mappers.ex b/lib/engine/mappers.ex index 856a9b2..724a196 100644 --- a/lib/engine/mappers.ex +++ b/lib/engine/mappers.ex @@ -6,24 +6,34 @@ defmodule Flagsmith.Engine.Mappers do @identity_overrides_segment_key "identity_overrides" @doc """ - Map an environment, an identity, and optionally traits overriding those of - the identity, to an evaluation context for `Flagsmith.Engine.Evaluator`. + Map an environment to an evaluation context for `Flagsmith.Engine.Evaluator`, + without an identity. Feature and segment contexts carry the feature state or segment they were mapped from in their metadata, so that results can be mapped back to them. """ - @spec map_environment_identity_to_context( - Environment.t(), - Identity.t(), - list(Traits.Trait.t()) - ) :: Flagsmith.Engine.Evaluator.context() - def map_environment_identity_to_context( - %Environment{ - api_key: api_key, - feature_states: feature_states, - project: %Environment.Project{segments: segments} - } = environment, - %Identity{identifier: identifier, identity_features: identity_features} = identity, + @spec map_environment_to_context(Environment.t()) :: Flagsmith.Engine.Evaluator.context() + def map_environment_to_context(%Environment{ + api_key: api_key, + name: name, + feature_states: feature_states, + project: %Environment.Project{segments: segments} + }) do + %{ + "environment" => %{"key" => api_key, "name" => name}, + "features" => Enum.map(feature_states, &{&1.feature.name, map_feature_state(&1)}), + "segments" => Enum.map(segments, &{to_string(&1.id), map_segment(&1)}) + } + end + + @doc """ + Map an identity in an environment, and optionally traits overriding those of + the identity, to the identity of an evaluation context. + """ + @spec map_identity_to_context(Environment.t(), Identity.t(), list(Traits.Trait.t())) :: map() + def map_identity_to_context( + %Environment{} = environment, + %Identity{identifier: identifier} = identity, override_traits \\ [] ) do identity = Identity.set_env_key(identity, environment) @@ -35,19 +45,55 @@ defmodule Flagsmith.Engine.Mappers do end %{ - "environment" => %{"key" => api_key, "name" => environment.name}, - "identity" => %{ - "identifier" => identifier, - "key" => to_string(Identity.composite_key(identity)), - "traits" => Map.new(traits, &map_trait/1) - }, - "features" => Enum.map(feature_states, &{&1.feature.name, map_feature_state(&1)}), - "segments" => - Enum.map(segments, &{to_string(&1.id), map_segment(&1)}) ++ - map_identity_overrides(identifier, identity_features) + "identifier" => identifier, + "key" => to_string(Identity.composite_key(identity)), + "traits" => Map.new(traits, &map_trait/1) } end + @doc """ + Map the overrides of an identity to segments for an evaluation context, + taking precedence over any other. + """ + @spec map_identity_overrides_to_segments(Identity.t()) :: list({String.t(), map()}) + def map_identity_overrides_to_segments(%Identity{identity_features: []}), do: [] + + def map_identity_overrides_to_segments(%Identity{ + identifier: identifier, + identity_features: identity_features + }) do + [ + {@identity_overrides_segment_key, + %{ + "key" => @identity_overrides_segment_key, + "name" => @identity_overrides_segment_key, + "rules" => [ + %{ + "type" => "ALL", + "conditions" => [ + %{ + "property" => "$.identity.identifier", + "operator" => "IN", + "value" => [identifier] + } + ] + } + ], + "overrides" => + Enum.map(identity_features, fn %Features.FeatureState{} = feature_state -> + %{ + "key" => "", + "name" => feature_state.feature.name, + "enabled" => feature_state.enabled, + "value" => feature_state.feature_state_value, + "priority" => :negative_infinity, + "metadata" => %{feature_state: feature_state} + } + end) + }} + ] + end + defp map_trait(%Traits.Trait{trait_key: key, trait_value: %Traits.Trait.Value{value: value}}), do: {key, map_trait_value(value)} @@ -69,13 +115,13 @@ defmodule Flagsmith.Engine.Mappers do defp map_rule(%Segments.Segment.Rule{type: type, rules: rules, conditions: conditions}) do %{ - "type" => to_string(type), + "type" => Atom.to_string(type), "rules" => Enum.map(rules, &map_rule/1), "conditions" => Enum.map(conditions, fn %Segments.Segment.Condition{} = condition -> %{ "property" => condition.property_ || "", - "operator" => to_string(condition.operator), + "operator" => Atom.to_string(condition.operator), "value" => condition.value } end) @@ -113,40 +159,4 @@ defmodule Flagsmith.Engine.Mappers do "priority" => value.id || value.mv_fs_value_uuid } end - - # a segment matching the identity alone, taking precedence over any other - defp map_identity_overrides(_identifier, []), do: [] - - defp map_identity_overrides(identifier, identity_features) do - [ - {@identity_overrides_segment_key, - %{ - "key" => @identity_overrides_segment_key, - "name" => @identity_overrides_segment_key, - "rules" => [ - %{ - "type" => "ALL", - "conditions" => [ - %{ - "property" => "$.identity.identifier", - "operator" => "IN", - "value" => [identifier] - } - ] - } - ], - "overrides" => - Enum.map(identity_features, fn %Features.FeatureState{} = feature_state -> - %{ - "key" => "", - "name" => feature_state.feature.name, - "enabled" => feature_state.enabled, - "value" => feature_state.feature_state_value, - "priority" => :negative_infinity, - "metadata" => %{feature_state: feature_state} - } - end) - }} - ] - end end diff --git a/lib/flagsmith_engine.ex b/lib/flagsmith_engine.ex index 3e8c7cf..93e5386 100644 --- a/lib/flagsmith_engine.ex +++ b/lib/flagsmith_engine.ex @@ -13,6 +13,7 @@ defmodule Flagsmith.Engine do alias Flagsmith.Engine.{Evaluator, Mappers} alias Flagsmith.Schemas.Types @condition_operators Flagsmith.Schemas.Types.Operator.values(:atoms) + @prepared_environment_key {__MODULE__, :prepared_environment} @moduledoc false @@ -68,7 +69,7 @@ defmodule Flagsmith.Engine do %Identity{} = identity, override_traits \\ [] ) do - %{"flags" => flags} = evaluate_identity(env, identity, override_traits) + %{"flags" => flags} = evaluate_identity(env, identity, override_traits, flags: true) Enum.map(fs, fn %{feature: %{name: name}} -> %{"enabled" => enabled, "value" => value, "metadata" => %{feature_state: feature_state}} = @@ -88,16 +89,32 @@ defmodule Flagsmith.Engine do override_traits :: list(Traits.Trait.t()) ) :: list(Segments.IdentitySegment.t()) def get_identity_segments(%Environment{} = env, identity, override_traits \\ []) do - %{"segments" => segments} = evaluate_identity(env, identity, override_traits) + %{"segments" => segments} = evaluate_identity(env, identity, override_traits, flags: false) for %{"metadata" => %{segment: segment}} <- segments, do: Segments.IdentitySegment.from_segment(segment) end - defp evaluate_identity(env, identity, override_traits) do + defp evaluate_identity(env, identity, override_traits, opts) do env - |> Mappers.map_environment_identity_to_context(identity, override_traits) - |> Evaluator.get_evaluation_result() + |> prepare_environment() + |> Evaluator.evaluate( + Mappers.map_identity_to_context(env, identity, override_traits), + [{:segments, Mappers.map_identity_overrides_to_segments(identity)} | opts] + ) + end + + # kept per process for the environment last evaluated, an unchanged one being the same term + defp prepare_environment(env) do + case Process.get(@prepared_environment_key) do + {^env, prepared} -> + prepared + + _ -> + prepared = env |> Mappers.map_environment_to_context() |> Evaluator.prepare() + Process.put(@prepared_environment_key, {env, prepared}) + prepared + end end @doc """ diff --git a/test/unit/prepared_environment_test.exs b/test/unit/prepared_environment_test.exs new file mode 100644 index 0000000..375d397 --- /dev/null +++ b/test/unit/prepared_environment_test.exs @@ -0,0 +1,80 @@ +defmodule Flagsmith.Engine.PreparedEnvironment.Test do + use ExUnit.Case, async: true + + import Mox, only: [stub_with: 2] + + alias Flagsmith.Engine + alias Flagsmith.Schemas.Identity + + @environment %{ + "api_key" => "env-key", + "feature_states" => [ + %{ + "django_id" => 1, + "enabled" => false, + "feature" => %{"id" => 1, "name" => "feature", "type" => "STANDARD"}, + "feature_state_value" => "environment" + } + ], + "project" => %{ + "hide_disabled_flags" => false, + "segments" => [ + %{ + "id" => 1, + "name" => "segment", + "rules" => [ + %{ + "type" => "ALL", + "rules" => [], + "conditions" => [ + %{"operator" => "EQUAL", "property_" => "plan", "value" => "premium"} + ] + } + ], + "feature_states" => [ + %{ + "django_id" => 2, + "enabled" => true, + "feature" => %{"id" => 1, "name" => "feature", "type" => "STANDARD"}, + "feature_state_value" => "segment", + "feature_segment" => %{"priority" => 0} + } + ] + } + ] + } + } + + setup do + stub_with(Flagsmith.Engine.MockHashing, Flagsmith.Engine.HashingUtils) + {:ok, env} = Engine.parse_environment(@environment) + + identity = + Identity.from_id_traits("user", [%{"trait_key" => "plan", "trait_value" => "premium"}]) + + [env: env, identity: identity] + end + + test "an environment changed after an evaluation is evaluated as changed", %{ + env: env, + identity: identity + } do + # Given + %{project: %{segments: [segment]} = project} = env + + changed_rule = + put_in(hd(segment.rules).conditions, [%{hd(hd(segment.rules).conditions) | value: "free"}]) + + changed_env = %{env | project: %{project | segments: [%{segment | rules: [changed_rule]}]}} + + # When + before = Engine.get_identity_feature_state(env, identity, "feature") + changed = Engine.get_identity_feature_state(changed_env, identity, "feature") + unchanged = Engine.get_identity_feature_state(env, identity, "feature") + + # Then + assert %{enabled: true, feature_state_value: "segment"} = before + assert %{enabled: false, feature_state_value: "environment"} = changed + assert unchanged == before + end +end