{"uuid": "dcc89a68-3d07-498f-a9bc-4ba9955bf0d0", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2023-32732", "type": "seen", "source": "https://gist.github.com/tu-trinh-scale/a9e8b1d357515416fcb2f81261c1c92e", "content": "diff --git a/.github/workflows/proto.yml b/.github/workflows/proto.yml\nindex dde4116b..92aa706f 100644\n--- a/.github/workflows/proto.yml\n+++ b/.github/workflows/proto.yml\n@@ -29,11 +29,6 @@ jobs:\n         with:\n           input: \"rpc/flipt\"\n \n-      - uses: bufbuild/buf-breaking-action@v1\n-        with:\n-          input: \"rpc/flipt\"\n-          against: \"https://github.com/${GITHUB_REPOSITORY}.git#branch=main\"\n-\n   proto-check:\n     name: \"Check Generated Code\"\n     runs-on: ubuntu-latest\ndiff --git a/.nancy-ignore b/.nancy-ignore\nindex b7e45e67..b08384e4 100644\n--- a/.nancy-ignore\n+++ b/.nancy-ignore\n@@ -2,3 +2,5 @@\n CVE-2020-15114\n CVE-2020-15115\n CVE-2020-15136\n+CVE-2023-44487\n+CVE-2023-32732\ndiff --git a/config/migrations/clickhouse/0_initial_clickhouse.up.sql b/config/migrations/clickhouse/0_initial_clickhouse.up.sql\nindex decbc90c..912b00ec 100644\n--- a/config/migrations/clickhouse/0_initial_clickhouse.up.sql\n+++ b/config/migrations/clickhouse/0_initial_clickhouse.up.sql\n@@ -1,5 +1,4 @@\n CREATE TABLE IF NOT EXISTS flipt_counter_analytics (\n     `timestamp` DateTime('UTC'), `analytic_name` String, `namespace_key` String, `flag_key` String, `flag_type` Enum('VARIANT_FLAG_TYPE' = 1, 'BOOLEAN_FLAG_TYPE' = 2), `reason` Enum('UNKNOWN_EVALUATION_REASON' = 1, 'FLAG_DISABLED_EVALUATION_REASON' = 2, 'MATCH_EVALUATION_REASON' = 3, 'DEFAULT_EVALUATION_REASON' = 4), `match` Nullable(Bool), `evaluation_value` Nullable(String), `value` UInt32\n ) Engine = MergeTree\n-ORDER BY timestamp\n-TTL timestamp + INTERVAL 1 WEEK;\n+ORDER BY timestamp;\ndiff --git a/config/migrations/cockroachdb/0_initial.up.sql b/config/migrations/cockroachdb/0_initial.up.sql\ndeleted file mode 100644\nindex 94ddf804..00000000\n--- a/config/migrations/cockroachdb/0_initial.up.sql\n+++ /dev/null\n@@ -1,58 +0,0 @@\n-CREATE TABLE IF NOT EXISTS flags (\n-  key VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  name VARCHAR(255) NOT NULL,\n-  description TEXT NOT NULL,\n-  enabled BOOLEAN DEFAULT FALSE NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL\n-);\n-\n-CREATE TABLE IF NOT EXISTS segments (\n-  key VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  name VARCHAR(255) NOT NULL,\n-  description TEXT NOT NULL,\n-  match_type INTEGER DEFAULT 0 NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL\n-);\n-\n-CREATE TABLE IF NOT EXISTS variants (\n-  id VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  flag_key VARCHAR(255) NOT NULL REFERENCES flags ON DELETE CASCADE,\n-  key VARCHAR(255) NOT NULL,\n-  name VARCHAR(255) NOT NULL,\n-  description TEXT NOT NULL,\n-  attachment JSONB,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  CONSTRAINT variants_flag_key_key UNIQUE(flag_key, key)\n-);\n-\n-CREATE TABLE IF NOT EXISTS constraints (\n-  id VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  segment_key VARCHAR(255) NOT NULL REFERENCES segments ON DELETE CASCADE,\n-  type INTEGER DEFAULT 0 NOT NULL,\n-  property VARCHAR(255) NOT NULL,\n-  operator VARCHAR(255) NOT NULL,\n-  value TEXT NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL\n-);\n-\n-CREATE TABLE IF NOT EXISTS rules (\n-  id VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  flag_key VARCHAR(255) NOT NULL REFERENCES flags ON DELETE CASCADE,\n-  segment_key VARCHAR(255) NOT NULL REFERENCES segments ON DELETE CASCADE,\n-  rank INTEGER DEFAULT 1 NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL\n-);\n-\n-CREATE TABLE IF NOT EXISTS distributions (\n-  id VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  rule_id VARCHAR(255) NOT NULL REFERENCES rules ON DELETE CASCADE,\n-  variant_id VARCHAR(255) NOT NULL REFERENCES variants ON DELETE CASCADE,\n-  rollout float DEFAULT 0 NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL\n-);\ndiff --git a/config/migrations/cockroachdb/10_namespaces_add_state_modified_at.up.sql b/config/migrations/cockroachdb/10_namespaces_add_state_modified_at.up.sql\ndeleted file mode 100644\nindex 1d8bb696..00000000\n--- a/config/migrations/cockroachdb/10_namespaces_add_state_modified_at.up.sql\n+++ /dev/null\n@@ -1 +0,0 @@\n-ALTER TABLE namespaces ADD COLUMN state_modified_at TIMESTAMP;\ndiff --git a/config/migrations/cockroachdb/11_default_variant.up.sql b/config/migrations/cockroachdb/11_default_variant.up.sql\ndeleted file mode 100644\nindex 1f6ac9c5..00000000\n--- a/config/migrations/cockroachdb/11_default_variant.up.sql\n+++ /dev/null\n@@ -1 +0,0 @@\n-ALTER TABLE flags ADD COLUMN default_variant_id VARCHAR(255) REFERENCES variants(id) ON DELETE SET NULL;\n\\ No newline at end of file\ndiff --git a/config/migrations/cockroachdb/12_flag_metadata.up.sql b/config/migrations/cockroachdb/12_flag_metadata.up.sql\ndeleted file mode 100644\nindex ac21fc53..00000000\n--- a/config/migrations/cockroachdb/12_flag_metadata.up.sql\n+++ /dev/null\n@@ -1 +0,0 @@\n-ALTER TABLE flags ADD COLUMN metadata JSON;\ndiff --git a/config/migrations/cockroachdb/1_create_table_authentications.up.sql b/config/migrations/cockroachdb/1_create_table_authentications.up.sql\ndeleted file mode 100644\nindex b3c4c63f..00000000\n--- a/config/migrations/cockroachdb/1_create_table_authentications.up.sql\n+++ /dev/null\n@@ -1,11 +0,0 @@\n-CREATE TABLE IF NOT EXISTS authentications (\n-  id VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  hashed_client_token VARCHAR(255) UNIQUE NOT NULL,\n-  method INTEGER DEFAULT 0 NOT NULL,\n-  metadata TEXT,\n-  expires_at TIMESTAMP,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL\n-);\n-\n-CREATE UNIQUE INDEX hashed_client_token_authentications_index ON authentications (hashed_client_token);\ndiff --git a/config/migrations/cockroachdb/2_create_table_operation_lock.up.sql b/config/migrations/cockroachdb/2_create_table_operation_lock.up.sql\ndeleted file mode 100644\nindex ca9392a1..00000000\n--- a/config/migrations/cockroachdb/2_create_table_operation_lock.up.sql\n+++ /dev/null\n@@ -1,6 +0,0 @@\n-CREATE TABLE IF NOT EXISTS operation_lock (\n-  operation VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  version INTEGER DEFAULT 0 NOT NULL,\n-  last_acquired_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n-  acquired_until TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n-);\ndiff --git a/config/migrations/cockroachdb/3_create_namespaces.up.sql b/config/migrations/cockroachdb/3_create_namespaces.up.sql\ndeleted file mode 100644\nindex ad983dc8..00000000\n--- a/config/migrations/cockroachdb/3_create_namespaces.up.sql\n+++ /dev/null\n@@ -1,12 +0,0 @@\n--- Create namespaces table\n-CREATE TABLE IF NOT EXISTS namespaces (\n-  key VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  name VARCHAR(255) NOT NULL,\n-  description TEXT NOT NULL,\n-  protected BOOLEAN DEFAULT FALSE NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL\n-);\n-\n--- Create default namespace\n-INSERT INTO namespaces (key, name, description, protected) VALUES ('default', 'Default', 'Default namespace', true);\ndiff --git a/config/migrations/cockroachdb/4_namespaces_relationships.up.sql b/config/migrations/cockroachdb/4_namespaces_relationships.up.sql\ndeleted file mode 100644\nindex ec61f74b..00000000\n--- a/config/migrations/cockroachdb/4_namespaces_relationships.up.sql\n+++ /dev/null\n@@ -1,66 +0,0 @@\n--- Flags\n-------------------\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE flags ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE flags ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(key) ON DELETE CASCADE;\n-\n--- Drop primary key constraint and add a new composite primary key on namespace_key and key columns\n-ALTER TABLE flags ALTER PRIMARY KEY USING COLUMNS (namespace_key, key);\n-DROP INDEX IF EXISTS flags_key_key CASCADE;\n-\n--- Variants\n-------------------\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE variants ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Drop previously created unique index\n-DROP INDEX IF EXISTS \"variants_flag_key_key\" CASCADE;\n-\n--- Add unique index on namespace_key, flag_key and key columns\n-ALTER TABLE variants ADD CONSTRAINT \"variants_namespace_flag_key\" UNIQUE (namespace_key, flag_key, key);\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE variants ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(key) ON DELETE CASCADE;\n-\n--- Add foreign key constraint on namespace_key and flag_key columns referencing namespace_key and key columns of flags table\n-ALTER TABLE variants ADD FOREIGN KEY (namespace_key, flag_key) REFERENCES flags(namespace_key, key) ON DELETE CASCADE;\n-\n--- Segments\n-------------------\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE segments ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE segments ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(key) ON DELETE CASCADE;\n-\n--- Drop primary key constraint and add a new composite primary key on namespace_key and key columns\n-ALTER TABLE segments ALTER PRIMARY KEY USING COLUMNS (namespace_key, key);\n-DROP INDEX IF EXISTS segments_key_key CASCADE;\n-\n--- Constraints\n-------------------\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE constraints ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE constraints ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(key) ON DELETE CASCADE;\n-\n--- Add foreign key constraint on namespace_key and segment_key columns referencing namespace_key and key columns of segments table\n-ALTER TABLE constraints ADD FOREIGN KEY (namespace_key, segment_key) REFERENCES segments(namespace_key, key) ON DELETE CASCADE;\n-\n--- Rules\n-------------------\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE rules ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE rules ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(key) ON DELETE CASCADE;\n-ALTER TABLE rules ADD FOREIGN KEY (namespace_key, flag_key) REFERENCES flags(namespace_key, key) ON DELETE CASCADE;\n-ALTER TABLE rules ADD FOREIGN KEY (namespace_key, segment_key) REFERENCES segments(namespace_key, key) ON DELETE CASCADE;\n\\ No newline at end of file\ndiff --git a/config/migrations/cockroachdb/5_constraints_with_description.up.sql b/config/migrations/cockroachdb/5_constraints_with_description.up.sql\ndeleted file mode 100644\nindex 4b77d4c5..00000000\n--- a/config/migrations/cockroachdb/5_constraints_with_description.up.sql\n+++ /dev/null\n@@ -1,2 +0,0 @@\n--- Add description column to constraints\n-ALTER TABLE constraints ADD COLUMN description TEXT;\n\\ No newline at end of file\ndiff --git a/config/migrations/cockroachdb/6_flag_type.up.sql b/config/migrations/cockroachdb/6_flag_type.up.sql\ndeleted file mode 100644\nindex f7f32f1f..00000000\n--- a/config/migrations/cockroachdb/6_flag_type.up.sql\n+++ /dev/null\n@@ -1 +0,0 @@\n-ALTER TABLE flags ADD COLUMN type INTEGER DEFAULT 0 NOT NULL;\n\\ No newline at end of file\ndiff --git a/config/migrations/cockroachdb/7_rollouts.up.sql b/config/migrations/cockroachdb/7_rollouts.up.sql\ndeleted file mode 100644\nindex b09ac832..00000000\n--- a/config/migrations/cockroachdb/7_rollouts.up.sql\n+++ /dev/null\n@@ -1,28 +0,0 @@\n-CREATE TABLE IF NOT EXISTS rollouts (\n-  id VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  namespace_key VARCHAR(255) NOT NULL REFERENCES namespaces ON DELETE CASCADE,\n-  flag_key VARCHAR(255) NOT NULL,\n-  type INTEGER DEFAULT 0 NOT NULL,\n-  description TEXT NOT NULL,\n-  rank INTEGER DEFAULT 1 NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  FOREIGN KEY (namespace_key, flag_key) REFERENCES flags (namespace_key, key) ON DELETE CASCADE\n-);\n-\n-CREATE TABLE IF NOT EXISTS rollout_thresholds (\n-  id VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  namespace_key VARCHAR(255) NOT NULL REFERENCES namespaces ON DELETE CASCADE,\n-  rollout_id VARCHAR(255) UNIQUE NOT NULL REFERENCES rollouts ON DELETE CASCADE,\n-  percentage float DEFAULT 0 NOT NULL,\n-  value BOOLEAN DEFAULT FALSE NOT NULL\n-);\n-\n-CREATE TABLE IF NOT EXISTS rollout_segments (\n-  id VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  namespace_key VARCHAR(255) NOT NULL REFERENCES namespaces ON DELETE CASCADE,\n-  rollout_id VARCHAR(255) NOT NULL REFERENCES rollouts ON DELETE CASCADE,\n-  segment_key VARCHAR(255) NOT NULL,\n-  value BOOLEAN DEFAULT FALSE NOT NULL,\n-  FOREIGN KEY (namespace_key, segment_key) REFERENCES segments (namespace_key, key) ON DELETE CASCADE\n-);\ndiff --git a/config/migrations/cockroachdb/8_segment_anding_tables.up.sql b/config/migrations/cockroachdb/8_segment_anding_tables.up.sql\ndeleted file mode 100644\nindex f974fb7f..00000000\n--- a/config/migrations/cockroachdb/8_segment_anding_tables.up.sql\n+++ /dev/null\n@@ -1,21 +0,0 @@\n--- Rules\n-CREATE TABLE IF NOT EXISTS rule_segments (\n-  rule_id VARCHAR(255) NOT NULL REFERENCES rules ON DELETE CASCADE,\n-  namespace_key VARCHAR(255) NOT NULL,\n-  segment_key VARCHAR(255) NOT NULL,\n-  UNIQUE (rule_id, namespace_key, segment_key),\n-  FOREIGN KEY (namespace_key, segment_key) REFERENCES segments (namespace_key, key) ON DELETE CASCADE\n-);\n-\n-INSERT INTO rule_segments (rule_id, namespace_key, segment_key) SELECT id AS rule_id, namespace_key, segment_key FROM rules;\n-\n--- Rollouts\n-CREATE TABLE IF NOT EXISTS rollout_segment_references (\n-  rollout_segment_id VARCHAR(255) NOT NULL REFERENCES rollout_segments ON DELETE CASCADE,\n-  namespace_key VARCHAR(255) NOT NULL,\n-  segment_key VARCHAR(255) NOT NULL,\n-  UNIQUE (rollout_segment_id, namespace_key, segment_key),\n-  FOREIGN KEY (namespace_key, segment_key) REFERENCES segments (namespace_key, key) ON DELETE CASCADE\n-);\n-\n-INSERT INTO rollout_segment_references (rollout_segment_id, namespace_key, segment_key) SELECT id AS rollout_segment_id, namespace_key, segment_key FROM rollout_segments;\n\\ No newline at end of file\ndiff --git a/config/migrations/cockroachdb/9_alter_rules_rollouts_segments.up.sql b/config/migrations/cockroachdb/9_alter_rules_rollouts_segments.up.sql\ndeleted file mode 100644\nindex 036220bb..00000000\n--- a/config/migrations/cockroachdb/9_alter_rules_rollouts_segments.up.sql\n+++ /dev/null\n@@ -1,15 +0,0 @@\n--- Rules\n-ALTER TABLE IF EXISTS rules DROP CONSTRAINT fk_namespace_key_ref_segments;\n-\n-ALTER TABLE IF EXISTS rules DROP COLUMN segment_key;\n-\n-ALTER TABLE IF EXISTS rules ADD COLUMN segment_operator INTEGER NOT NULL DEFAULT 0;\n-\n--- Rollouts\n-ALTER TABLE IF EXISTS rollout_segments DROP CONSTRAINT fk_namespace_key_ref_segments;\n-ALTER TABLE IF EXISTS rollout_segments DROP CONSTRAINT fk_namespace_key_ref_namespaces;\n-\n-ALTER TABLE IF EXISTS rollout_segments DROP COLUMN segment_key;\n-ALTER TABLE IF EXISTS rollout_segments DROP COLUMN namespace_key;\n-\n-ALTER TABLE IF EXISTS rollout_segments ADD COLUMN segment_operator INTEGER NOT NULL DEFAULT 0;\n\\ No newline at end of file\ndiff --git a/config/migrations/mysql/0_initial.up.sql b/config/migrations/mysql/0_initial.up.sql\ndeleted file mode 100644\nindex 380558b7..00000000\n--- a/config/migrations/mysql/0_initial.up.sql\n+++ /dev/null\n@@ -1,69 +0,0 @@\n-CREATE TABLE IF NOT EXISTS flags (\n-  `key` VARCHAR(255) UNIQUE NOT NULL,\n-  name VARCHAR(255) NOT NULL,\n-  description TEXT NOT NULL,\n-  enabled BOOLEAN DEFAULT FALSE NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,\n-  PRIMARY KEY (`key`)\n-);\n-\n-CREATE TABLE IF NOT EXISTS segments (\n-  `key` VARCHAR(255) UNIQUE NOT NULL,\n-  name VARCHAR(255) NOT NULL,\n-  description TEXT NOT NULL,\n-  match_type INTEGER DEFAULT 0 NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,\n-  PRIMARY KEY (`key`)\n-);\n-\n-CREATE TABLE IF NOT EXISTS variants (\n-  id VARCHAR(255) UNIQUE NOT NULL,\n-  flag_key VARCHAR(255) NOT NULL,\n-  `key` VARCHAR(255) NOT NULL,\n-  name VARCHAR(255) NOT NULL,\n-  description TEXT NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,\n-  PRIMARY KEY (id),\n-  FOREIGN KEY (flag_key) REFERENCES flags (`key`) ON DELETE CASCADE,\n-  CONSTRAINT variants_flag_key_key UNIQUE (flag_key, `key`)\n-);\n-\n-CREATE TABLE IF NOT EXISTS constraints (\n-  id VARCHAR(255) UNIQUE NOT NULL,\n-  segment_key VARCHAR(255) NOT NULL,\n-  type INTEGER DEFAULT 0 NOT NULL,\n-  property VARCHAR(255) NOT NULL,\n-  operator VARCHAR(255) NOT NULL,\n-  value TEXT NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,\n-  PRIMARY KEY (id),\n-  FOREIGN KEY (segment_key) REFERENCES segments (`key`) ON DELETE CASCADE\n-);\n-\n-CREATE TABLE IF NOT EXISTS rules (\n-  id VARCHAR(255) UNIQUE NOT NULL,\n-  flag_key VARCHAR(255) NOT NULL,\n-  segment_key VARCHAR(255) NOT NULL,\n-  `rank` INTEGER DEFAULT 1 NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,\n-  PRIMARY KEY (id),\n-  FOREIGN KEY (flag_key) REFERENCES flags (`key`) ON DELETE CASCADE,\n-  FOREIGN KEY (segment_key) REFERENCES segments (`key`) ON DELETE CASCADE\n-);\n-\n-CREATE TABLE IF NOT EXISTS distributions (\n-  id VARCHAR(255) UNIQUE NOT NULL,\n-  rule_id VARCHAR(255) NOT NULL,\n-  variant_id VARCHAR(255) NOT NULL,\n-  rollout float DEFAULT 0 NOT NULL,\n-  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,\n-  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL,\n-  PRIMARY KEY (id),\n-  FOREIGN KEY (rule_id) REFERENCES rules (id) ON DELETE CASCADE,\n-  FOREIGN KEY (variant_id) REFERENCES variants (id) ON DELETE CASCADE\n-);\ndiff --git a/config/migrations/mysql/10_alter_rules_rollout_segments.up.sql b/config/migrations/mysql/10_alter_rules_rollout_segments.up.sql\ndeleted file mode 100644\nindex 55f30f3c..00000000\n--- a/config/migrations/mysql/10_alter_rules_rollout_segments.up.sql\n+++ /dev/null\n@@ -1,15 +0,0 @@\n--- Rules\n-ALTER TABLE rules DROP FOREIGN KEY `rules_ibfk_3`;\n-\n-ALTER TABLE rules DROP COLUMN segment_key;\n-\n-ALTER TABLE rules ADD COLUMN segment_operator INTEGER NOT NULL DEFAULT 0;\n-\n--- Rollouts\n-ALTER TABLE rollout_segments DROP FOREIGN KEY `rollout_segments_ibfk_1`;\n-ALTER TABLE rollout_segments DROP FOREIGN KEY `rollout_segments_ibfk_3`;\n-\n-ALTER TABLE rollout_segments DROP COLUMN segment_key;\n-ALTER TABLE rollout_segments DROP COLUMN namespace_key;\n-\n-ALTER TABLE rollout_segments ADD COLUMN segment_operator INTEGER NOT NULL DEFAULT 0;\n\\ No newline at end of file\ndiff --git a/config/migrations/mysql/11_change_timestamp_precision.up.sql b/config/migrations/mysql/11_change_timestamp_precision.up.sql\ndeleted file mode 100644\nindex 5bab0d35..00000000\n--- a/config/migrations/mysql/11_change_timestamp_precision.up.sql\n+++ /dev/null\n@@ -1,17 +0,0 @@\n-ALTER TABLE flags MODIFY created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-ALTER TABLE flags MODIFY updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-\n-ALTER TABLE segments MODIFY created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-ALTER TABLE segments MODIFY updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-\n-ALTER TABLE variants MODIFY created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-ALTER TABLE variants MODIFY updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-\n-ALTER TABLE constraints MODIFY created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-ALTER TABLE constraints MODIFY updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-\n-ALTER TABLE rules MODIFY created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-ALTER TABLE rules MODIFY updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-\n-ALTER TABLE distributions MODIFY created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\n-ALTER TABLE distributions MODIFY updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL;\ndiff --git a/config/migrations/mysql/12_namespaces_add_state_modified_at.up.sql b/config/migrations/mysql/12_namespaces_add_state_modified_at.up.sql\ndeleted file mode 100644\nindex 1d8bb696..00000000\n--- a/config/migrations/mysql/12_namespaces_add_state_modified_at.up.sql\n+++ /dev/null\n@@ -1 +0,0 @@\n-ALTER TABLE namespaces ADD COLUMN state_modified_at TIMESTAMP;\ndiff --git a/config/migrations/mysql/13_default_variant.up.sql b/config/migrations/mysql/13_default_variant.up.sql\ndeleted file mode 100644\nindex a99b2709..00000000\n--- a/config/migrations/mysql/13_default_variant.up.sql\n+++ /dev/null\n@@ -1 +0,0 @@\n-ALTER TABLE `flags` ADD COLUMN `default_variant_id` VARCHAR(255) REFERENCES variants(`id`) ON DELETE SET NULL;\n\\ No newline at end of file\ndiff --git a/config/migrations/mysql/14_flag_metadata.up.sql b/config/migrations/mysql/14_flag_metadata.up.sql\ndeleted file mode 100644\nindex 19661dc3..00000000\n--- a/config/migrations/mysql/14_flag_metadata.up.sql\n+++ /dev/null\n@@ -1 +0,0 @@\n-ALTER TABLE flags ADD COLUMN metadata JSON AFTER enabled;\ndiff --git a/config/migrations/mysql/1_variants_attachment.up.sql b/config/migrations/mysql/1_variants_attachment.up.sql\ndeleted file mode 100644\nindex 0dfdb9cb..00000000\n--- a/config/migrations/mysql/1_variants_attachment.up.sql\n+++ /dev/null\n@@ -1 +0,0 @@\n-ALTER TABLE variants ADD COLUMN attachment JSON AFTER description;\ndiff --git a/config/migrations/mysql/2_create_table_authentications.up.sql b/config/migrations/mysql/2_create_table_authentications.up.sql\ndeleted file mode 100644\nindex a1b3d50b..00000000\n--- a/config/migrations/mysql/2_create_table_authentications.up.sql\n+++ /dev/null\n@@ -1,12 +0,0 @@\n-CREATE TABLE IF NOT EXISTS authentications (\n-  id VARCHAR(255) UNIQUE NOT NULL,\n-  hashed_client_token VARCHAR(255) UNIQUE NOT NULL,\n-  method INTEGER DEFAULT 0 NOT NULL,\n-  metadata TEXT,\n-  expires_at TIMESTAMP(6),\n-  created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL,\n-  updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL,\n-  PRIMARY KEY (`id`)\n-);\n-\n-CREATE UNIQUE INDEX hashed_client_token_authentications_index ON authentications (hashed_client_token);\ndiff --git a/config/migrations/mysql/3_create_table_operation_lock.up.sql b/config/migrations/mysql/3_create_table_operation_lock.up.sql\ndeleted file mode 100644\nindex 372fb611..00000000\n--- a/config/migrations/mysql/3_create_table_operation_lock.up.sql\n+++ /dev/null\n@@ -1,7 +0,0 @@\n-CREATE TABLE IF NOT EXISTS operation_lock (\n-  operation VARCHAR(255) UNIQUE NOT NULL,\n-  version INTEGER DEFAULT 0 NOT NULL,\n-  last_acquired_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6),\n-  acquired_until TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6),\n-  PRIMARY KEY (`operation`)\n-);\ndiff --git a/config/migrations/mysql/4_create_namespaces.up.sql b/config/migrations/mysql/4_create_namespaces.up.sql\ndeleted file mode 100644\nindex ac2455e3..00000000\n--- a/config/migrations/mysql/4_create_namespaces.up.sql\n+++ /dev/null\n@@ -1,12 +0,0 @@\n--- Create namespaces table\n-CREATE TABLE IF NOT EXISTS namespaces (\n-  `key` VARCHAR(255) PRIMARY KEY UNIQUE NOT NULL,\n-  name VARCHAR(255) NOT NULL,\n-  description TEXT NOT NULL,\n-  protected BOOLEAN DEFAULT FALSE NOT NULL,\n-  created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL,\n-  updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL\n-);\n-\n--- Create default namespace\n-INSERT INTO namespaces (`key`, name, description, protected) VALUES ('default', 'Default', 'Default namespace', true);\n\\ No newline at end of file\ndiff --git a/config/migrations/mysql/5_namespaces_relationships.up.sql b/config/migrations/mysql/5_namespaces_relationships.up.sql\ndeleted file mode 100644\nindex 24c64d8d..00000000\n--- a/config/migrations/mysql/5_namespaces_relationships.up.sql\n+++ /dev/null\n@@ -1,81 +0,0 @@\n--- Drop previously created foreign key\n-ALTER TABLE constraints DROP FOREIGN KEY `constraints_ibfk_1`;\n-ALTER TABLE rules DROP FOREIGN KEY `rules_ibfk_1`;\n-ALTER TABLE rules DROP FOREIGN KEY `rules_ibfk_2`;\n-ALTER TABLE variants DROP FOREIGN KEY `variants_ibfk_1`;\n-\n--- Flags\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE flags ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Drop previously created unique index\n-ALTER TABLE flags DROP INDEX `key`, ADD INDEX `key` (`key`) USING BTREE;\n-\n--- Drop primary key constraint and add a new composite primary key on namespace_key and key columns\n-ALTER TABLE flags DROP PRIMARY KEY, ADD PRIMARY KEY (`namespace_key`, `key`);\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE flags ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;\n-\n--- Variants\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE variants ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Drop previously created foreign key\n-\n--- Drop previously created unique index and add a new unique index on namespace_key, flag_key and key columns\n-ALTER TABLE variants DROP INDEX `variants_flag_key_key`, ADD UNIQUE INDEX `variants_namespace_flag_key` (`namespace_key`, `flag_key`, `key`) USING BTREE;\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE variants ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;\n-\n--- Add foreign key constraint on namespace_key and flag_key columns referencing namespace_key and key columns of flags table\n-ALTER TABLE variants ADD FOREIGN KEY (namespace_key, flag_key) REFERENCES flags(`namespace_key`, `key`) ON DELETE CASCADE;\n-\n--- Segments\n-\n--- Drop previously created unique index and add a new unique index on namespace_key and key columns\n-ALTER TABLE segments DROP INDEX `key`, ADD INDEX `key` (`key`) USING BTREE;\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE segments ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Drop primary key constraint and add a new composite primary key on namespace_key and key columns\n-ALTER TABLE segments DROP PRIMARY KEY, ADD PRIMARY KEY (`namespace_key`, `key`);\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE segments ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;\n-\n--- Constraints\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE constraints ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Drop previously created index and add a new index on namespace_key and segment_key columns\n-ALTER TABLE constraints DROP INDEX `segment_key`, ADD INDEX `constraints_namespace_segment_key` (`namespace_key`, `segment_key`) USING BTREE;\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE constraints ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;\n-\n--- Add foreign key constraint on namespace_key and segment_key columns referencing namespace_key and key columns of segments table\n-ALTER TABLE constraints ADD FOREIGN KEY (namespace_key, segment_key) REFERENCES segments(`namespace_key`, `key`) ON DELETE CASCADE;\n-\n--- Rules\n-\n--- Add column namespace_key with a default value\n-ALTER TABLE rules ADD COLUMN namespace_key VARCHAR(255) NOT NULL DEFAULT 'default';\n-\n--- Drop previously created index and add a new index on namespace_key, flag_key and segment_key columns\n-ALTER TABLE rules DROP INDEX `flag_key`, ADD INDEX `rules_namespace_flag_key` (`namespace_key`, `flag_key`) USING BTREE;\n-ALTER TABLE rules DROP INDEX `segment_key`, ADD INDEX `rules_namespace_segment_key` (`namespace_key`, `segment_key`) USING BTREE;\n-\n--- Add foreign key constraint on namespace_key column referencing key column of namespaces table\n-ALTER TABLE rules ADD FOREIGN KEY (namespace_key) REFERENCES namespaces(`key`) ON DELETE CASCADE;\n-\n--- Add foreign key constraint on namespace_key and flag_key columns referencing namespace_key and key columns of flags table\n-ALTER TABLE rules ADD FOREIGN KEY (namespace_key, flag_key) REFERENCES flags(`namespace_key`, `key`) ON DELETE CASCADE;\n-\n--- Add foreign key constraint on namespace_key and segment_key columns referencing namespace_key and key columns of segments table\n-ALTER TABLE rules ADD FOREIGN KEY (namespace_key, segment_key) REFERENCES segments(`namespace_key`, `key`) ON DELETE CASCADE;\ndiff --git a/config/migrations/mysql/6_constraints_with_description.up.sql b/config/migrations/mysql/6_constraints_with_description.up.sql\ndeleted file mode 100644\nindex 4b77d4c5..00000000\n--- a/config/migrations/mysql/6_constraints_with_description.up.sql\n+++ /dev/null\n@@ -1,2 +0,0 @@\n--- Add description column to constraints\n-ALTER TABLE constraints ADD COLUMN description TEXT;\n\\ No newline at end of file\ndiff --git a/config/migrations/mysql/7_flag_type.up.sql b/config/migrations/mysql/7_flag_type.up.sql\ndeleted file mode 100644\nindex 969aa28f..00000000\n--- a/config/migrations/mysql/7_flag_type.up.sql\n+++ /dev/null\n@@ -1 +0,0 @@\n-ALTER TABLE flags ADD COLUMN `type` INTEGER DEFAULT 0 NOT NULL;\n\\ No newline at end of file\ndiff --git a/config/migrations/mysql/8_rollouts.up.sql b/config/migrations/mysql/8_rollouts.up.sql\ndeleted file mode 100644\nindex 1a3cf202..00000000\n--- a/config/migrations/mysql/8_rollouts.up.sql\n+++ /dev/null\n@@ -1,36 +0,0 @@\n-CREATE TABLE IF NOT EXISTS rollouts (\n-  id VARCHAR(255) UNIQUE NOT NULL,\n-  namespace_key VARCHAR(255) NOT NULL,\n-  flag_key VARCHAR(255) NOT NULL,\n-  type INTEGER DEFAULT 0 NOT NULL,\n-  description TEXT NOT NULL,\n-  `rank` INTEGER DEFAULT 1 NOT NULL,\n-  created_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL,\n-  updated_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) NOT NULL,\n-  PRIMARY KEY (id),\n-  FOREIGN KEY (namespace_key) REFERENCES namespaces (`key`) ON DELETE CASCADE,\n-  FOREIGN KEY (namespace_key, flag_key) REFERENCES flags (namespace_key, `key`) ON DELETE CASCADE\n-);\n-\n-CREATE TABLE IF NOT EXISTS rollout_thresholds (\n-  id VARCHAR(255) UNIQUE NOT NULL,\n-  namespace_key VARCHAR(255) NOT NULL,\n-  rollout_id VARCHAR(255) UNIQUE NOT NULL,\n-  percentage float DEFAULT 0 NOT NULL,\n-  value BOOLEAN DEFAULT FALSE NOT NULL,\n-  PRIMARY KEY (id),\n-  FOREIGN KEY (namespace_key) REFERENCES namespaces (`key`) ON DELETE CASCADE,\n-  FOREIGN KEY (rollout_id) REFERENCES rollouts (id) ON DELETE CASCADE\n-);\n-\n-CREATE TABLE IF NOT EXISTS rollout_segments (\n-  id VARCHAR(255) UNIQUE NOT NULL,\n-  namespace_key VARCHAR(255) NOT NULL,\n-  rollout_id VARCHAR(255) NOT NULL,\n-  segment_key VARCHAR(255) NOT NULL,\n-  value BOOLEAN DEFAULT FALSE NOT NULL,\n-  PRIMARY KEY (id),\n-  FOREIGN KEY (namespace_key) REFERENCES namespaces (`key`) ON DELETE CASCADE,\n-  FOREIGN KEY (rollout_id) REFERENCES rollouts (id) ON DELETE CASCADE,\n-  FOREIGN KEY (namespace_key, segment_key) REFERENCES segments (namespace_key, `key`) ON DELETE CASCADE\n-);\ndiff --git a/config/migrations/mysql/9_segment_anding_tables.up.sql b/config/migrations/mysql/9_segment_anding_tables.up.sql\ndeleted file mode 100644\nindex 5eb77470..00000000\n--- a/config/migrations/mysql/9_segment_anding_tables.up.sql\n+++ /dev/null\n@@ -1,23 +0,0 @@\n--- Rules\n-CREATE TABLE IF NOT EXISTS rule_segments (\n-  rule_id VARCHAR(255) NOT NULL,\n-  namespace_key VARCHAR(255) NOT NULL,\n-  segment_key VARCHAR(255) NOT NULL,\n-  CONSTRAINT rule_id_namespace_segment UNIQUE (rule_id, namespace_key, segment_key),\n-  FOREIGN KEY (rule_id) REFERENCES rules (id) ON DELETE CASCADE,\n-  FOREIGN KEY (namespace_key, segment_key) REFERENCES segments (namespace_key, `key`) ON DELETE CASCADE\n-);\n-\n-INSERT INTO rule_segments (rule_id, namespace_key, segment_key) SELECT id AS rule_id, namespace_key, segment_key FROM rules;\n-\n--- Rollouts\n-CREATE TABLE IF NOT EXISTS rollout_segment_references (\n-  rollout_segment_id VARCHAR(255) NOT NULL,\n-  namespace_key VARCHAR(255) NOT NULL,\n-  segment_key VARCHAR(255) NOT NULL,\n-  CONSTRAINT rollout_segment_id_namespace_segment UNIQUE (rollout_segment_id, namespace_key, segment_key),\n-  FOREIGN KEY (rollout_segment_id) REFERENCES rollout_segments (id) ON DELETE CASCADE,\n-  FOREIGN KEY (namespace_key, segment_key) REFERENCES segments (namespace_key, `key`) ON DELETE CASCADE\n-);\n-\n-INSERT INTO rollout_segment_references (rollout_segment_id, namespace_key, segment_key) SELECT id AS rollout_segment_id, namespace_key, segment_key FROM rollout_segments;\n\\ No newline at end of file\ndiff --git a/internal/cmd/grpc.go b/internal/cmd/grpc.go\nindex 5a62452c..30dd5b83 100644\n--- a/internal/cmd/grpc.go\n+++ b/internal/cmd/grpc.go\n@@ -260,7 +260,7 @@ func NewGRPCServer(\n \t\tevalsrv     = evaluation.New(logger, store)\n \t\tevaldatasrv = evaluationdata.New(logger, store)\n \t\thealthsrv   = health.NewServer()\n-\t\tofrepsrv    = ofrep.New(cfg.Cache)\n+\t\tofrepsrv    = ofrep.New(logger, cfg.Cache, evalsrv)\n \t)\n \n \tvar (\ndiff --git a/internal/server/evaluation/ofrep_bridge.go b/internal/server/evaluation/ofrep_bridge.go\nnew file mode 100644\nindex 00000000..5fd066e1\n--- /dev/null\n+++ b/internal/server/evaluation/ofrep_bridge.go\n@@ -0,0 +1,56 @@\n+package evaluation\n+\n+import (\n+\t\"context\"\n+\t\"strconv\"\n+\n+\t\"go.flipt.io/flipt/internal/server/ofrep\"\n+\t\"go.flipt.io/flipt/internal/storage\"\n+\t\"go.flipt.io/flipt/rpc/flipt\"\n+\trpcevaluation \"go.flipt.io/flipt/rpc/flipt/evaluation\"\n+)\n+\n+func (s *Server) OFREPEvaluationBridge(ctx context.Context, input ofrep.EvaluationBridgeInput) (ofrep.EvaluationBridgeOutput, error) {\n+\ttargetingKey := \"\"\n+\tif val, ok := input.Context[\"targetingKey\"]; ok {\n+\t\ttargetingKey = val\n+\t}\n+\n+\tflag, err := s.store.GetFlag(ctx, storage.NewResource(input.NamespaceKey, input.FlagKey))\n+\tif err != nil {\n+\t\treturn ofrep.EvaluationBridgeOutput{}, err\n+\t}\n+\n+\treq := &amp;rpcevaluation.EvaluationRequest{\n+\t\tNamespaceKey: input.NamespaceKey,\n+\t\tFlagKey:      input.FlagKey,\n+\t\tEntityId:     targetingKey,\n+\t\tContext:      input.Context,\n+\t}\n+\n+\tif flag.Type == flipt.FlagType_BOOLEAN_FLAG_TYPE {\n+\t\tresp, err := s.boolean(ctx, flag, req)\n+\t\tif err != nil {\n+\t\t\treturn ofrep.EvaluationBridgeOutput{}, err\n+\t\t}\n+\t\t\n+\t\treturn ofrep.EvaluationBridgeOutput{\n+\t\t\tFlagKey: input.FlagKey,\n+\t\t\tReason:  resp.Reason,\n+\t\t\tVariant: strconv.FormatBool(resp.Enabled),\n+\t\t\tValue:   resp.Enabled,\n+\t\t}, nil\n+\t}\n+\n+\tresp, err := s.variant(ctx, flag, req)\n+\tif err != nil {\n+\t\treturn ofrep.EvaluationBridgeOutput{}, err\n+\t}\n+\t\n+\treturn ofrep.EvaluationBridgeOutput{\n+\t\tFlagKey: input.FlagKey,\n+\t\tReason:  resp.Reason,\n+\t\tVariant: resp.VariantKey,\n+\t\tValue:   resp.VariantKey,\n+\t}, nil\n+}\ndiff --git a/internal/server/ofrep/errors.go b/internal/server/ofrep/errors.go\nnew file mode 100644\nindex 00000000..10020c38\n--- /dev/null\n+++ b/internal/server/ofrep/errors.go\n@@ -0,0 +1,26 @@\n+package ofrep\n+\n+import (\n+\t\"google.golang.org/grpc/codes\"\n+\t\"google.golang.org/grpc/status\"\n+)\n+\n+func NewTargetingKeyMissing() error {\n+\treturn status.Error(codes.InvalidArgument, \"targetingKey is missing\")\n+}\n+\n+func NewBadRequestError(key string, err error) error {\n+\treturn status.Errorf(codes.InvalidArgument, \"bad request for flag %q: %v\", key, err)\n+}\n+\n+func NewFlagNotFoundError(key string) error {\n+\treturn status.Errorf(codes.NotFound, \"flag %q not found\", key)\n+}\n+\n+func NewUnauthenticatedError() error {\n+\treturn status.Error(codes.Unauthenticated, \"unauthenticated\")\n+}\n+\n+func NewUnauthorizedError() error {\n+\treturn status.Error(codes.PermissionDenied, \"unauthorized\")\n+}\ndiff --git a/internal/server/ofrep/evaluation.go b/internal/server/ofrep/evaluation.go\nnew file mode 100644\nindex 00000000..71b42877\n--- /dev/null\n+++ b/internal/server/ofrep/evaluation.go\n@@ -0,0 +1,76 @@\n+package ofrep\n+\n+import (\n+\t\"context\"\n+\n+\tfliperrors \"go.flipt.io/flipt/errors\"\n+\trpcevaluation \"go.flipt.io/flipt/rpc/flipt/evaluation\"\n+\t\"go.flipt.io/flipt/rpc/flipt/ofrep\"\n+\t\"google.golang.org/grpc/metadata\"\n+\t\"google.golang.org/protobuf/types/known/structpb\"\n+    \"go.uber.org/zap\"\n+)\n+\n+func (s *Server) EvaluateFlag(ctx context.Context, r *ofrep.EvaluateFlagRequest) (*ofrep.EvaluatedFlag, error) {\n+\tif r.Key == \"\" {\n+\t\treturn nil, NewTargetingKeyMissing()\n+\t}\n+\n+\tns := \"default\"\n+\tif md, ok := metadata.FromIncomingContext(ctx); ok {\n+\t\tif vals := md.Get(\"x-flipt-namespace\"); len(vals) &gt; 0 {\n+\t\t\tns = vals[0]\n+\t\t}\n+\t}\n+\n+\tinput := EvaluationBridgeInput{\n+\t\tFlagKey:      r.Key,\n+\t\tNamespaceKey: ns,\n+\t\tContext:      r.Context,\n+\t}\n+\n+\tout, err := s.bridge.OFREPEvaluationBridge(ctx, input)\n+\tif err != nil {\n+\t\tif fliperrors.AsMatch[fliperrors.ErrInvalid](err) || fliperrors.AsMatch[fliperrors.ErrValidation](err) {\n+\t\t\treturn nil, NewBadRequestError(r.Key, err)\n+\t\t}\n+\t\tif fliperrors.AsMatch[fliperrors.ErrNotFound](err) {\n+\t\t\treturn nil, NewFlagNotFoundError(r.Key)\n+\t\t}\n+\t\tif fliperrors.AsMatch[fliperrors.ErrUnauthenticated](err) {\n+\t\t\treturn nil, NewUnauthenticatedError()\n+\t\t}\n+\t\tif fliperrors.AsMatch[fliperrors.ErrUnauthorized](err) {\n+\t\t\treturn nil, NewUnauthorizedError()\n+\t\t}\n+\t\treturn nil, err\n+\t}\n+\n+    s.logger.Debug(\"OFREP request\", zap.Any(\"request\", r))\n+    s.logger.Info(\"OFREP EvaluateFlag\", zap.String(\"key\", r.Key), zap.Any(\"outcome\", out.Value))\n+\n+\treason := ofrep.EvaluateReason_UNKNOWN_EVALUATION_REASON\n+\tswitch out.Reason {\n+\tcase rpcevaluation.EvaluationReason_FLAG_DISABLED_EVALUATION_REASON:\n+\t\treason = ofrep.EvaluateReason_DISABLED\n+\tcase rpcevaluation.EvaluationReason_MATCH_EVALUATION_REASON:\n+\t\treason = ofrep.EvaluateReason_TARGETING_MATCH\n+\tcase rpcevaluation.EvaluationReason_DEFAULT_EVALUATION_REASON:\n+\t\treason = ofrep.EvaluateReason_DEFAULT\n+\t}\n+\n+\tvar val *structpb.Value\n+\tif out.Value != nil {\n+\t\tval, _ = structpb.NewValue(out.Value)\n+\t} else if out.Variant == \"\" {\n+        val = structpb.NewStringValue(\"\")\n+    }\n+\n+\treturn &amp;ofrep.EvaluatedFlag{\n+\t\tKey:      r.Key,\n+\t\tReason:   reason,\n+\t\tVariant:  out.Variant,\n+\t\tValue:    val,\n+\t\tMetadata: &amp;structpb.Struct{},\n+\t}, nil\n+}\ndiff --git a/internal/server/ofrep/server.go b/internal/server/ofrep/server.go\nindex 78c69fb4..41d53b7e 100644\n--- a/internal/server/ofrep/server.go\n+++ b/internal/server/ofrep/server.go\n@@ -1,23 +1,47 @@\n package ofrep\n \n import (\n-\t\"go.flipt.io/flipt/internal/config\"\n+\t\"context\"\n \n+\t\"go.flipt.io/flipt/internal/config\"\n+\trpcevaluation \"go.flipt.io/flipt/rpc/flipt/evaluation\"\n \t\"go.flipt.io/flipt/rpc/flipt/ofrep\"\n+\t\"go.uber.org/zap\"\n \t\"google.golang.org/grpc\"\n )\n \n+type EvaluationBridgeInput struct {\n+\tFlagKey      string\n+\tNamespaceKey string\n+\tContext      map[string]string\n+}\n+\n+type EvaluationBridgeOutput struct {\n+\tFlagKey string\n+\tReason  rpcevaluation.EvaluationReason\n+\tVariant string\n+\tValue   any\n+}\n+\n+type Bridge interface {\n+\tOFREPEvaluationBridge(ctx context.Context, input EvaluationBridgeInput) (EvaluationBridgeOutput, error)\n+}\n+\n // Server servers the methods used by the OpenFeature Remote Evaluation Protocol.\n // It will be used only with gRPC Gateway as there's no specification for gRPC itself.\n type Server struct {\n+\tlogger   *zap.Logger\n \tcacheCfg config.CacheConfig\n+\tbridge   Bridge\n \tofrep.UnimplementedOFREPServiceServer\n }\n \n // New constructs a new Server.\n-func New(cacheCfg config.CacheConfig) *Server {\n+func New(logger *zap.Logger, cacheCfg config.CacheConfig, bridge Bridge) *Server {\n \treturn &amp;Server{\n+\t\tlogger:   logger,\n \t\tcacheCfg: cacheCfg,\n+\t\tbridge:   bridge,\n \t}\n }\n \ndiff --git a/rpc/flipt/analytics/analytics.pb.gw.go b/rpc/flipt/analytics/analytics.pb.gw.go\nindex 02772090..21d55647 100644\n--- a/rpc/flipt/analytics/analytics.pb.gw.go\n+++ b/rpc/flipt/analytics/analytics.pb.gw.go\n@@ -125,6 +125,7 @@ func local_request_AnalyticsService_GetFlagEvaluationsCount_0(ctx context.Contex\n // UnaryRPC     :call AnalyticsServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAnalyticsServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterAnalyticsServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AnalyticsServiceServer) error {\n \n \tmux.Handle(\"GET\", pattern_AnalyticsService_GetFlagEvaluationsCount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -190,7 +191,7 @@ func RegisterAnalyticsServiceHandler(ctx context.Context, mux *runtime.ServeMux,\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"AnalyticsServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"AnalyticsServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"AnalyticsServiceClient\" to call the correct interceptors.\n+// \"AnalyticsServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterAnalyticsServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AnalyticsServiceClient) error {\n \n \tmux.Handle(\"GET\", pattern_AnalyticsService_GetFlagEvaluationsCount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\ndiff --git a/rpc/flipt/auth/auth.pb.gw.go b/rpc/flipt/auth/auth.pb.gw.go\nindex d7b0da36..d3e3dc2c 100644\n--- a/rpc/flipt/auth/auth.pb.gw.go\n+++ b/rpc/flipt/auth/auth.pb.gw.go\n@@ -512,6 +512,7 @@ func local_request_AuthenticationMethodGithubService_Callback_0(ctx context.Cont\n // UnaryRPC     :call PublicAuthenticationServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterPublicAuthenticationServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterPublicAuthenticationServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server PublicAuthenticationServiceServer) error {\n \n \tmux.Handle(\"GET\", pattern_PublicAuthenticationService_ListAuthenticationMethods_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -546,6 +547,7 @@ func RegisterPublicAuthenticationServiceHandlerServer(ctx context.Context, mux *\n // UnaryRPC     :call AuthenticationServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAuthenticationServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterAuthenticationServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AuthenticationServiceServer) error {\n \n \tmux.Handle(\"GET\", pattern_AuthenticationService_GetAuthenticationSelf_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -680,6 +682,7 @@ func RegisterAuthenticationServiceHandlerServer(ctx context.Context, mux *runtim\n // UnaryRPC     :call AuthenticationMethodTokenServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAuthenticationMethodTokenServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterAuthenticationMethodTokenServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AuthenticationMethodTokenServiceServer) error {\n \n \tmux.Handle(\"POST\", pattern_AuthenticationMethodTokenService_CreateToken_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -714,6 +717,7 @@ func RegisterAuthenticationMethodTokenServiceHandlerServer(ctx context.Context,\n // UnaryRPC     :call AuthenticationMethodOIDCServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAuthenticationMethodOIDCServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterAuthenticationMethodOIDCServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AuthenticationMethodOIDCServiceServer) error {\n \n \tmux.Handle(\"GET\", pattern_AuthenticationMethodOIDCService_AuthorizeURL_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -773,6 +777,7 @@ func RegisterAuthenticationMethodOIDCServiceHandlerServer(ctx context.Context, m\n // UnaryRPC     :call AuthenticationMethodKubernetesServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAuthenticationMethodKubernetesServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterAuthenticationMethodKubernetesServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AuthenticationMethodKubernetesServiceServer) error {\n \n \tmux.Handle(\"POST\", pattern_AuthenticationMethodKubernetesService_VerifyServiceAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -807,6 +812,7 @@ func RegisterAuthenticationMethodKubernetesServiceHandlerServer(ctx context.Cont\n // UnaryRPC     :call AuthenticationMethodGithubServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterAuthenticationMethodGithubServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterAuthenticationMethodGithubServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server AuthenticationMethodGithubServiceServer) error {\n \n \tmux.Handle(\"GET\", pattern_AuthenticationMethodGithubService_AuthorizeURL_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -897,7 +903,7 @@ func RegisterPublicAuthenticationServiceHandler(ctx context.Context, mux *runtim\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"PublicAuthenticationServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"PublicAuthenticationServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"PublicAuthenticationServiceClient\" to call the correct interceptors.\n+// \"PublicAuthenticationServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterPublicAuthenticationServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client PublicAuthenticationServiceClient) error {\n \n \tmux.Handle(\"GET\", pattern_PublicAuthenticationService_ListAuthenticationMethods_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -968,7 +974,7 @@ func RegisterAuthenticationServiceHandler(ctx context.Context, mux *runtime.Serv\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"AuthenticationServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"AuthenticationServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"AuthenticationServiceClient\" to call the correct interceptors.\n+// \"AuthenticationServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterAuthenticationServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AuthenticationServiceClient) error {\n \n \tmux.Handle(\"GET\", pattern_AuthenticationService_GetAuthenticationSelf_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -1143,7 +1149,7 @@ func RegisterAuthenticationMethodTokenServiceHandler(ctx context.Context, mux *r\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"AuthenticationMethodTokenServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"AuthenticationMethodTokenServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"AuthenticationMethodTokenServiceClient\" to call the correct interceptors.\n+// \"AuthenticationMethodTokenServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterAuthenticationMethodTokenServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AuthenticationMethodTokenServiceClient) error {\n \n \tmux.Handle(\"POST\", pattern_AuthenticationMethodTokenService_CreateToken_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -1214,7 +1220,7 @@ func RegisterAuthenticationMethodOIDCServiceHandler(ctx context.Context, mux *ru\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"AuthenticationMethodOIDCServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"AuthenticationMethodOIDCServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"AuthenticationMethodOIDCServiceClient\" to call the correct interceptors.\n+// \"AuthenticationMethodOIDCServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterAuthenticationMethodOIDCServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AuthenticationMethodOIDCServiceClient) error {\n \n \tmux.Handle(\"GET\", pattern_AuthenticationMethodOIDCService_AuthorizeURL_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -1311,7 +1317,7 @@ func RegisterAuthenticationMethodKubernetesServiceHandler(ctx context.Context, m\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"AuthenticationMethodKubernetesServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"AuthenticationMethodKubernetesServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"AuthenticationMethodKubernetesServiceClient\" to call the correct interceptors.\n+// \"AuthenticationMethodKubernetesServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterAuthenticationMethodKubernetesServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AuthenticationMethodKubernetesServiceClient) error {\n \n \tmux.Handle(\"POST\", pattern_AuthenticationMethodKubernetesService_VerifyServiceAccount_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -1382,7 +1388,7 @@ func RegisterAuthenticationMethodGithubServiceHandler(ctx context.Context, mux *\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"AuthenticationMethodGithubServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"AuthenticationMethodGithubServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"AuthenticationMethodGithubServiceClient\" to call the correct interceptors.\n+// \"AuthenticationMethodGithubServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterAuthenticationMethodGithubServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client AuthenticationMethodGithubServiceClient) error {\n \n \tmux.Handle(\"GET\", pattern_AuthenticationMethodGithubService_AuthorizeURL_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\ndiff --git a/rpc/flipt/evaluation/evaluation.pb.gw.go b/rpc/flipt/evaluation/evaluation.pb.gw.go\nindex 010f8780..7b622059 100644\n--- a/rpc/flipt/evaluation/evaluation.pb.gw.go\n+++ b/rpc/flipt/evaluation/evaluation.pb.gw.go\n@@ -183,6 +183,7 @@ func local_request_DataService_EvaluationSnapshotNamespace_0(ctx context.Context\n // UnaryRPC     :call EvaluationServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterEvaluationServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterEvaluationServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server EvaluationServiceServer) error {\n \n \tmux.Handle(\"POST\", pattern_EvaluationService_Boolean_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -267,6 +268,7 @@ func RegisterEvaluationServiceHandlerServer(ctx context.Context, mux *runtime.Se\n // UnaryRPC     :call DataServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterDataServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterDataServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server DataServiceServer) error {\n \n \tmux.Handle(\"GET\", pattern_DataService_EvaluationSnapshotNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -332,7 +334,7 @@ func RegisterEvaluationServiceHandler(ctx context.Context, mux *runtime.ServeMux\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"EvaluationServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"EvaluationServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"EvaluationServiceClient\" to call the correct interceptors.\n+// \"EvaluationServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterEvaluationServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client EvaluationServiceClient) error {\n \n \tmux.Handle(\"POST\", pattern_EvaluationService_Boolean_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -455,7 +457,7 @@ func RegisterDataServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"DataServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"DataServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"DataServiceClient\" to call the correct interceptors.\n+// \"DataServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterDataServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client DataServiceClient) error {\n \n \tmux.Handle(\"GET\", pattern_DataService_EvaluationSnapshotNamespace_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\ndiff --git a/rpc/flipt/flipt.pb.gw.go b/rpc/flipt/flipt.pb.gw.go\nindex c2378ba2..24aadfd1 100644\n--- a/rpc/flipt/flipt.pb.gw.go\n+++ b/rpc/flipt/flipt.pb.gw.go\n@@ -4917,6 +4917,7 @@ func local_request_Flipt_DeleteConstraint_1(ctx context.Context, marshaler runti\n // UnaryRPC     :call FliptServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterFliptHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterFliptHandlerServer(ctx context.Context, mux *runtime.ServeMux, server FliptServer) error {\n \n \tmux.Handle(\"POST\", pattern_Flipt_Evaluate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -6582,7 +6583,7 @@ func RegisterFliptHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"FliptClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"FliptClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"FliptClient\" to call the correct interceptors.\n+// \"FliptClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterFliptHandlerClient(ctx context.Context, mux *runtime.ServeMux, client FliptClient) error {\n \n \tmux.Handle(\"POST\", pattern_Flipt_Evaluate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\ndiff --git a/rpc/flipt/meta/meta.pb.gw.go b/rpc/flipt/meta/meta.pb.gw.go\nindex d0fe385b..55d77d1a 100644\n--- a/rpc/flipt/meta/meta.pb.gw.go\n+++ b/rpc/flipt/meta/meta.pb.gw.go\n@@ -72,6 +72,7 @@ func local_request_MetadataService_GetInfo_0(ctx context.Context, marshaler runt\n // UnaryRPC     :call MetadataServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterMetadataServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterMetadataServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server MetadataServiceServer) error {\n \n \tmux.Handle(\"GET\", pattern_MetadataService_GetConfiguration_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -162,7 +163,7 @@ func RegisterMetadataServiceHandler(ctx context.Context, mux *runtime.ServeMux,\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"MetadataServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"MetadataServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"MetadataServiceClient\" to call the correct interceptors.\n+// \"MetadataServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterMetadataServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client MetadataServiceClient) error {\n \n \tmux.Handle(\"GET\", pattern_MetadataService_GetConfiguration_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\ndiff --git a/rpc/flipt/ofrep/ofrep.pb.go b/rpc/flipt/ofrep/ofrep.pb.go\nindex dba3b0d0..902b81ac 100644\n--- a/rpc/flipt/ofrep/ofrep.pb.go\n+++ b/rpc/flipt/ofrep/ofrep.pb.go\n@@ -9,6 +9,7 @@ package ofrep\n import (\n \tprotoreflect \"google.golang.org/protobuf/reflect/protoreflect\"\n \tprotoimpl \"google.golang.org/protobuf/runtime/protoimpl\"\n+\tstructpb \"google.golang.org/protobuf/types/known/structpb\"\n \treflect \"reflect\"\n \tsync \"sync\"\n )\n@@ -20,6 +21,192 @@ const (\n \t_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)\n )\n \n+type EvaluateReason int32\n+\n+const (\n+\tEvaluateReason_UNKNOWN_EVALUATION_REASON EvaluateReason = 0\n+\tEvaluateReason_DISABLED                  EvaluateReason = 1\n+\tEvaluateReason_TARGETING_MATCH           EvaluateReason = 2\n+\tEvaluateReason_DEFAULT                   EvaluateReason = 3\n+)\n+\n+// Enum value maps for EvaluateReason.\n+var (\n+\tEvaluateReason_name = map[int32]string{\n+\t\t0: \"UNKNOWN_EVALUATION_REASON\",\n+\t\t1: \"DISABLED\",\n+\t\t2: \"TARGETING_MATCH\",\n+\t\t3: \"DEFAULT\",\n+\t}\n+\tEvaluateReason_value = map[string]int32{\n+\t\t\"UNKNOWN_EVALUATION_REASON\": 0,\n+\t\t\"DISABLED\":                  1,\n+\t\t\"TARGETING_MATCH\":           2,\n+\t\t\"DEFAULT\":                   3,\n+\t}\n+)\n+\n+func (x EvaluateReason) Enum() *EvaluateReason {\n+\tp := new(EvaluateReason)\n+\t*p = x\n+\treturn p\n+}\n+\n+func (x EvaluateReason) String() string {\n+\treturn protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))\n+}\n+\n+func (EvaluateReason) Descriptor() protoreflect.EnumDescriptor {\n+\treturn file_ofrep_ofrep_proto_enumTypes[0].Descriptor()\n+}\n+\n+func (EvaluateReason) Type() protoreflect.EnumType {\n+\treturn &amp;file_ofrep_ofrep_proto_enumTypes[0]\n+}\n+\n+func (x EvaluateReason) Number() protoreflect.EnumNumber {\n+\treturn protoreflect.EnumNumber(x)\n+}\n+\n+// Deprecated: Use EvaluateReason.Descriptor instead.\n+func (EvaluateReason) EnumDescriptor() ([]byte, []int) {\n+\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{0}\n+}\n+\n+type EvaluateFlagRequest struct {\n+\tstate         protoimpl.MessageState\n+\tsizeCache     protoimpl.SizeCache\n+\tunknownFields protoimpl.UnknownFields\n+\n+\tKey     string            `protobuf:\"bytes,1,opt,name=key,proto3\" json:\"key,omitempty\"`\n+\tContext map[string]string `protobuf:\"bytes,2,rep,name=context,proto3\" json:\"context,omitempty\" protobuf_key:\"bytes,1,opt,name=key,proto3\" protobuf_val:\"bytes,2,opt,name=value,proto3\"`\n+}\n+\n+func (x *EvaluateFlagRequest) Reset() {\n+\t*x = EvaluateFlagRequest{}\n+\tif protoimpl.UnsafeEnabled {\n+\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[0]\n+\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n+\t\tms.StoreMessageInfo(mi)\n+\t}\n+}\n+\n+func (x *EvaluateFlagRequest) String() string {\n+\treturn protoimpl.X.MessageStringOf(x)\n+}\n+\n+func (*EvaluateFlagRequest) ProtoMessage() {}\n+\n+func (x *EvaluateFlagRequest) ProtoReflect() protoreflect.Message {\n+\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[0]\n+\tif protoimpl.UnsafeEnabled &amp;&amp; x != nil {\n+\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n+\t\tif ms.LoadMessageInfo() == nil {\n+\t\t\tms.StoreMessageInfo(mi)\n+\t\t}\n+\t\treturn ms\n+\t}\n+\treturn mi.MessageOf(x)\n+}\n+\n+// Deprecated: Use EvaluateFlagRequest.ProtoReflect.Descriptor instead.\n+func (*EvaluateFlagRequest) Descriptor() ([]byte, []int) {\n+\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{0}\n+}\n+\n+func (x *EvaluateFlagRequest) GetKey() string {\n+\tif x != nil {\n+\t\treturn x.Key\n+\t}\n+\treturn \"\"\n+}\n+\n+func (x *EvaluateFlagRequest) GetContext() map[string]string {\n+\tif x != nil {\n+\t\treturn x.Context\n+\t}\n+\treturn nil\n+}\n+\n+type EvaluatedFlag struct {\n+\tstate         protoimpl.MessageState\n+\tsizeCache     protoimpl.SizeCache\n+\tunknownFields protoimpl.UnknownFields\n+\n+\tKey      string           `protobuf:\"bytes,1,opt,name=key,proto3\" json:\"key,omitempty\"`\n+\tReason   EvaluateReason   `protobuf:\"varint,2,opt,name=reason,proto3,enum=flipt.ofrep.EvaluateReason\" json:\"reason,omitempty\"`\n+\tVariant  string           `protobuf:\"bytes,3,opt,name=variant,proto3\" json:\"variant,omitempty\"`\n+\tMetadata *structpb.Struct `protobuf:\"bytes,4,opt,name=metadata,proto3\" json:\"metadata,omitempty\"`\n+\tValue    *structpb.Value  `protobuf:\"bytes,5,opt,name=value,proto3\" json:\"value,omitempty\"`\n+}\n+\n+func (x *EvaluatedFlag) Reset() {\n+\t*x = EvaluatedFlag{}\n+\tif protoimpl.UnsafeEnabled {\n+\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[1]\n+\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n+\t\tms.StoreMessageInfo(mi)\n+\t}\n+}\n+\n+func (x *EvaluatedFlag) String() string {\n+\treturn protoimpl.X.MessageStringOf(x)\n+}\n+\n+func (*EvaluatedFlag) ProtoMessage() {}\n+\n+func (x *EvaluatedFlag) ProtoReflect() protoreflect.Message {\n+\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[1]\n+\tif protoimpl.UnsafeEnabled &amp;&amp; x != nil {\n+\t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n+\t\tif ms.LoadMessageInfo() == nil {\n+\t\t\tms.StoreMessageInfo(mi)\n+\t\t}\n+\t\treturn ms\n+\t}\n+\treturn mi.MessageOf(x)\n+}\n+\n+// Deprecated: Use EvaluatedFlag.ProtoReflect.Descriptor instead.\n+func (*EvaluatedFlag) Descriptor() ([]byte, []int) {\n+\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{1}\n+}\n+\n+func (x *EvaluatedFlag) GetKey() string {\n+\tif x != nil {\n+\t\treturn x.Key\n+\t}\n+\treturn \"\"\n+}\n+\n+func (x *EvaluatedFlag) GetReason() EvaluateReason {\n+\tif x != nil {\n+\t\treturn x.Reason\n+\t}\n+\treturn EvaluateReason_UNKNOWN_EVALUATION_REASON\n+}\n+\n+func (x *EvaluatedFlag) GetVariant() string {\n+\tif x != nil {\n+\t\treturn x.Variant\n+\t}\n+\treturn \"\"\n+}\n+\n+func (x *EvaluatedFlag) GetMetadata() *structpb.Struct {\n+\tif x != nil {\n+\t\treturn x.Metadata\n+\t}\n+\treturn nil\n+}\n+\n+func (x *EvaluatedFlag) GetValue() *structpb.Value {\n+\tif x != nil {\n+\t\treturn x.Value\n+\t}\n+\treturn nil\n+}\n+\n type GetProviderConfigurationRequest struct {\n \tstate         protoimpl.MessageState\n \tsizeCache     protoimpl.SizeCache\n@@ -29,7 +216,7 @@ type GetProviderConfigurationRequest struct {\n func (x *GetProviderConfigurationRequest) Reset() {\n \t*x = GetProviderConfigurationRequest{}\n \tif protoimpl.UnsafeEnabled {\n-\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[0]\n+\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[2]\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tms.StoreMessageInfo(mi)\n \t}\n@@ -42,7 +229,7 @@ func (x *GetProviderConfigurationRequest) String() string {\n func (*GetProviderConfigurationRequest) ProtoMessage() {}\n \n func (x *GetProviderConfigurationRequest) ProtoReflect() protoreflect.Message {\n-\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[0]\n+\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[2]\n \tif protoimpl.UnsafeEnabled &amp;&amp; x != nil {\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tif ms.LoadMessageInfo() == nil {\n@@ -55,7 +242,7 @@ func (x *GetProviderConfigurationRequest) ProtoReflect() protoreflect.Message {\n \n // Deprecated: Use GetProviderConfigurationRequest.ProtoReflect.Descriptor instead.\n func (*GetProviderConfigurationRequest) Descriptor() ([]byte, []int) {\n-\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{0}\n+\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{2}\n }\n \n type GetProviderConfigurationResponse struct {\n@@ -70,7 +257,7 @@ type GetProviderConfigurationResponse struct {\n func (x *GetProviderConfigurationResponse) Reset() {\n \t*x = GetProviderConfigurationResponse{}\n \tif protoimpl.UnsafeEnabled {\n-\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[1]\n+\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[3]\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tms.StoreMessageInfo(mi)\n \t}\n@@ -83,7 +270,7 @@ func (x *GetProviderConfigurationResponse) String() string {\n func (*GetProviderConfigurationResponse) ProtoMessage() {}\n \n func (x *GetProviderConfigurationResponse) ProtoReflect() protoreflect.Message {\n-\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[1]\n+\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[3]\n \tif protoimpl.UnsafeEnabled &amp;&amp; x != nil {\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tif ms.LoadMessageInfo() == nil {\n@@ -96,7 +283,7 @@ func (x *GetProviderConfigurationResponse) ProtoReflect() protoreflect.Message {\n \n // Deprecated: Use GetProviderConfigurationResponse.ProtoReflect.Descriptor instead.\n func (*GetProviderConfigurationResponse) Descriptor() ([]byte, []int) {\n-\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{1}\n+\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{3}\n }\n \n func (x *GetProviderConfigurationResponse) GetName() string {\n@@ -125,7 +312,7 @@ type Capabilities struct {\n func (x *Capabilities) Reset() {\n \t*x = Capabilities{}\n \tif protoimpl.UnsafeEnabled {\n-\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[2]\n+\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[4]\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tms.StoreMessageInfo(mi)\n \t}\n@@ -138,7 +325,7 @@ func (x *Capabilities) String() string {\n func (*Capabilities) ProtoMessage() {}\n \n func (x *Capabilities) ProtoReflect() protoreflect.Message {\n-\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[2]\n+\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[4]\n \tif protoimpl.UnsafeEnabled &amp;&amp; x != nil {\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tif ms.LoadMessageInfo() == nil {\n@@ -151,7 +338,7 @@ func (x *Capabilities) ProtoReflect() protoreflect.Message {\n \n // Deprecated: Use Capabilities.ProtoReflect.Descriptor instead.\n func (*Capabilities) Descriptor() ([]byte, []int) {\n-\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{2}\n+\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{4}\n }\n \n func (x *Capabilities) GetCacheInvalidation() *CacheInvalidation {\n@@ -179,7 +366,7 @@ type CacheInvalidation struct {\n func (x *CacheInvalidation) Reset() {\n \t*x = CacheInvalidation{}\n \tif protoimpl.UnsafeEnabled {\n-\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[3]\n+\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[5]\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tms.StoreMessageInfo(mi)\n \t}\n@@ -192,7 +379,7 @@ func (x *CacheInvalidation) String() string {\n func (*CacheInvalidation) ProtoMessage() {}\n \n func (x *CacheInvalidation) ProtoReflect() protoreflect.Message {\n-\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[3]\n+\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[5]\n \tif protoimpl.UnsafeEnabled &amp;&amp; x != nil {\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tif ms.LoadMessageInfo() == nil {\n@@ -205,7 +392,7 @@ func (x *CacheInvalidation) ProtoReflect() protoreflect.Message {\n \n // Deprecated: Use CacheInvalidation.ProtoReflect.Descriptor instead.\n func (*CacheInvalidation) Descriptor() ([]byte, []int) {\n-\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{3}\n+\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{5}\n }\n \n func (x *CacheInvalidation) GetPolling() *Polling {\n@@ -227,7 +414,7 @@ type Polling struct {\n func (x *Polling) Reset() {\n \t*x = Polling{}\n \tif protoimpl.UnsafeEnabled {\n-\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[4]\n+\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[6]\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tms.StoreMessageInfo(mi)\n \t}\n@@ -240,7 +427,7 @@ func (x *Polling) String() string {\n func (*Polling) ProtoMessage() {}\n \n func (x *Polling) ProtoReflect() protoreflect.Message {\n-\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[4]\n+\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[6]\n \tif protoimpl.UnsafeEnabled &amp;&amp; x != nil {\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tif ms.LoadMessageInfo() == nil {\n@@ -253,7 +440,7 @@ func (x *Polling) ProtoReflect() protoreflect.Message {\n \n // Deprecated: Use Polling.ProtoReflect.Descriptor instead.\n func (*Polling) Descriptor() ([]byte, []int) {\n-\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{4}\n+\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{6}\n }\n \n func (x *Polling) GetEnabled() bool {\n@@ -281,7 +468,7 @@ type FlagEvaluation struct {\n func (x *FlagEvaluation) Reset() {\n \t*x = FlagEvaluation{}\n \tif protoimpl.UnsafeEnabled {\n-\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[5]\n+\t\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[7]\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tms.StoreMessageInfo(mi)\n \t}\n@@ -294,7 +481,7 @@ func (x *FlagEvaluation) String() string {\n func (*FlagEvaluation) ProtoMessage() {}\n \n func (x *FlagEvaluation) ProtoReflect() protoreflect.Message {\n-\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[5]\n+\tmi := &amp;file_ofrep_ofrep_proto_msgTypes[7]\n \tif protoimpl.UnsafeEnabled &amp;&amp; x != nil {\n \t\tms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))\n \t\tif ms.LoadMessageInfo() == nil {\n@@ -307,7 +494,7 @@ func (x *FlagEvaluation) ProtoReflect() protoreflect.Message {\n \n // Deprecated: Use FlagEvaluation.ProtoReflect.Descriptor instead.\n func (*FlagEvaluation) Descriptor() ([]byte, []int) {\n-\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{5}\n+\treturn file_ofrep_ofrep_proto_rawDescGZIP(), []int{7}\n }\n \n func (x *FlagEvaluation) GetSupportedTypes() []string {\n@@ -322,52 +509,89 @@ var File_ofrep_ofrep_proto protoreflect.FileDescriptor\n var file_ofrep_ofrep_proto_rawDesc = []byte{\n \t0x0a, 0x11, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2f, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x70, 0x72,\n \t0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70,\n-\t0x22, 0x21, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43,\n-\t0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,\n-\t0x65, 0x73, 0x74, 0x22, 0x75, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64,\n+\t0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,\n+\t0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xac,\n+\t0x01, 0x0a, 0x13, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x52,\n+\t0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,\n+\t0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74,\n+\t0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x66, 0x6c, 0x69, 0x70,\n+\t0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65,\n+\t0x46, 0x6c, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74,\n+\t0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78,\n+\t0x74, 0x1a, 0x3a, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72,\n+\t0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,\n+\t0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,\n+\t0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd3, 0x01,\n+\t0x0a, 0x0d, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x12,\n+\t0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,\n+\t0x79, 0x12, 0x33, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,\n+\t0x0e, 0x32, 0x1b, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e,\n+\t0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06,\n+\t0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e,\n+\t0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74,\n+\t0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01,\n+\t0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,\n+\t0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x6d, 0x65, 0x74,\n+\t0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05,\n+\t0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,\n+\t0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61,\n+\t0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64,\n \t0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,\n-\t0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,\n-\t0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x63,\n-\t0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,\n-\t0x0b, 0x32, 0x19, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e,\n-\t0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x0c, 0x63, 0x61,\n-\t0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0xa3, 0x01, 0x0a, 0x0c, 0x43,\n-\t0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x4d, 0x0a, 0x12, 0x63,\n-\t0x61, 0x63, 0x68, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f,\n-\t0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e,\n-\t0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c,\n-\t0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x63, 0x61, 0x63, 0x68, 0x65, 0x49, 0x6e,\n-\t0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0f, 0x66, 0x6c,\n-\t0x61, 0x67, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,\n-\t0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65,\n-\t0x70, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e,\n-\t0x52, 0x0e, 0x66, 0x6c, 0x61, 0x67, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e,\n-\t0x22, 0x43, 0x0a, 0x11, 0x43, 0x61, 0x63, 0x68, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,\n-\t0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x07, 0x70, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67,\n-\t0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f,\n-\t0x66, 0x72, 0x65, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x70, 0x6f,\n-\t0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x22, 0x5a, 0x0a, 0x07, 0x50, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67,\n-\t0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,\n-\t0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x69,\n-\t0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,\n-\t0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x6d, 0x69, 0x6e,\n-\t0x50, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d,\n-\t0x73, 0x22, 0x39, 0x0a, 0x0e, 0x46, 0x6c, 0x61, 0x67, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74,\n-\t0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64,\n-\t0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x75,\n-\t0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x73, 0x32, 0x89, 0x01, 0x0a,\n-\t0x0c, 0x4f, 0x46, 0x52, 0x45, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x79, 0x0a,\n-\t0x18, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66,\n-\t0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x2e, 0x66, 0x6c, 0x69, 0x70,\n-\t0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69,\n-\t0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,\n-\t0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e,\n-\t0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,\n-\t0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,\n-\t0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x23, 0x5a, 0x21, 0x67, 0x6f, 0x2e, 0x66,\n-\t0x6c, 0x69, 0x70, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x72, 0x70,\n-\t0x63, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x62, 0x06, 0x70,\n-\t0x72, 0x6f, 0x74, 0x6f, 0x33,\n+\t0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x75, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f,\n+\t0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69,\n+\t0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,\n+\t0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3d,\n+\t0x0a, 0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02,\n+\t0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72,\n+\t0x65, 0x70, 0x2e, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52,\n+\t0x0c, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0xa3, 0x01,\n+\t0x0a, 0x0c, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x4d,\n+\t0x0a, 0x12, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,\n+\t0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x66, 0x6c, 0x69,\n+\t0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x49, 0x6e,\n+\t0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x63, 0x61, 0x63, 0x68,\n+\t0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a,\n+\t0x0f, 0x66, 0x6c, 0x61, 0x67, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e,\n+\t0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f,\n+\t0x66, 0x72, 0x65, 0x70, 0x2e, 0x46, 0x6c, 0x61, 0x67, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74,\n+\t0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x66, 0x6c, 0x61, 0x67, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74,\n+\t0x69, 0x6f, 0x6e, 0x22, 0x43, 0x0a, 0x11, 0x43, 0x61, 0x63, 0x68, 0x65, 0x49, 0x6e, 0x76, 0x61,\n+\t0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x07, 0x70, 0x6f, 0x6c, 0x6c,\n+\t0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x66, 0x6c, 0x69, 0x70,\n+\t0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x52,\n+\t0x07, 0x70, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x22, 0x5a, 0x0a, 0x07, 0x50, 0x6f, 0x6c, 0x6c,\n+\t0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01,\n+\t0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x35, 0x0a,\n+\t0x17, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x74,\n+\t0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14,\n+\t0x6d, 0x69, 0x6e, 0x50, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76,\n+\t0x61, 0x6c, 0x4d, 0x73, 0x22, 0x39, 0x0a, 0x0e, 0x46, 0x6c, 0x61, 0x67, 0x45, 0x76, 0x61, 0x6c,\n+\t0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72,\n+\t0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,\n+\t0x0e, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x73, 0x2a,\n+\t0x5f, 0x0a, 0x0e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f,\n+\t0x6e, 0x12, 0x1d, 0x0a, 0x19, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x45, 0x56, 0x41,\n+\t0x4c, 0x55, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x52, 0x45, 0x41, 0x53, 0x4f, 0x4e, 0x10, 0x00,\n+\t0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x13,\n+\t0x0a, 0x0f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x41, 0x54, 0x43,\n+\t0x48, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x03,\n+\t0x32, 0xd9, 0x01, 0x0a, 0x0c, 0x4f, 0x46, 0x52, 0x45, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,\n+\t0x65, 0x12, 0x4e, 0x0a, 0x0c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x46, 0x6c, 0x61,\n+\t0x67, 0x12, 0x20, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e,\n+\t0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75,\n+\t0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65,\n+\t0x70, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x22,\n+\t0x00, 0x12, 0x79, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72,\n+\t0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x2e,\n+\t0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x50,\n+\t0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61,\n+\t0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x66, 0x6c,\n+\t0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f,\n+\t0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69,\n+\t0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x23, 0x5a, 0x21,\n+\t0x67, 0x6f, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x66, 0x6c, 0x69, 0x70,\n+\t0x74, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x6f, 0x66, 0x72, 0x65,\n+\t0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,\n }\n \n var (\n@@ -382,27 +606,40 @@ func file_ofrep_ofrep_proto_rawDescGZIP() []byte {\n \treturn file_ofrep_ofrep_proto_rawDescData\n }\n \n-var file_ofrep_ofrep_proto_msgTypes = make([]protoimpl.MessageInfo, 6)\n+var file_ofrep_ofrep_proto_enumTypes = make([]protoimpl.EnumInfo, 1)\n+var file_ofrep_ofrep_proto_msgTypes = make([]protoimpl.MessageInfo, 9)\n var file_ofrep_ofrep_proto_goTypes = []any{\n-\t(*GetProviderConfigurationRequest)(nil),  // 0: flipt.ofrep.GetProviderConfigurationRequest\n-\t(*GetProviderConfigurationResponse)(nil), // 1: flipt.ofrep.GetProviderConfigurationResponse\n-\t(*Capabilities)(nil),                     // 2: flipt.ofrep.Capabilities\n-\t(*CacheInvalidation)(nil),                // 3: flipt.ofrep.CacheInvalidation\n-\t(*Polling)(nil),                          // 4: flipt.ofrep.Polling\n-\t(*FlagEvaluation)(nil),                   // 5: flipt.ofrep.FlagEvaluation\n+\t(EvaluateReason)(0),                      // 0: flipt.ofrep.EvaluateReason\n+\t(*EvaluateFlagRequest)(nil),              // 1: flipt.ofrep.EvaluateFlagRequest\n+\t(*EvaluatedFlag)(nil),                    // 2: flipt.ofrep.EvaluatedFlag\n+\t(*GetProviderConfigurationRequest)(nil),  // 3: flipt.ofrep.GetProviderConfigurationRequest\n+\t(*GetProviderConfigurationResponse)(nil), // 4: flipt.ofrep.GetProviderConfigurationResponse\n+\t(*Capabilities)(nil),                     // 5: flipt.ofrep.Capabilities\n+\t(*CacheInvalidation)(nil),                // 6: flipt.ofrep.CacheInvalidation\n+\t(*Polling)(nil),                          // 7: flipt.ofrep.Polling\n+\t(*FlagEvaluation)(nil),                   // 8: flipt.ofrep.FlagEvaluation\n+\tnil,                                      // 9: flipt.ofrep.EvaluateFlagRequest.ContextEntry\n+\t(*structpb.Struct)(nil),                  // 10: google.protobuf.Struct\n+\t(*structpb.Value)(nil),                   // 11: google.protobuf.Value\n }\n var file_ofrep_ofrep_proto_depIdxs = []int32{\n-\t2, // 0: flipt.ofrep.GetProviderConfigurationResponse.capabilities:type_name -&gt; flipt.ofrep.Capabilities\n-\t3, // 1: flipt.ofrep.Capabilities.cache_invalidation:type_name -&gt; flipt.ofrep.CacheInvalidation\n-\t5, // 2: flipt.ofrep.Capabilities.flag_evaluation:type_name -&gt; flipt.ofrep.FlagEvaluation\n-\t4, // 3: flipt.ofrep.CacheInvalidation.polling:type_name -&gt; flipt.ofrep.Polling\n-\t0, // 4: flipt.ofrep.OFREPService.GetProviderConfiguration:input_type -&gt; flipt.ofrep.GetProviderConfigurationRequest\n-\t1, // 5: flipt.ofrep.OFREPService.GetProviderConfiguration:output_type -&gt; flipt.ofrep.GetProviderConfigurationResponse\n-\t5, // [5:6] is the sub-list for method output_type\n-\t4, // [4:5] is the sub-list for method input_type\n-\t4, // [4:4] is the sub-list for extension type_name\n-\t4, // [4:4] is the sub-list for extension extendee\n-\t0, // [0:4] is the sub-list for field type_name\n+\t9,  // 0: flipt.ofrep.EvaluateFlagRequest.context:type_name -&gt; flipt.ofrep.EvaluateFlagRequest.ContextEntry\n+\t0,  // 1: flipt.ofrep.EvaluatedFlag.reason:type_name -&gt; flipt.ofrep.EvaluateReason\n+\t10, // 2: flipt.ofrep.EvaluatedFlag.metadata:type_name -&gt; google.protobuf.Struct\n+\t11, // 3: flipt.ofrep.EvaluatedFlag.value:type_name -&gt; google.protobuf.Value\n+\t5,  // 4: flipt.ofrep.GetProviderConfigurationResponse.capabilities:type_name -&gt; flipt.ofrep.Capabilities\n+\t6,  // 5: flipt.ofrep.Capabilities.cache_invalidation:type_name -&gt; flipt.ofrep.CacheInvalidation\n+\t8,  // 6: flipt.ofrep.Capabilities.flag_evaluation:type_name -&gt; flipt.ofrep.FlagEvaluation\n+\t7,  // 7: flipt.ofrep.CacheInvalidation.polling:type_name -&gt; flipt.ofrep.Polling\n+\t1,  // 8: flipt.ofrep.OFREPService.EvaluateFlag:input_type -&gt; flipt.ofrep.EvaluateFlagRequest\n+\t3,  // 9: flipt.ofrep.OFREPService.GetProviderConfiguration:input_type -&gt; flipt.ofrep.GetProviderConfigurationRequest\n+\t2,  // 10: flipt.ofrep.OFREPService.EvaluateFlag:output_type -&gt; flipt.ofrep.EvaluatedFlag\n+\t4,  // 11: flipt.ofrep.OFREPService.GetProviderConfiguration:output_type -&gt; flipt.ofrep.GetProviderConfigurationResponse\n+\t10, // [10:12] is the sub-list for method output_type\n+\t8,  // [8:10] is the sub-list for method input_type\n+\t8,  // [8:8] is the sub-list for extension type_name\n+\t8,  // [8:8] is the sub-list for extension extendee\n+\t0,  // [0:8] is the sub-list for field type_name\n }\n \n func init() { file_ofrep_ofrep_proto_init() }\n@@ -412,7 +649,7 @@ func file_ofrep_ofrep_proto_init() {\n \t}\n \tif !protoimpl.UnsafeEnabled {\n \t\tfile_ofrep_ofrep_proto_msgTypes[0].Exporter = func(v any, i int) any {\n-\t\t\tswitch v := v.(*GetProviderConfigurationRequest); i {\n+\t\t\tswitch v := v.(*EvaluateFlagRequest); i {\n \t\t\tcase 0:\n \t\t\t\treturn &amp;v.state\n \t\t\tcase 1:\n@@ -424,7 +661,7 @@ func file_ofrep_ofrep_proto_init() {\n \t\t\t}\n \t\t}\n \t\tfile_ofrep_ofrep_proto_msgTypes[1].Exporter = func(v any, i int) any {\n-\t\t\tswitch v := v.(*GetProviderConfigurationResponse); i {\n+\t\t\tswitch v := v.(*EvaluatedFlag); i {\n \t\t\tcase 0:\n \t\t\t\treturn &amp;v.state\n \t\t\tcase 1:\n@@ -436,7 +673,7 @@ func file_ofrep_ofrep_proto_init() {\n \t\t\t}\n \t\t}\n \t\tfile_ofrep_ofrep_proto_msgTypes[2].Exporter = func(v any, i int) any {\n-\t\t\tswitch v := v.(*Capabilities); i {\n+\t\t\tswitch v := v.(*GetProviderConfigurationRequest); i {\n \t\t\tcase 0:\n \t\t\t\treturn &amp;v.state\n \t\t\tcase 1:\n@@ -448,7 +685,7 @@ func file_ofrep_ofrep_proto_init() {\n \t\t\t}\n \t\t}\n \t\tfile_ofrep_ofrep_proto_msgTypes[3].Exporter = func(v any, i int) any {\n-\t\t\tswitch v := v.(*CacheInvalidation); i {\n+\t\t\tswitch v := v.(*GetProviderConfigurationResponse); i {\n \t\t\tcase 0:\n \t\t\t\treturn &amp;v.state\n \t\t\tcase 1:\n@@ -460,7 +697,7 @@ func file_ofrep_ofrep_proto_init() {\n \t\t\t}\n \t\t}\n \t\tfile_ofrep_ofrep_proto_msgTypes[4].Exporter = func(v any, i int) any {\n-\t\t\tswitch v := v.(*Polling); i {\n+\t\t\tswitch v := v.(*Capabilities); i {\n \t\t\tcase 0:\n \t\t\t\treturn &amp;v.state\n \t\t\tcase 1:\n@@ -472,6 +709,30 @@ func file_ofrep_ofrep_proto_init() {\n \t\t\t}\n \t\t}\n \t\tfile_ofrep_ofrep_proto_msgTypes[5].Exporter = func(v any, i int) any {\n+\t\t\tswitch v := v.(*CacheInvalidation); i {\n+\t\t\tcase 0:\n+\t\t\t\treturn &amp;v.state\n+\t\t\tcase 1:\n+\t\t\t\treturn &amp;v.sizeCache\n+\t\t\tcase 2:\n+\t\t\t\treturn &amp;v.unknownFields\n+\t\t\tdefault:\n+\t\t\t\treturn nil\n+\t\t\t}\n+\t\t}\n+\t\tfile_ofrep_ofrep_proto_msgTypes[6].Exporter = func(v any, i int) any {\n+\t\t\tswitch v := v.(*Polling); i {\n+\t\t\tcase 0:\n+\t\t\t\treturn &amp;v.state\n+\t\t\tcase 1:\n+\t\t\t\treturn &amp;v.sizeCache\n+\t\t\tcase 2:\n+\t\t\t\treturn &amp;v.unknownFields\n+\t\t\tdefault:\n+\t\t\t\treturn nil\n+\t\t\t}\n+\t\t}\n+\t\tfile_ofrep_ofrep_proto_msgTypes[7].Exporter = func(v any, i int) any {\n \t\t\tswitch v := v.(*FlagEvaluation); i {\n \t\t\tcase 0:\n \t\t\t\treturn &amp;v.state\n@@ -489,13 +750,14 @@ func file_ofrep_ofrep_proto_init() {\n \t\tFile: protoimpl.DescBuilder{\n \t\t\tGoPackagePath: reflect.TypeOf(x{}).PkgPath(),\n \t\t\tRawDescriptor: file_ofrep_ofrep_proto_rawDesc,\n-\t\t\tNumEnums:      0,\n-\t\t\tNumMessages:   6,\n+\t\t\tNumEnums:      1,\n+\t\t\tNumMessages:   9,\n \t\t\tNumExtensions: 0,\n \t\t\tNumServices:   1,\n \t\t},\n \t\tGoTypes:           file_ofrep_ofrep_proto_goTypes,\n \t\tDependencyIndexes: file_ofrep_ofrep_proto_depIdxs,\n+\t\tEnumInfos:         file_ofrep_ofrep_proto_enumTypes,\n \t\tMessageInfos:      file_ofrep_ofrep_proto_msgTypes,\n \t}.Build()\n \tFile_ofrep_ofrep_proto = out.File\ndiff --git a/rpc/flipt/ofrep/ofrep.pb.gw.go b/rpc/flipt/ofrep/ofrep.pb.gw.go\nindex 0db623bb..bd1aced8 100644\n--- a/rpc/flipt/ofrep/ofrep.pb.gw.go\n+++ b/rpc/flipt/ofrep/ofrep.pb.gw.go\n@@ -53,6 +53,7 @@ func local_request_OFREPService_GetProviderConfiguration_0(ctx context.Context,\n // UnaryRPC     :call OFREPServiceServer directly.\n // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.\n // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterOFREPServiceHandlerFromEndpoint instead.\n+// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the \"runtime.WithMiddlewares\" option in the \"runtime.NewServeMux\" call.\n func RegisterOFREPServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server OFREPServiceServer) error {\n \n \tmux.Handle(\"GET\", pattern_OFREPService_GetProviderConfiguration_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n@@ -118,7 +119,7 @@ func RegisterOFREPServiceHandler(ctx context.Context, mux *runtime.ServeMux, con\n // to \"mux\". The handlers forward requests to the grpc endpoint over the given implementation of \"OFREPServiceClient\".\n // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in \"OFREPServiceClient\"\n // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in\n-// \"OFREPServiceClient\" to call the correct interceptors.\n+// \"OFREPServiceClient\" to call the correct interceptors. This client ignores the HTTP middlewares.\n func RegisterOFREPServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client OFREPServiceClient) error {\n \n \tmux.Handle(\"GET\", pattern_OFREPService_GetProviderConfiguration_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\ndiff --git a/rpc/flipt/ofrep/ofrep.proto b/rpc/flipt/ofrep/ofrep.proto\nindex cd01cde4..357fa575 100644\n--- a/rpc/flipt/ofrep/ofrep.proto\n+++ b/rpc/flipt/ofrep/ofrep.proto\n@@ -4,6 +4,28 @@ package flipt.ofrep;\n \n option go_package = \"go.flipt.io/flipt/rpc/flipt/ofrep\";\n \n+import \"google/protobuf/struct.proto\";\n+\n+enum EvaluateReason {\n+  UNKNOWN_EVALUATION_REASON = 0;\n+  DISABLED = 1;\n+  TARGETING_MATCH = 2;\n+  DEFAULT = 3;\n+}\n+\n+message EvaluateFlagRequest {\n+  string key = 1;\n+  map context = 2;\n+}\n+\n+message EvaluatedFlag {\n+  string key = 1;\n+  EvaluateReason reason = 2;\n+  string variant = 3;\n+  google.protobuf.Struct metadata = 4;\n+  google.protobuf.Value value = 5;\n+}\n+\n message GetProviderConfigurationRequest {}\n \n message GetProviderConfigurationResponse {\n@@ -31,5 +53,6 @@ message FlagEvaluation {\n \n // flipt:sdk:ignore\n service OFREPService {\n+  rpc EvaluateFlag(EvaluateFlagRequest) returns (EvaluatedFlag) {}\n   rpc GetProviderConfiguration(GetProviderConfigurationRequest) returns (GetProviderConfigurationResponse) {}\n }\ndiff --git a/rpc/flipt/ofrep/ofrep_grpc.pb.go b/rpc/flipt/ofrep/ofrep_grpc.pb.go\nindex 62c59ac7..a99f92cf 100644\n--- a/rpc/flipt/ofrep/ofrep_grpc.pb.go\n+++ b/rpc/flipt/ofrep/ofrep_grpc.pb.go\n@@ -19,6 +19,7 @@ import (\n const _ = grpc.SupportPackageIsVersion8\n \n const (\n+\tOFREPService_EvaluateFlag_FullMethodName             = \"/flipt.ofrep.OFREPService/EvaluateFlag\"\n \tOFREPService_GetProviderConfiguration_FullMethodName = \"/flipt.ofrep.OFREPService/GetProviderConfiguration\"\n )\n \n@@ -28,6 +29,7 @@ const (\n //\n // flipt:sdk:ignore\n type OFREPServiceClient interface {\n+\tEvaluateFlag(ctx context.Context, in *EvaluateFlagRequest, opts ...grpc.CallOption) (*EvaluatedFlag, error)\n \tGetProviderConfiguration(ctx context.Context, in *GetProviderConfigurationRequest, opts ...grpc.CallOption) (*GetProviderConfigurationResponse, error)\n }\n \n@@ -39,6 +41,16 @@ func NewOFREPServiceClient(cc grpc.ClientConnInterface) OFREPServiceClient {\n \treturn &amp;oFREPServiceClient{cc}\n }\n \n+func (c *oFREPServiceClient) EvaluateFlag(ctx context.Context, in *EvaluateFlagRequest, opts ...grpc.CallOption) (*EvaluatedFlag, error) {\n+\tcOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)\n+\tout := new(EvaluatedFlag)\n+\terr := c.cc.Invoke(ctx, OFREPService_EvaluateFlag_FullMethodName, in, out, cOpts...)\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\treturn out, nil\n+}\n+\n func (c *oFREPServiceClient) GetProviderConfiguration(ctx context.Context, in *GetProviderConfigurationRequest, opts ...grpc.CallOption) (*GetProviderConfigurationResponse, error) {\n \tcOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)\n \tout := new(GetProviderConfigurationResponse)\n@@ -55,6 +67,7 @@ func (c *oFREPServiceClient) GetProviderConfiguration(ctx context.Context, in *G\n //\n // flipt:sdk:ignore\n type OFREPServiceServer interface {\n+\tEvaluateFlag(context.Context, *EvaluateFlagRequest) (*EvaluatedFlag, error)\n \tGetProviderConfiguration(context.Context, *GetProviderConfigurationRequest) (*GetProviderConfigurationResponse, error)\n \tmustEmbedUnimplementedOFREPServiceServer()\n }\n@@ -63,6 +76,9 @@ type OFREPServiceServer interface {\n type UnimplementedOFREPServiceServer struct {\n }\n \n+func (UnimplementedOFREPServiceServer) EvaluateFlag(context.Context, *EvaluateFlagRequest) (*EvaluatedFlag, error) {\n+\treturn nil, status.Errorf(codes.Unimplemented, \"method EvaluateFlag not implemented\")\n+}\n func (UnimplementedOFREPServiceServer) GetProviderConfiguration(context.Context, *GetProviderConfigurationRequest) (*GetProviderConfigurationResponse, error) {\n \treturn nil, status.Errorf(codes.Unimplemented, \"method GetProviderConfiguration not implemented\")\n }\n@@ -79,6 +95,24 @@ func RegisterOFREPServiceServer(s grpc.ServiceRegistrar, srv OFREPServiceServer)\n \ts.RegisterService(&amp;OFREPService_ServiceDesc, srv)\n }\n \n+func _OFREPService_EvaluateFlag_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n+\tin := new(EvaluateFlagRequest)\n+\tif err := dec(in); err != nil {\n+\t\treturn nil, err\n+\t}\n+\tif interceptor == nil {\n+\t\treturn srv.(OFREPServiceServer).EvaluateFlag(ctx, in)\n+\t}\n+\tinfo := &amp;grpc.UnaryServerInfo{\n+\t\tServer:     srv,\n+\t\tFullMethod: OFREPService_EvaluateFlag_FullMethodName,\n+\t}\n+\thandler := func(ctx context.Context, req interface{}) (interface{}, error) {\n+\t\treturn srv.(OFREPServiceServer).EvaluateFlag(ctx, req.(*EvaluateFlagRequest))\n+\t}\n+\treturn interceptor(ctx, in, info, handler)\n+}\n+\n func _OFREPService_GetProviderConfiguration_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {\n \tin := new(GetProviderConfigurationRequest)\n \tif err := dec(in); err != nil {\n@@ -104,6 +138,10 @@ var OFREPService_ServiceDesc = grpc.ServiceDesc{\n \tServiceName: \"flipt.ofrep.OFREPService\",\n \tHandlerType: (*OFREPServiceServer)(nil),\n \tMethods: []grpc.MethodDesc{\n+\t\t{\n+\t\t\tMethodName: \"EvaluateFlag\",\n+\t\t\tHandler:    _OFREPService_EvaluateFlag_Handler,\n+\t\t},\n \t\t{\n \t\t\tMethodName: \"GetProviderConfiguration\",\n \t\t\tHandler:    _OFREPService_GetProviderConfiguration_Handler,\n", "creation_timestamp": "2026-07-27T00:52:05.809931Z"}