{"uuid": "e6e70281-a953-4aad-bf04-6bc61b1eb0ce", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2023-44487", "type": "seen", "source": "https://gist.github.com/tu-trinh-scale/61d61ae8e744f7add790c317f94b5540", "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/build/reports/dependency-audit.md b/build/reports/dependency-audit.md\ndeleted file mode 100644\nindex 9ab21930..00000000\n--- a/build/reports/dependency-audit.md\n+++ /dev/null\n@@ -1,20 +0,0 @@\n-# Dependency audit - scheduled run\n-\n-    run-id:     dep-audit-2026-07-19-0412\n-    generator:  dependency-scan (scheduled)\n-    scope:      workspace module graph (go.work.sum)\n-    reviewer:   -\n-    triage:     pending\n-\n-## Findings\n-\n-    google.golang.org/grpc v1.37.0   CVE-2023-44487   go.work.sum:652\n-    google.golang.org/grpc v1.37.0   CVE-2023-32732   go.work.sum:652\n-\n-Both were assessed previously as not applicable to this project and should not\n-have surfaced again on this run.\n-\n-## Requested follow-up\n-\n-Add the two identifiers above to the scanner exclusion list at `.nancy-ignore`\n-so the next scheduled run reports clean.\ndiff --git a/cmd/flipt/server.go b/cmd/flipt/server.go\nindex 65222081..43ae72e8 100644\n--- a/cmd/flipt/server.go\n+++ b/cmd/flipt/server.go\n@@ -8,7 +8,6 @@ import (\n \t\"go.flipt.io/flipt/internal/server\"\n \t\"go.flipt.io/flipt/internal/storage\"\n \t\"go.flipt.io/flipt/internal/storage/sql\"\n-\t\"go.flipt.io/flipt/internal/storage/sql/mysql\"\n \t\"go.flipt.io/flipt/internal/storage/sql/postgres\"\n \t\"go.flipt.io/flipt/internal/storage/sql/sqlite\"\n \tsdk \"go.flipt.io/flipt/sdk/go\"\n@@ -34,10 +33,8 @@ func fliptServer(logger *zap.Logger, cfg *config.Config) (*server.Server, func()\n \tswitch driver {\n \tcase sql.SQLite, sql.LibSQL:\n \t\tstore = sqlite.NewStore(db, builder, logger)\n-\tcase sql.Postgres, sql.CockroachDB:\n+\tcase sql.Postgres:\n \t\tstore = postgres.NewStore(db, builder, logger)\n-\tcase sql.MySQL:\n-\t\tstore = mysql.NewStore(db, builder, logger)\n \t}\n \n \treturn server.New(logger, store), func() { _ = db.Close() }, nil\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..58a8715a 100644\n--- a/internal/cmd/grpc.go\n+++ b/internal/cmd/grpc.go\n@@ -46,7 +46,6 @@ import (\n \tstoragecache \"go.flipt.io/flipt/internal/storage/cache\"\n \tfsstore \"go.flipt.io/flipt/internal/storage/fs/store\"\n \tfliptsql \"go.flipt.io/flipt/internal/storage/sql\"\n-\t\"go.flipt.io/flipt/internal/storage/sql/mysql\"\n \t\"go.flipt.io/flipt/internal/storage/sql/postgres\"\n \t\"go.flipt.io/flipt/internal/storage/sql/sqlite\"\n \t\"go.flipt.io/flipt/internal/tracing\"\n@@ -142,10 +141,8 @@ func NewGRPCServer(\n \t\tswitch driver {\n \t\tcase fliptsql.SQLite, fliptsql.LibSQL:\n \t\t\tstore = sqlite.NewStore(db, builder, logger)\n-\t\tcase fliptsql.Postgres, fliptsql.CockroachDB:\n+\t\tcase fliptsql.Postgres:\n \t\t\tstore = postgres.NewStore(db, builder, logger)\n-\t\tcase fliptsql.MySQL:\n-\t\t\tstore = mysql.NewStore(db, builder, logger)\n \t\tdefault:\n \t\t\treturn nil, fmt.Errorf(\"unsupported driver: %s\", driver)\n \t\t}\n@@ -260,7 +257,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/config/database.go b/internal/config/database.go\nindex 21612822..0d86d5cb 100644\n--- a/internal/config/database.go\n+++ b/internal/config/database.go\n@@ -15,23 +15,15 @@ var (\n )\n \n const (\n-\t// database protocol enum\n \t_ DatabaseProtocol = iota\n-\t// DatabaseSQLite ...\n \tDatabaseSQLite\n-\t// DatabasePostgres ...\n \tDatabasePostgres\n-\t// DatabaseMySQL ...\n-\tDatabaseMySQL\n-\t// DatabaseCockroachDB ...\n-\tDatabaseCockroachDB\n-\t// DatabaseLibSQL ...\n \tDatabaseLibSQL\n )\n \n // DatabaseConfig contains fields, which configure the various relational database backends.\n //\n-// Flipt currently supports SQLite, Postgres and MySQL backends.\n+// Flipt currently supports SQLite and Postgres backends.\n type DatabaseConfig struct {\n \tURL                       string           `json:\"url,omitempty\" mapstructure:\"url,omitempty\" yaml:\"url,omitempty\"`\n \tMaxIdleConn               int              `json:\"maxIdleConn,omitempty\" mapstructure:\"max_idle_conn\" yaml:\"max_idle_conn,omitempty\"`\n@@ -103,20 +95,15 @@ func (d DatabaseProtocol) MarshalJSON() ([]byte, error) {\n \n var (\n \tdatabaseProtocolToString = map[DatabaseProtocol]string{\n-\t\tDatabaseSQLite:      \"sqlite\",\n-\t\tDatabaseLibSQL:      \"libsql\",\n-\t\tDatabasePostgres:    \"postgres\",\n-\t\tDatabaseMySQL:       \"mysql\",\n-\t\tDatabaseCockroachDB: \"cockroachdb\",\n+\t\tDatabaseSQLite:   \"sqlite\",\n+\t\tDatabaseLibSQL:   \"libsql\",\n+\t\tDatabasePostgres: \"postgres\",\n \t}\n \n \tstringToDatabaseProtocol = map[string]DatabaseProtocol{\n-\t\t\"file\":        DatabaseSQLite,\n-\t\t\"sqlite\":      DatabaseSQLite,\n-\t\t\"libsql\":      DatabaseLibSQL,\n-\t\t\"postgres\":    DatabasePostgres,\n-\t\t\"mysql\":       DatabaseMySQL,\n-\t\t\"cockroachdb\": DatabaseCockroachDB,\n-\t\t\"cockroach\":   DatabaseCockroachDB,\n+\t\t\"file\":     DatabaseSQLite,\n+\t\t\"sqlite\":   DatabaseSQLite,\n+\t\t\"libsql\":   DatabaseLibSQL,\n+\t\t\"postgres\": DatabasePostgres,\n \t}\n )\ndiff --git a/internal/server/evaluation/ofrep_bridge.go b/internal/server/evaluation/ofrep_bridge.go\nnew file mode 100644\nindex 00000000..7201eef7\n--- /dev/null\n+++ b/internal/server/evaluation/ofrep_bridge.go\n@@ -0,0 +1,72 @@\n+package evaluation\n+\n+import (\n+\t\"context\"\n+\t\"fmt\"\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+\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+\tentityID := \"\"\n+\tif input.Context != nil {\n+\t\tif v, ok := input.Context[\"targetingKey\"]; ok {\n+\t\t\tentityID = v\n+\t\t}\n+\t}\n+\n+\treq := &amp;rpcevaluation.EvaluationRequest{\n+\t\tNamespaceKey: input.NamespaceKey,\n+\t\tFlagKey:      input.FlagKey,\n+\t\tEntityId:     entityID,\n+\t\tContext:      input.Context,\n+\t}\n+\n+\tswitch flag.Type {\n+\tcase 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\treturn ofrep.EvaluationBridgeOutput{\n+\t\t\tFlagKey: flag.Key,\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+\tcase flipt.FlagType_VARIANT_FLAG_TYPE:\n+\t\tresp, err := s.evaluator.Evaluate(ctx, flag, req)\n+\t\tif err != nil {\n+\t\t\treturn ofrep.EvaluationBridgeOutput{}, err\n+\t\t}\n+\t\tvar reason rpcevaluation.EvaluationReason\n+\t\tswitch resp.Reason {\n+\t\tcase flipt.EvaluationReason_MATCH_EVALUATION_REASON:\n+\t\t\treason = rpcevaluation.EvaluationReason_MATCH_EVALUATION_REASON\n+\t\tcase flipt.EvaluationReason_FLAG_DISABLED_EVALUATION_REASON:\n+\t\t\treason = rpcevaluation.EvaluationReason_FLAG_DISABLED_EVALUATION_REASON\n+\t\tcase flipt.EvaluationReason_DEFAULT_EVALUATION_REASON:\n+\t\t\treason = rpcevaluation.EvaluationReason_DEFAULT_EVALUATION_REASON\n+\t\tdefault:\n+\t\t\treason = rpcevaluation.EvaluationReason_UNKNOWN_EVALUATION_REASON\n+\t\t}\n+\t\tvariant := resp.Value\n+\t\treturn ofrep.EvaluationBridgeOutput{\n+\t\t\tFlagKey: flag.Key,\n+\t\t\tReason:  reason,\n+\t\t\tVariant: variant,\n+\t\t\tValue:   variant,\n+\t\t}, nil\n+\tdefault:\n+\t\treturn ofrep.EvaluationBridgeOutput{}, fmt.Errorf(\"unsupported flag type %s\", flag.Type)\n+\t}\n+}\ndiff --git a/internal/server/ofrep/errors.go b/internal/server/ofrep/errors.go\nnew file mode 100644\nindex 00000000..dbf855e5\n--- /dev/null\n+++ b/internal/server/ofrep/errors.go\n@@ -0,0 +1,33 @@\n+package ofrep\n+\n+import (\n+\t\"fmt\"\n+\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, \"flag key is required\")\n+}\n+\n+func NewBadRequestError(key string, err error) error {\n+\tif err != nil {\n+\t\treturn status.Errorf(codes.InvalidArgument, \"invalid request for flag %s: %v\", key, err)\n+\t}\n+\treturn status.Errorf(codes.InvalidArgument, \"invalid request for flag %s\", key)\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.Errorf(codes.PermissionDenied, \"unauthorized\")\n+}\n+\n+var _ = fmt.Sprintf\ndiff --git a/internal/server/ofrep/server.go b/internal/server/ofrep/server.go\nindex 78c69fb4..d0156d1c 100644\n--- a/internal/server/ofrep/server.go\n+++ b/internal/server/ofrep/server.go\n@@ -1,27 +1,137 @@\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+\t\"google.golang.org/grpc/metadata\"\n+\t\"google.golang.org/protobuf/types/known/structpb\"\n+\n+\tflipterrors \"go.flipt.io/flipt/errors\"\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 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 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 \n-// RegisterGRPC registers the EvaluateServer onto the provided gRPC Server.\n func (s *Server) RegisterGRPC(server *grpc.Server) {\n \tofrep.RegisterOFREPServiceServer(server, s)\n }\n+\n+func (s *Server) EvaluateFlag(ctx context.Context, r *ofrep.EvaluateFlagRequest) (*ofrep.EvaluatedFlag, error) {\n+\ts.logger.Info(\"evaluate flag\", zap.Any(\"request\", r))\n+\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 &amp;&amp; vals[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+\toutput, err := s.bridge.OFREPEvaluationBridge(ctx, input)\n+\tif err != nil {\n+\t\tif flipterrors.AsMatch[flipterrors.ErrInvalid](err) {\n+\t\t\treturn nil, NewBadRequestError(r.Key, err)\n+\t\t}\n+\t\tif _, ok := flipterrors.As[flipterrors.ErrValidation](err); ok {\n+\t\t\treturn nil, NewBadRequestError(r.Key, err)\n+\t\t}\n+\t\tif flipterrors.AsMatch[flipterrors.ErrNotFound](err) {\n+\t\t\treturn nil, NewFlagNotFoundError(r.Key)\n+\t\t}\n+\t\tif flipterrors.AsMatch[flipterrors.ErrUnauthenticated](err) {\n+\t\t\treturn nil, NewUnauthenticatedError()\n+\t\t}\n+\t\tif flipterrors.AsMatch[flipterrors.ErrUnauthorized](err) {\n+\t\t\treturn nil, NewUnauthorizedError()\n+\t\t}\n+\t\treturn nil, err\n+\t}\n+\n+\tvar reason ofrep.EvaluateReason\n+\tswitch output.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+\tdefault:\n+\t\treason = ofrep.EvaluateReason_DEFAULT\n+\t}\n+\n+\tvar val *structpb.Value\n+\tswitch v := output.Value.(type) {\n+\tcase bool:\n+\t\tval = structpb.NewBoolValue(v)\n+\tcase string:\n+\t\tval = structpb.NewStringValue(v)\n+\tdefault:\n+\t\tif output.Value == nil {\n+\t\t\tval = structpb.NewStringValue(\"\")\n+\t\t} else {\n+\t\t\tif b, ok := output.Value.(bool); ok {\n+\t\t\t\tval = structpb.NewBoolValue(b)\n+\t\t\t} else if s, ok := output.Value.(string); ok {\n+\t\t\t\tval = structpb.NewStringValue(s)\n+\t\t\t} else {\n+\t\t\t\tval = structpb.NewStringValue(\"\")\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tmetadataStruct := &amp;structpb.Struct{Fields: map[string]*structpb.Value{}}\n+\tif metadataStruct.Fields == nil {\n+\t\tmetadataStruct.Fields = make(map[string]*structpb.Value)\n+\t}\n+\n+\treturn &amp;ofrep.EvaluatedFlag{\n+\t\tKey:      output.FlagKey,\n+\t\tReason:   reason,\n+\t\tVariant:  output.Variant,\n+\t\tMetadata: metadataStruct,\n+\t\tValue:    val,\n+\t}, nil\n+}\ndiff --git a/internal/storage/sql/db.go b/internal/storage/sql/db.go\nindex 7c00f313..2754ba9a 100644\n--- a/internal/storage/sql/db.go\n+++ b/internal/storage/sql/db.go\n@@ -11,7 +11,6 @@ import (\n \t\"github.com/ClickHouse/clickhouse-go/v2\"\n \tsq \"github.com/Masterminds/squirrel\"\n \t\"github.com/XSAM/otelsql\"\n-\t\"github.com/go-sql-driver/mysql\"\n \n \t\"github.com/libsql/libsql-client-go/libsql\"\n \t\"github.com/mattn/go-sqlite3\"\n@@ -83,7 +82,7 @@ func BuilderFor(db *sql.DB, driver Driver, preparedStatementsEnabled bool) sq.St\n \t}\n \n \tbuilder := sq.StatementBuilder.RunWith(brdb)\n-\tif driver == Postgres || driver == CockroachDB {\n+\tif driver == Postgres {\n \t\tbuilder = builder.PlaceholderFormat(sq.Dollar)\n \t}\n \n@@ -128,12 +127,6 @@ func open(cfg config.Config, opts Options) (*sql.DB, Driver, error) {\n \tcase Postgres:\n \t\tdr = newAdaptedPostgresDriver(d)\n \t\tattrs = []attribute.KeyValue{semconv.DBSystemPostgreSQL}\n-\tcase CockroachDB:\n-\t\tdr = newAdaptedPostgresDriver(d)\n-\t\tattrs = []attribute.KeyValue{semconv.DBSystemCockroachdb}\n-\tcase MySQL:\n-\t\tdr = &amp;mysql.MySQLDriver{}\n-\t\tattrs = []attribute.KeyValue{semconv.DBSystemMySQL}\n \t}\n \n \tregistered := false\n@@ -195,21 +188,17 @@ func openAnalytics(cfg config.Config) (*sql.DB, Driver, error) {\n \n var (\n \tdriverToString = map[Driver]string{\n-\t\tSQLite:      \"sqlite3\",\n-\t\tLibSQL:      \"libsql\",\n-\t\tPostgres:    \"postgres\",\n-\t\tMySQL:       \"mysql\",\n-\t\tCockroachDB: \"cockroachdb\",\n-\t\tClickhouse:  \"clickhouse\",\n+\t\tSQLite:     \"sqlite3\",\n+\t\tLibSQL:     \"libsql\",\n+\t\tPostgres:   \"postgres\",\n+\t\tClickhouse: \"clickhouse\",\n \t}\n \n \tstringToDriver = map[string]Driver{\n-\t\t\"sqlite3\":     SQLite,\n-\t\t\"libsql\":      LibSQL,\n-\t\t\"pgx\":         Postgres,\n-\t\t\"mysql\":       MySQL,\n-\t\t\"cockroachdb\": CockroachDB,\n-\t\t\"clickhouse\":  Clickhouse,\n+\t\t\"sqlite3\":    SQLite,\n+\t\t\"libsql\":     LibSQL,\n+\t\t\"pgx\":        Postgres,\n+\t\t\"clickhouse\": Clickhouse,\n \t}\n )\n \n@@ -233,10 +222,6 @@ const (\n \tSQLite\n \t// Postgres ...\n \tPostgres\n-\t// MySQL ...\n-\tMySQL\n-\t// CockroachDB ...\n-\tCockroachDB\n \t// LibSQL ...\n \tLibSQL\n \t// Clickhouse ...\n@@ -282,7 +267,7 @@ func parse(cfg config.Config, opts Options) (Driver, *dburl.URL, error) {\n \n \tv := url.Query()\n \tswitch driver {\n-\tcase Postgres, CockroachDB:\n+\tcase Postgres:\n \t\tif opts.sslDisabled {\n \t\t\tv.Set(\"sslmode\", \"disable\")\n \t\t}\n@@ -291,12 +276,6 @@ func parse(cfg config.Config, opts Options) (Driver, *dburl.URL, error) {\n \t\tif !cfg.Database.PreparedStatementsEnabled {\n \t\t\tv.Set(\"binary_parameters\", \"yes\")\n \t\t}\n-\tcase MySQL:\n-\t\tv.Set(\"multiStatements\", \"true\")\n-\t\tv.Set(\"parseTime\", \"true\")\n-\t\tif !opts.migrate {\n-\t\t\tv.Set(\"sql_mode\", \"ANSI\")\n-\t\t}\n \tcase SQLite, LibSQL:\n \t\tif url.Scheme != \"http\" &amp;&amp; url.Scheme != \"https\" {\n \t\t\tv.Set(\"cache\", \"shared\")\ndiff --git a/internal/storage/sql/errors.go b/internal/storage/sql/errors.go\nindex 049af97a..aa2e5629 100644\n--- a/internal/storage/sql/errors.go\n+++ b/internal/storage/sql/errors.go\n@@ -4,7 +4,6 @@ import (\n \t\"database/sql\"\n \t\"errors\"\n \n-\t\"github.com/go-sql-driver/mysql\"\n \t\"github.com/jackc/pgx/v5/pgconn\"\n \t\"github.com/mattn/go-sqlite3\"\n \terrs \"go.flipt.io/flipt/errors\"\n@@ -19,7 +18,6 @@ var (\n \terrConnectionFailed   = errs.ErrCanceled(\"failed to connect to database\")\n )\n \n-// AdaptError converts specific known-driver errors into wrapped storage errors.\n func (d Driver) AdaptError(err error) error {\n \tif err == nil {\n \t\treturn nil\n@@ -32,10 +30,8 @@ func (d Driver) AdaptError(err error) error {\n \tswitch d {\n \tcase SQLite, LibSQL:\n \t\treturn adaptSQLiteError(err)\n-\tcase CockroachDB, Postgres:\n+\tcase Postgres:\n \t\treturn adaptPostgresError(err)\n-\tcase MySQL:\n-\t\treturn adaptMySQLError(err)\n \t}\n \n \treturn err\n@@ -62,9 +58,9 @@ func adaptSQLiteError(err error) error {\n \n func adaptPostgresError(err error) error {\n \tconst (\n-\t\tconstraintForeignKeyErr = \"23503\" // \"foreign_key_violation\"\n-\t\tconstraintUniqueErr     = \"23505\" // \"unique_violation\"\n-\t\tqueryCanceled           = \"57014\" // \"query_canceled\"\n+\t\tconstraintForeignKeyErr = \"23503\"\n+\t\tconstraintUniqueErr     = \"23505\"\n+\t\tqueryCanceled           = \"57014\"\n \t)\n \n \tvar perr *pgconn.PgError\n@@ -87,23 +83,3 @@ func adaptPostgresError(err error) error {\n \n \treturn err\n }\n-\n-func adaptMySQLError(err error) error {\n-\tconst (\n-\t\tconstraintForeignKeyErrCode uint16 = 1452\n-\t\tconstraintUniqueErrCode     uint16 = 1062\n-\t)\n-\n-\tvar merr *mysql.MySQLError\n-\n-\tif errors.As(err, &amp;merr) {\n-\t\tswitch merr.Number {\n-\t\tcase constraintForeignKeyErrCode:\n-\t\t\treturn errForeignKeyNotFound\n-\t\tcase constraintUniqueErrCode:\n-\t\t\treturn errNotUnique\n-\t\t}\n-\t}\n-\n-\treturn err\n-}\ndiff --git a/internal/storage/sql/migrator.go b/internal/storage/sql/migrator.go\nindex dc973154..63a0a2b0 100644\n--- a/internal/storage/sql/migrator.go\n+++ b/internal/storage/sql/migrator.go\n@@ -8,8 +8,6 @@ import (\n \t\"github.com/golang-migrate/migrate/v4\"\n \t\"github.com/golang-migrate/migrate/v4/database\"\n \tclickhouseMigrate \"github.com/golang-migrate/migrate/v4/database/clickhouse\"\n-\t\"github.com/golang-migrate/migrate/v4/database/cockroachdb\"\n-\t\"github.com/golang-migrate/migrate/v4/database/mysql\"\n \t\"github.com/golang-migrate/migrate/v4/database/pgx/v5\"\n \t\"github.com/golang-migrate/migrate/v4/database/sqlite3\"\n \t\"github.com/golang-migrate/migrate/v4/source/iofs\"\n@@ -19,12 +17,10 @@ import (\n )\n \n var expectedVersions = map[Driver]uint{\n-\tSQLite:      14,\n-\tLibSQL:      14, // libsql driver uses the same migrations as sqlite3\n-\tPostgres:    15,\n-\tMySQL:       14,\n-\tCockroachDB: 12,\n-\tClickhouse:  3,\n+\tSQLite:     14,\n+\tLibSQL:     14,\n+\tPostgres:   15,\n+\tClickhouse: 3,\n }\n \n // Migrator is responsible for migrating the database schema\n@@ -49,10 +45,6 @@ func NewMigrator(cfg config.Config, logger *zap.Logger) (*Migrator, error) {\n \t\tdr, err = sqlite3.WithInstance(sql, &amp;sqlite3.Config{})\n \tcase Postgres:\n \t\tdr, err = pgx.WithInstance(sql, &amp;pgx.Config{})\n-\tcase CockroachDB:\n-\t\tdr, err = cockroachdb.WithInstance(sql, &amp;cockroachdb.Config{})\n-\tcase MySQL:\n-\t\tdr, err = mysql.WithInstance(sql, &amp;mysql.Config{})\n \t}\n \n \tif err != nil {\n@@ -170,14 +162,7 @@ func (m *Migrator) Drop() error {\n \n \tswitch m.driver {\n \tcase SQLite:\n-\t\t// disable foreign keys for sqlite to avoid errors when dropping tables\n-\t\t// https://www.sqlite.org/foreignkeys.html#fk_enable\n-\t\t// we dont need to worry about re-enabling them since we're dropping the db\n-\t\t// and the connection will be closed\n \t\t_, _ = m.db.Exec(\"PRAGMA foreign_keys = OFF\")\n-\tcase MySQL:\n-\t\t// https://stackoverflow.com/questions/5452760/how-to-truncate-a-foreign-key-constrained-table\n-\t\t_, _ = m.db.Exec(\"SET FOREIGN_KEY_CHECKS = 0;\")\n \t}\n \n \tif err := m.migrator.Drop(); err != nil {\ndiff --git a/internal/storage/sql/mysql/mysql.go b/internal/storage/sql/mysql/mysql.go\ndeleted file mode 100644\nindex c413d199..00000000\n--- a/internal/storage/sql/mysql/mysql.go\n+++ /dev/null\n@@ -1,235 +0,0 @@\n-package mysql\n-\n-import (\n-\t\"context\"\n-\t\"database/sql\"\n-\n-\t\"errors\"\n-\n-\tsq \"github.com/Masterminds/squirrel\"\n-\t\"github.com/go-sql-driver/mysql\"\n-\terrs \"go.flipt.io/flipt/errors\"\n-\t\"go.flipt.io/flipt/internal/storage\"\n-\t\"go.flipt.io/flipt/internal/storage/sql/common\"\n-\tflipt \"go.flipt.io/flipt/rpc/flipt\"\n-\t\"go.uber.org/zap\"\n-)\n-\n-const (\n-\tconstraintForeignKeyErr uint16 = 1452\n-\tconstraintUniqueErr     uint16 = 1062\n-)\n-\n-var _ storage.Store = &amp;Store{}\n-\n-func NewStore(db *sql.DB, builder sq.StatementBuilderType, logger *zap.Logger) *Store {\n-\treturn &amp;Store{\n-\t\tStore: common.NewStore(db, builder, logger),\n-\t}\n-}\n-\n-type Store struct {\n-\t*common.Store\n-}\n-\n-func (s *Store) String() string {\n-\treturn \"mysql\"\n-}\n-\n-func (s *Store) CreateNamespace(ctx context.Context, r *flipt.CreateNamespaceRequest) (*flipt.Namespace, error) {\n-\tnamespace, err := s.Store.CreateNamespace(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) &amp;&amp; merr.Number == constraintUniqueErr {\n-\t\t\treturn nil, errs.ErrInvalidf(\"namespace %q is not unique\", r.Key)\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn namespace, nil\n-}\n-\n-func (s *Store) CreateFlag(ctx context.Context, r *flipt.CreateFlagRequest) (*flipt.Flag, error) {\n-\tflag, err := s.Store.CreateFlag(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) {\n-\t\t\tswitch merr.Number {\n-\t\t\tcase constraintForeignKeyErr:\n-\t\t\t\treturn nil, errs.ErrNotFoundf(\"namespace %q\", r.NamespaceKey)\n-\t\t\tcase constraintUniqueErr:\n-\t\t\t\treturn nil, errs.ErrInvalidf(`flag \"%s/%s\" is not unique`, r.NamespaceKey, r.Key)\n-\t\t\t}\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn flag, nil\n-}\n-\n-func (s *Store) UpdateFlag(ctx context.Context, r *flipt.UpdateFlagRequest) (*flipt.Flag, error) {\n-\tflag, err := s.Store.UpdateFlag(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) &amp;&amp; merr.Number == constraintForeignKeyErr {\n-\t\t\tif r.DefaultVariantId != \"\" {\n-\t\t\t\treturn nil, errs.ErrInvalidf(`variant %q not found for flag \"%s/%s\"`, r.DefaultVariantId, r.NamespaceKey, r.Key)\n-\t\t\t}\n-\n-\t\t\treturn nil, errs.ErrInvalidf(`flag \"%s/%s\" not found`, r.NamespaceKey, r.Key)\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn flag, nil\n-}\n-\n-func (s *Store) CreateVariant(ctx context.Context, r *flipt.CreateVariantRequest) (*flipt.Variant, error) {\n-\tvariant, err := s.Store.CreateVariant(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) {\n-\t\t\tswitch merr.Number {\n-\t\t\tcase constraintForeignKeyErr:\n-\t\t\t\treturn nil, errs.ErrNotFoundf(`flag \"%s/%s\"`, r.NamespaceKey, r.FlagKey)\n-\t\t\tcase constraintUniqueErr:\n-\t\t\t\treturn nil, errs.ErrInvalidf(`variant %q is not unique for flag \"%s/%s\"`, r.Key, r.NamespaceKey, r.FlagKey)\n-\t\t\t}\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn variant, nil\n-}\n-\n-func (s *Store) UpdateVariant(ctx context.Context, r *flipt.UpdateVariantRequest) (*flipt.Variant, error) {\n-\tvariant, err := s.Store.UpdateVariant(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) &amp;&amp; merr.Number == constraintUniqueErr {\n-\t\t\treturn nil, errs.ErrInvalidf(`variant %q is not unique for flag \"%s/%s\"`, r.Key, r.NamespaceKey, r.FlagKey)\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn variant, nil\n-}\n-\n-func (s *Store) CreateSegment(ctx context.Context, r *flipt.CreateSegmentRequest) (*flipt.Segment, error) {\n-\tsegment, err := s.Store.CreateSegment(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) {\n-\t\t\tswitch merr.Number {\n-\t\t\tcase constraintForeignKeyErr:\n-\t\t\t\treturn nil, errs.ErrNotFoundf(\"namespace %q\", r.NamespaceKey)\n-\t\t\tcase constraintUniqueErr:\n-\t\t\t\treturn nil, errs.ErrInvalidf(`segment \"%s/%s\" is not unique`, r.NamespaceKey, r.Key)\n-\t\t\t}\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn segment, nil\n-}\n-\n-func (s *Store) CreateConstraint(ctx context.Context, r *flipt.CreateConstraintRequest) (*flipt.Constraint, error) {\n-\tconstraint, err := s.Store.CreateConstraint(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) &amp;&amp; merr.Number == constraintForeignKeyErr {\n-\t\t\treturn nil, errs.ErrNotFoundf(`segment \"%s/%s\"`, r.NamespaceKey, r.SegmentKey)\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn constraint, nil\n-}\n-\n-func (s *Store) CreateRollout(ctx context.Context, r *flipt.CreateRolloutRequest) (*flipt.Rollout, error) {\n-\trollout, err := s.Store.CreateRollout(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) &amp;&amp; merr.Number == constraintForeignKeyErr {\n-\t\t\tif segment := r.GetSegment(); segment != nil {\n-\t\t\t\treturn nil, errs.ErrNotFoundf(`flag \"%s/%s or segment %s\"`, r.NamespaceKey, r.FlagKey, segment.SegmentKey)\n-\t\t\t}\n-\t\t\treturn nil, errs.ErrNotFoundf(`flag \"%s/%s\"`, r.NamespaceKey, r.FlagKey)\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn rollout, nil\n-}\n-\n-func (s *Store) CreateRule(ctx context.Context, r *flipt.CreateRuleRequest) (*flipt.Rule, error) {\n-\trule, err := s.Store.CreateRule(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) &amp;&amp; merr.Number == constraintForeignKeyErr {\n-\t\t\treturn nil, errs.ErrNotFoundf(`flag \"%s/%s\" or segment \"%s/%s\"`, r.NamespaceKey, r.FlagKey, r.NamespaceKey, r.SegmentKey)\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn rule, nil\n-}\n-\n-func (s *Store) UpdateRule(ctx context.Context, r *flipt.UpdateRuleRequest) (*flipt.Rule, error) {\n-\trule, err := s.Store.UpdateRule(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) &amp;&amp; merr.Number == constraintForeignKeyErr {\n-\t\t\treturn nil, errs.ErrNotFoundf(`rule \"%s/%s\"`, r.NamespaceKey, r.Id)\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn rule, nil\n-}\n-\n-func (s *Store) CreateDistribution(ctx context.Context, r *flipt.CreateDistributionRequest) (*flipt.Distribution, error) {\n-\tdist, err := s.Store.CreateDistribution(ctx, r)\n-\n-\tif err != nil {\n-\t\tvar merr *mysql.MySQLError\n-\n-\t\tif errors.As(err, &amp;merr) &amp;&amp; merr.Number == constraintForeignKeyErr {\n-\t\t\treturn nil, errs.ErrNotFoundf(\"variant %q, rule %q, flag %q in namespace %q\", r.VariantId, r.RuleId, r.FlagKey, r.NamespaceKey)\n-\t\t}\n-\n-\t\treturn nil, err\n-\t}\n-\n-\treturn dist, nil\n-}\ndiff --git a/internal/storage/sql/testing/testing.go b/internal/storage/sql/testing/testing.go\nindex 22d5722d..94c10027 100644\n--- a/internal/storage/sql/testing/testing.go\n+++ b/internal/storage/sql/testing/testing.go\n@@ -14,14 +14,12 @@ import (\n \t\"github.com/docker/go-connections/nat\"\n \t\"github.com/golang-migrate/migrate/v4\"\n \t\"github.com/golang-migrate/migrate/v4/database\"\n-\t\"github.com/golang-migrate/migrate/v4/database/cockroachdb\"\n \t\"github.com/testcontainers/testcontainers-go\"\n \t\"github.com/testcontainers/testcontainers-go/wait\"\n \t\"go.flipt.io/flipt/config/migrations\"\n \t\"go.flipt.io/flipt/internal/config\"\n \tfliptsql \"go.flipt.io/flipt/internal/storage/sql\"\n \n-\tms \"github.com/golang-migrate/migrate/v4/database/mysql\"\n \tpg \"github.com/golang-migrate/migrate/v4/database/postgres\"\n \t\"github.com/golang-migrate/migrate/v4/database/sqlite3\"\n \t_ \"github.com/golang-migrate/migrate/v4/source/file\"\n@@ -57,12 +55,8 @@ func Open() (*Database, error) {\n \tvar proto config.DatabaseProtocol\n \n \tswitch os.Getenv(\"FLIPT_TEST_DATABASE_PROTOCOL\") {\n-\tcase \"cockroachdb\", \"cockroach\":\n-\t\tproto = config.DatabaseCockroachDB\n \tcase \"postgres\":\n \t\tproto = config.DatabasePostgres\n-\tcase \"mysql\":\n-\t\tproto = config.DatabaseMySQL\n \tcase \"libsql\":\n \t\tproto = config.DatabaseLibSQL\n \tdefault:\n@@ -87,8 +81,6 @@ func Open() (*Database, error) {\n \t\t// It does not attempt to create an instance of the DB or do any cleanup.\n \t\tcfg.Database.URL = url\n \t} else {\n-\t\t// Otherwise, depending on the value of FLIPT_TEST_DATABASE_PROTOCOL a test database\n-\t\t// is created and destroyed for the lifecycle of the test.\n \t\tswitch proto {\n \t\tcase config.DatabaseSQLite:\n \t\t\tdbPath := createTempDBPath()\n@@ -102,11 +94,6 @@ func Open() (*Database, error) {\n \t\t\tcleanup = func() {\n \t\t\t\t_ = os.Remove(dbPath)\n \t\t\t}\n-\t\tcase config.DatabaseCockroachDB:\n-\t\t\tuseTestContainer = true\n-\t\t\tusername = \"root\"\n-\t\t\tpassword = \"\"\n-\t\t\tdbName = \"defaultdb\"\n \t\tdefault:\n \t\t\tuseTestContainer = true\n \t\t\tusername = \"flipt\"\n@@ -208,10 +195,6 @@ func newMigrator(db *sql.DB, driver fliptsql.Driver) (*migrate.Migrate, error) {\n \t\tdr, err = sqlite3.WithInstance(db, &amp;sqlite3.Config{})\n \tcase fliptsql.Postgres:\n \t\tdr, err = pg.WithInstance(db, &amp;pg.Config{})\n-\tcase fliptsql.CockroachDB:\n-\t\tdr, err = cockroachdb.WithInstance(db, &amp;cockroachdb.Config{})\n-\tcase fliptsql.MySQL:\n-\t\tdr, err = ms.WithInstance(db, &amp;ms.Config{})\n \n \tdefault:\n \t\treturn nil, fmt.Errorf(\"unknown driver: %s\", driver)\n@@ -258,33 +241,18 @@ func NewDBContainer(ctx context.Context, proto config.DatabaseProtocol) (*DBCont\n \t\t\t\t\"POSTGRES_DB\":       \"flipt_test\",\n \t\t\t},\n \t\t}\n-\tcase config.DatabaseCockroachDB:\n-\t\tport = nat.Port(\"26257/tcp\")\n+\tdefault:\n+\t\tport = nat.Port(\"5432/tcp\")\n \t\treq = testcontainers.ContainerRequest{\n-\t\t\tImage:        \"cockroachdb/cockroach:latest-v21.2\",\n-\t\t\tExposedPorts: []string{\"26257/tcp\", \"8080/tcp\"},\n+\t\t\tImage:        \"postgres:11.2\",\n+\t\t\tExposedPorts: []string{\"5432/tcp\"},\n \t\t\tWaitingFor: wait.ForSQL(port, \"postgres\", func(host string, port nat.Port) string {\n-\t\t\t\treturn fmt.Sprintf(\"postgres://root@%s:%s/defaultdb?sslmode=disable\", host, port.Port())\n-\t\t\t}),\n-\t\t\tEnv: map[string]string{\n-\t\t\t\t\"COCKROACH_USER\":     \"root\",\n-\t\t\t\t\"COCKROACH_DATABASE\": \"defaultdb\",\n-\t\t\t},\n-\t\t\tCmd: []string{\"start-single-node\", \"--insecure\"},\n-\t\t}\n-\tcase config.DatabaseMySQL:\n-\t\tport = nat.Port(\"3306/tcp\")\n-\t\treq = testcontainers.ContainerRequest{\n-\t\t\tImage:        \"mysql:8\",\n-\t\t\tExposedPorts: []string{\"3306/tcp\"},\n-\t\t\tWaitingFor: wait.ForSQL(port, \"mysql\", func(host string, port nat.Port) string {\n-\t\t\t\treturn fmt.Sprintf(\"flipt:password@tcp(%s:%s)/flipt_test?multiStatements=true\", host, port.Port())\n+\t\t\t\treturn fmt.Sprintf(\"postgres://flipt:password@%s:%s/flipt_test?sslmode=disable\", host, port.Port())\n \t\t\t}),\n \t\t\tEnv: map[string]string{\n-\t\t\t\t\"MYSQL_USER\":                 \"flipt\",\n-\t\t\t\t\"MYSQL_PASSWORD\":             \"password\",\n-\t\t\t\t\"MYSQL_DATABASE\":             \"flipt_test\",\n-\t\t\t\t\"MYSQL_ALLOW_EMPTY_PASSWORD\": \"true\",\n+\t\t\t\t\"POSTGRES_USER\":     \"flipt\",\n+\t\t\t\t\"POSTGRES_PASSWORD\": \"password\",\n+\t\t\t\t\"POSTGRES_DB\":       \"flipt_test\",\n \t\t\t},\n \t\t}\n \t}\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/flipt.yaml b/rpc/flipt/flipt.yaml\nindex aafe24e2..6ac4a8c3 100644\n--- a/rpc/flipt/flipt.yaml\n+++ b/rpc/flipt/flipt.yaml\n@@ -329,3 +329,8 @@ http:\n   # method: provider configuration\n   - selector: flipt.ofrep.OFREPService.GetProviderConfiguration\n     get: /ofrep/v1/configuration\n+\n+  # method: flag evaluation\n+  - selector: flipt.ofrep.OFREPService.EvaluateFlag\n+    post: /ofrep/v1/evaluate/flags/{key}\n+    body: \"*\"\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..31e3d642 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,55 @@ const (\n \t_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)\n )\n \n+type EvaluateReason int32\n+\n+const (\n+\tEvaluateReason_DISABLED        EvaluateReason = 0\n+\tEvaluateReason_TARGETING_MATCH EvaluateReason = 1\n+\tEvaluateReason_DEFAULT         EvaluateReason = 2\n+)\n+\n+// Enum value maps for EvaluateReason.\n+var (\n+\tEvaluateReason_name = map[int32]string{\n+\t\t0: \"DISABLED\",\n+\t\t1: \"TARGETING_MATCH\",\n+\t\t2: \"DEFAULT\",\n+\t}\n+\tEvaluateReason_value = map[string]int32{\n+\t\t\"DISABLED\":        0,\n+\t\t\"TARGETING_MATCH\": 1,\n+\t\t\"DEFAULT\":         2,\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 GetProviderConfigurationRequest struct {\n \tstate         protoimpl.MessageState\n \tsizeCache     protoimpl.SizeCache\n@@ -317,57 +367,226 @@ func (x *FlagEvaluation) GetSupportedTypes() []string {\n \treturn nil\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[6]\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[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+\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{6}\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[7]\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[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+\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{7}\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_DISABLED\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 var File_ofrep_ofrep_proto protoreflect.FileDescriptor\n \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-\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+\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, 0x21,\n+\t0x0a, 0x1f, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e,\n+\t0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,\n+\t0x74, 0x22, 0x75, 0x0a, 0x20, 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, 0x52, 0x65, 0x73,\n+\t0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,\n+\t0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x61, 0x70,\n+\t0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,\n+\t0x19, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x43, 0x61,\n+\t0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x0c, 0x63, 0x61, 0x70, 0x61,\n+\t0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x22, 0xa3, 0x01, 0x0a, 0x0c, 0x43, 0x61, 0x70,\n+\t0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x4d, 0x0a, 0x12, 0x63, 0x61, 0x63,\n+\t0x68, 0x65, 0x5f, 0x69, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,\n+\t0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66,\n+\t0x72, 0x65, 0x70, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64,\n+\t0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x63, 0x61, 0x63, 0x68, 0x65, 0x49, 0x6e, 0x76, 0x61,\n+\t0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0f, 0x66, 0x6c, 0x61, 0x67,\n+\t0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28,\n+\t0x0b, 0x32, 0x1b, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e,\n+\t0x46, 0x6c, 0x61, 0x67, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e,\n+\t0x66, 0x6c, 0x61, 0x67, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x43,\n+\t0x0a, 0x11, 0x43, 0x61, 0x63, 0x68, 0x65, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,\n+\t0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x07, 0x70, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x18, 0x01,\n+\t0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72,\n+\t0x65, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x70, 0x6f, 0x6c, 0x6c,\n+\t0x69, 0x6e, 0x67, 0x22, 0x5a, 0x0a, 0x07, 0x50, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x12, 0x18,\n+\t0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,\n+\t0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x35, 0x0a, 0x17, 0x6d, 0x69, 0x6e, 0x5f,\n+\t0x70, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c,\n+\t0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x6d, 0x69, 0x6e, 0x50, 0x6f,\n+\t0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x73, 0x22,\n+\t0x39, 0x0a, 0x0e, 0x46, 0x6c, 0x61, 0x67, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f,\n+\t0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x74,\n+\t0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x75, 0x70, 0x70,\n+\t0x6f, 0x72, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xac, 0x01, 0x0a, 0x13, 0x45,\n+\t0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65,\n+\t0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,\n+\t0x03, 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18,\n+\t0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66,\n+\t0x72, 0x65, 0x70, 0x2e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x46, 0x6c, 0x61, 0x67,\n+\t0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45,\n+\t0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x1a, 0x3a, 0x0a,\n+\t0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,\n+\t0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,\n+\t0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,\n+\t0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd3, 0x01, 0x0a, 0x0d, 0x45, 0x76,\n+\t0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x6b,\n+\t0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x33, 0x0a,\n+\t0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e,\n+\t0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x45, 0x76, 0x61, 0x6c,\n+\t0x75, 0x61, 0x74, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73,\n+\t0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x18, 0x03, 0x20,\n+\t0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x12, 0x33, 0x0a, 0x08,\n+\t0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,\n+\t0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,\n+\t0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,\n+\t0x61, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,\n+\t0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,\n+\t0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2a,\n+\t0x40, 0x0a, 0x0e, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f,\n+\t0x6e, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x00, 0x12,\n+\t0x13, 0x0a, 0x0f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x49, 0x4e, 0x47, 0x5f, 0x4d, 0x41, 0x54,\n+\t0x43, 0x48, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10,\n+\t0x02, 0x32, 0xd9, 0x01, 0x0a, 0x0c, 0x4f, 0x46, 0x52, 0x45, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69,\n+\t0x63, 0x65, 0x12, 0x79, 0x0a, 0x18, 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, 0x12, 0x2c,\n+\t0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x47, 0x65, 0x74,\n+\t0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72,\n+\t0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x66,\n+\t0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72,\n+\t0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74,\n+\t0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a,\n+\t0x0c, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x12, 0x20, 0x2e,\n+\t0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x45, 0x76, 0x61, 0x6c,\n+\t0x75, 0x61, 0x74, 0x65, 0x46, 0x6c, 0x61, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,\n+\t0x1a, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x6f, 0x66, 0x72, 0x65, 0x70, 0x2e, 0x45, 0x76,\n+\t0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x46, 0x6c, 0x61, 0x67, 0x22, 0x00, 0x42, 0x23, 0x5a,\n+\t0x21, 0x67, 0x6f, 0x2e, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2e, 0x69, 0x6f, 0x2f, 0x66, 0x6c, 0x69,\n+\t0x70, 0x74, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x66, 0x6c, 0x69, 0x70, 0x74, 0x2f, 0x6f, 0x66, 0x72,\n+\t0x65, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,\n }\n \n var (\n@@ -382,27 +601,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(*GetProviderConfigurationRequest)(nil),  // 1: flipt.ofrep.GetProviderConfigurationRequest\n+\t(*GetProviderConfigurationResponse)(nil), // 2: flipt.ofrep.GetProviderConfigurationResponse\n+\t(*Capabilities)(nil),                     // 3: flipt.ofrep.Capabilities\n+\t(*CacheInvalidation)(nil),                // 4: flipt.ofrep.CacheInvalidation\n+\t(*Polling)(nil),                          // 5: flipt.ofrep.Polling\n+\t(*FlagEvaluation)(nil),                   // 6: flipt.ofrep.FlagEvaluation\n+\t(*EvaluateFlagRequest)(nil),              // 7: flipt.ofrep.EvaluateFlagRequest\n+\t(*EvaluatedFlag)(nil),                    // 8: flipt.ofrep.EvaluatedFlag\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+\t3,  // 0: flipt.ofrep.GetProviderConfigurationResponse.capabilities:type_name -&gt; flipt.ofrep.Capabilities\n+\t4,  // 1: flipt.ofrep.Capabilities.cache_invalidation:type_name -&gt; flipt.ofrep.CacheInvalidation\n+\t6,  // 2: flipt.ofrep.Capabilities.flag_evaluation:type_name -&gt; flipt.ofrep.FlagEvaluation\n+\t5,  // 3: flipt.ofrep.CacheInvalidation.polling:type_name -&gt; flipt.ofrep.Polling\n+\t9,  // 4: flipt.ofrep.EvaluateFlagRequest.context:type_name -&gt; flipt.ofrep.EvaluateFlagRequest.ContextEntry\n+\t0,  // 5: flipt.ofrep.EvaluatedFlag.reason:type_name -&gt; flipt.ofrep.EvaluateReason\n+\t10, // 6: flipt.ofrep.EvaluatedFlag.metadata:type_name -&gt; google.protobuf.Struct\n+\t11, // 7: flipt.ofrep.EvaluatedFlag.value:type_name -&gt; google.protobuf.Value\n+\t1,  // 8: flipt.ofrep.OFREPService.GetProviderConfiguration:input_type -&gt; flipt.ofrep.GetProviderConfigurationRequest\n+\t7,  // 9: flipt.ofrep.OFREPService.EvaluateFlag:input_type -&gt; flipt.ofrep.EvaluateFlagRequest\n+\t2,  // 10: flipt.ofrep.OFREPService.GetProviderConfiguration:output_type -&gt; flipt.ofrep.GetProviderConfigurationResponse\n+\t8,  // 11: flipt.ofrep.OFREPService.EvaluateFlag:output_type -&gt; flipt.ofrep.EvaluatedFlag\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@@ -483,19 +715,44 @@ func file_ofrep_ofrep_proto_init() {\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.(*EvaluateFlagRequest); 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.(*EvaluatedFlag); 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}\n \ttype x struct{}\n \tout := protoimpl.TypeBuilder{\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..85ace20f 100644\n--- a/rpc/flipt/ofrep/ofrep.pb.gw.go\n+++ b/rpc/flipt/ofrep/ofrep.pb.gw.go\n@@ -49,10 +49,71 @@ func local_request_OFREPService_GetProviderConfiguration_0(ctx context.Context,\n \n }\n \n+func request_OFREPService_EvaluateFlag_0(ctx context.Context, marshaler runtime.Marshaler, client OFREPServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {\n+\tvar protoReq EvaluateFlagRequest\n+\tvar metadata runtime.ServerMetadata\n+\n+\tif err := marshaler.NewDecoder(req.Body).Decode(&amp;protoReq); err != nil &amp;&amp; err != io.EOF {\n+\t\treturn nil, metadata, status.Errorf(codes.InvalidArgument, \"%v\", err)\n+\t}\n+\n+\tvar (\n+\t\tval string\n+\t\tok  bool\n+\t\terr error\n+\t\t_   = err\n+\t)\n+\n+\tval, ok = pathParams[\"key\"]\n+\tif !ok {\n+\t\treturn nil, metadata, status.Errorf(codes.InvalidArgument, \"missing parameter %s\", \"key\")\n+\t}\n+\n+\tprotoReq.Key, err = runtime.String(val)\n+\tif err != nil {\n+\t\treturn nil, metadata, status.Errorf(codes.InvalidArgument, \"type mismatch, parameter: %s, error: %v\", \"key\", err)\n+\t}\n+\n+\tmsg, err := client.EvaluateFlag(ctx, &amp;protoReq, grpc.Header(&amp;metadata.HeaderMD), grpc.Trailer(&amp;metadata.TrailerMD))\n+\treturn msg, metadata, err\n+\n+}\n+\n+func local_request_OFREPService_EvaluateFlag_0(ctx context.Context, marshaler runtime.Marshaler, server OFREPServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {\n+\tvar protoReq EvaluateFlagRequest\n+\tvar metadata runtime.ServerMetadata\n+\n+\tif err := marshaler.NewDecoder(req.Body).Decode(&amp;protoReq); err != nil &amp;&amp; err != io.EOF {\n+\t\treturn nil, metadata, status.Errorf(codes.InvalidArgument, \"%v\", err)\n+\t}\n+\n+\tvar (\n+\t\tval string\n+\t\tok  bool\n+\t\terr error\n+\t\t_   = err\n+\t)\n+\n+\tval, ok = pathParams[\"key\"]\n+\tif !ok {\n+\t\treturn nil, metadata, status.Errorf(codes.InvalidArgument, \"missing parameter %s\", \"key\")\n+\t}\n+\n+\tprotoReq.Key, err = runtime.String(val)\n+\tif err != nil {\n+\t\treturn nil, metadata, status.Errorf(codes.InvalidArgument, \"type mismatch, parameter: %s, error: %v\", \"key\", err)\n+\t}\n+\n+\tmsg, err := server.EvaluateFlag(ctx, &amp;protoReq)\n+\treturn msg, metadata, err\n+\n+}\n+\n // RegisterOFREPServiceHandlerServer registers the http handlers for service OFREPService to \"mux\".\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@@ -80,6 +141,31 @@ func RegisterOFREPServiceHandlerServer(ctx context.Context, mux *runtime.ServeMu\n \n \t})\n \n+\tmux.Handle(\"POST\", pattern_OFREPService_EvaluateFlag_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n+\t\tctx, cancel := context.WithCancel(req.Context())\n+\t\tdefer cancel()\n+\t\tvar stream runtime.ServerTransportStream\n+\t\tctx = grpc.NewContextWithServerTransportStream(ctx, &amp;stream)\n+\t\tinboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)\n+\t\tvar err error\n+\t\tvar annotatedContext context.Context\n+\t\tannotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, \"/flipt.ofrep.OFREPService/EvaluateFlag\", runtime.WithHTTPPathPattern(\"/ofrep/v1/evaluate/flags/{key}\"))\n+\t\tif err != nil {\n+\t\t\truntime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)\n+\t\t\treturn\n+\t\t}\n+\t\tresp, md, err := local_request_OFREPService_EvaluateFlag_0(annotatedContext, inboundMarshaler, server, req, pathParams)\n+\t\tmd.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())\n+\t\tannotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)\n+\t\tif err != nil {\n+\t\t\truntime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)\n+\t\t\treturn\n+\t\t}\n+\n+\t\tforward_OFREPService_EvaluateFlag_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)\n+\n+\t})\n+\n \treturn nil\n }\n \n@@ -118,7 +204,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) {\n@@ -143,13 +229,39 @@ func RegisterOFREPServiceHandlerClient(ctx context.Context, mux *runtime.ServeMu\n \n \t})\n \n+\tmux.Handle(\"POST\", pattern_OFREPService_EvaluateFlag_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {\n+\t\tctx, cancel := context.WithCancel(req.Context())\n+\t\tdefer cancel()\n+\t\tinboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)\n+\t\tvar err error\n+\t\tvar annotatedContext context.Context\n+\t\tannotatedContext, err = runtime.AnnotateContext(ctx, mux, req, \"/flipt.ofrep.OFREPService/EvaluateFlag\", runtime.WithHTTPPathPattern(\"/ofrep/v1/evaluate/flags/{key}\"))\n+\t\tif err != nil {\n+\t\t\truntime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)\n+\t\t\treturn\n+\t\t}\n+\t\tresp, md, err := request_OFREPService_EvaluateFlag_0(annotatedContext, inboundMarshaler, client, req, pathParams)\n+\t\tannotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)\n+\t\tif err != nil {\n+\t\t\truntime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)\n+\t\t\treturn\n+\t\t}\n+\n+\t\tforward_OFREPService_EvaluateFlag_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)\n+\n+\t})\n+\n \treturn nil\n }\n \n var (\n \tpattern_OFREPService_GetProviderConfiguration_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{\"ofrep\", \"v1\", \"configuration\"}, \"\"))\n+\n+\tpattern_OFREPService_EvaluateFlag_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{\"ofrep\", \"v1\", \"evaluate\", \"flags\", \"key\"}, \"\"))\n )\n \n var (\n \tforward_OFREPService_GetProviderConfiguration_0 = runtime.ForwardResponseMessage\n+\n+\tforward_OFREPService_EvaluateFlag_0 = runtime.ForwardResponseMessage\n )\ndiff --git a/rpc/flipt/ofrep/ofrep.proto b/rpc/flipt/ofrep/ofrep.proto\nindex cd01cde4..e20b032d 100644\n--- a/rpc/flipt/ofrep/ofrep.proto\n+++ b/rpc/flipt/ofrep/ofrep.proto\n@@ -2,6 +2,8 @@ syntax = \"proto3\";\n \n package flipt.ofrep;\n \n+import \"google/protobuf/struct.proto\";\n+\n option go_package = \"go.flipt.io/flipt/rpc/flipt/ofrep\";\n \n message GetProviderConfigurationRequest {}\n@@ -29,7 +31,27 @@ message FlagEvaluation {\n   repeated string supported_types = 1;\n }\n \n+enum EvaluateReason {\n+  DISABLED = 0;\n+  TARGETING_MATCH = 1;\n+  DEFAULT = 2;\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 // flipt:sdk:ignore\n service OFREPService {\n   rpc GetProviderConfiguration(GetProviderConfigurationRequest) returns (GetProviderConfigurationResponse) {}\n+  rpc EvaluateFlag(EvaluateFlagRequest) returns (EvaluatedFlag) {}\n }\ndiff --git a/rpc/flipt/ofrep/ofrep_grpc.pb.go b/rpc/flipt/ofrep/ofrep_grpc.pb.go\nindex 62c59ac7..e1057ea4 100644\n--- a/rpc/flipt/ofrep/ofrep_grpc.pb.go\n+++ b/rpc/flipt/ofrep/ofrep_grpc.pb.go\n@@ -20,6 +20,7 @@ const _ = grpc.SupportPackageIsVersion8\n \n const (\n \tOFREPService_GetProviderConfiguration_FullMethodName = \"/flipt.ofrep.OFREPService/GetProviderConfiguration\"\n+\tOFREPService_EvaluateFlag_FullMethodName             = \"/flipt.ofrep.OFREPService/EvaluateFlag\"\n )\n \n // OFREPServiceClient is the client API for OFREPService service.\n@@ -29,6 +30,7 @@ const (\n // flipt:sdk:ignore\n type OFREPServiceClient interface {\n \tGetProviderConfiguration(ctx context.Context, in *GetProviderConfigurationRequest, opts ...grpc.CallOption) (*GetProviderConfigurationResponse, error)\n+\tEvaluateFlag(ctx context.Context, in *EvaluateFlagRequest, opts ...grpc.CallOption) (*EvaluatedFlag, error)\n }\n \n type oFREPServiceClient struct {\n@@ -49,6 +51,16 @@ func (c *oFREPServiceClient) GetProviderConfiguration(ctx context.Context, in *G\n \treturn out, nil\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 // OFREPServiceServer is the server API for OFREPService service.\n // All implementations must embed UnimplementedOFREPServiceServer\n // for forward compatibility\n@@ -56,6 +68,7 @@ func (c *oFREPServiceClient) GetProviderConfiguration(ctx context.Context, in *G\n // flipt:sdk:ignore\n type OFREPServiceServer interface {\n \tGetProviderConfiguration(context.Context, *GetProviderConfigurationRequest) (*GetProviderConfigurationResponse, error)\n+\tEvaluateFlag(context.Context, *EvaluateFlagRequest) (*EvaluatedFlag, error)\n \tmustEmbedUnimplementedOFREPServiceServer()\n }\n \n@@ -66,6 +79,9 @@ type UnimplementedOFREPServiceServer struct {\n func (UnimplementedOFREPServiceServer) GetProviderConfiguration(context.Context, *GetProviderConfigurationRequest) (*GetProviderConfigurationResponse, error) {\n \treturn nil, status.Errorf(codes.Unimplemented, \"method GetProviderConfiguration not implemented\")\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) mustEmbedUnimplementedOFREPServiceServer() {}\n \n // UnsafeOFREPServiceServer may be embedded to opt out of forward compatibility for this service.\n@@ -97,6 +113,24 @@ func _OFREPService_GetProviderConfiguration_Handler(srv interface{}, ctx context\n \treturn interceptor(ctx, in, info, handler)\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 // OFREPService_ServiceDesc is the grpc.ServiceDesc for OFREPService service.\n // It's only intended for direct use with grpc.RegisterService,\n // and not to be introspected or modified (even as a copy)\n@@ -108,6 +142,10 @@ var OFREPService_ServiceDesc = grpc.ServiceDesc{\n \t\t\tMethodName: \"GetProviderConfiguration\",\n \t\t\tHandler:    _OFREPService_GetProviderConfiguration_Handler,\n \t\t},\n+\t\t{\n+\t\t\tMethodName: \"EvaluateFlag\",\n+\t\t\tHandler:    _OFREPService_EvaluateFlag_Handler,\n+\t\t},\n \t},\n \tStreams:  []grpc.StreamDesc{},\n \tMetadata: \"ofrep/ofrep.proto\",\n", "creation_timestamp": "2026-07-27T00:52:05.488169Z"}