    "type": "array"
    },
    "targeting": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "A JEXL targeting expression used to filter out experiments."
    },
    "startDate": {
      "anyOf": [
        {
          "format": "date",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "Actual publish date of the experiment. Note that this value is expected to be null in Remote Settings."
    },
    "enrollmentEndDate": {
      "anyOf": [
        {
          "format": "date",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "Actual enrollment end date of the experiment. Note that this value is expected to be null in Remote Settings."
    },
    "endDate": {
      "anyOf": [
        {
          "format": "date",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "Actual end date of this experiment. Note that this field is expected to be null in Remote Settings."
    },
    "proposedDuration": {
      "description": "Duration of the experiment from the start date in days. Note that this property is only used during the analysis phase (i.e., not by the SDK).",
      "type": "integer"
    },
    "proposedEnrollment": {
      "description": "This represents the number of days that we expect to enroll new users. Note that this property is only used during the analysis phase (i.e., not by the SDK).",
      "type": "integer"
    },
    "referenceBranch": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "The slug of the reference branch (i.e., the branch we consider \"control\")."
    },
    "locales": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "description": "The list of locale codes (e.g., \"en-US\" or \"fr\") that this experiment is targeting. If null, all locales are targeted."
    },
    "localizations": {
      "anyOf": [
        {
          "$ref": "#/$defs/ExperimentLocalizations"
        },
        {
          "type": "null"
        }
      ]
    },
    "publishedDate": {
      "anyOf": [
        {
          "format": "date-time",
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "The date that this experiment was first published to Remote Settings. If null, it has not yet been published."
    },
    "branches": {
      "description": "Branch configuration for the experiment.",
      "items": {
        "$ref": "#/$defs/DesktopExperimentBranch"
      },
      "type": "array"
    },
    "isFirefoxLabsOptIn": {
      "description": "When this property is set to true, treat this experiment as aFirefox Labs experiment",
      "type": "boolean"
    },
    "firefoxLabsGroup": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "The group this should appear under in Firefox Labs"
    },
    "firefoxLabsTitle": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "The title shown in Firefox Labs (Fluent ID)"
    },
    "firefoxLabsDescription": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "description": "The description shown in Firefox Labs (Fluent ID)"
    },
    "firefoxLabsDescriptionLinks": {
      "anyOf": [
        {
          "additionalProperties": {
            "format": "uri",
            "maxLength": 2083,
            "minLength": 1,
            "type": "string"
          },
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "description": "Links that will be used with the firefoxLabsDescription Fluent ID. May be null for Firefox Labs Opt-In recipes that do not use links."
    },
    "featureValidationOptOut": {
      "description": "Opt out of feature schema validation.",
      "type": "boolean"
    },
    "requiresRestart": {
      "description": "Does the experiment require a restart to take effect? Only used by Firefox Labs Opt-Ins.",
      "type": "boolean"
    }
  },
  "required": [
    "schemaVersion",
    "slug",
    "id",
    "appName",
    "appId",
    "channel",
    "userFacingName",
    "userFacingDescription",
    "isEnrollmentPaused",
    "bucketConfig",
    "featureIds",
    "startDate",
    "endDate",
    "proposedEnrollment",
    "referenceBranch",
    "branches"
  ],
  "dependentSchemas": {
    "isFirefoxLabsOptIn": {
      "if": {
        "properties": {
          "isFirefoxLabsOptIn": {
            "const": true
          }
        }
      },
      "then": {
        "if": {
          "properties": {
            "isRollout": {
              "const": false
            }
          },
          "required": [
            "isRollout"
          ]
        },
        "required": [
          "firefoxLabsDescription",
          "firefoxLabsDescriptionLinks",
          "firefoxLabsGroup",
          "firefoxLabsTitle"
        ],
        "then": {
          "properties": {
            "branches": {
              "items": {
                "required": [
                  "firefoxLabsTitle"
                ]
              }
            }
          }
        }
      }
    }
  },
  "$defs": {
    "DesktopExperimentBranch": {
      "description": "The branch definition supported on Firefox Desktop 95+.",
      "properties": {
        "slug": {
          "description": "Identifier for the branch.",
          "type": "string"
        },
        "ratio": {
          "description": "Relative ratio of population for the branch. e.g., if branch A=1 and branch B=3, then branch A would get 25% of the population.",
          "type": "integer"
        },
        "features": {
          "description": "An array of feature configurations.",
          "items": {
            "$ref": "#/$defs/ExperimentFeatureConfig"
          },
          "type": "array"
        },
        "firefoxLabsTitle": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "description": "The branch title shown in Firefox Labs (Fluent ID)"
        }
      },
      "required": [
        "slug",
        "ratio",
        "features"
      ],
      "type": "object"
    },
    "ExperimentBucketConfig": {
      "properties": {
        "randomizationUnit": {
          "$ref": "#/$defs/RandomizationUnit"
        },
        "namespace": {
          "description": "Additional inputs to the hashing function.",
          "type": "string"
        },
        "start": {
          "description": "Index of the starting bucket of the range.",
          "type": "integer"
        },
        "count": {
          "description": "Number of buckets in the range.",
          "type": "integer"
        },
        "total": {
          "description": "The total number of buckets. You can assume this will always be 10000.",
          "type": "integer"
        }
      },
      "required": [
        "randomizationUnit",
        "namespace",
        "start",
        "count",
        "total"
      ],
      "type": "object"
    },
    "ExperimentFeatureConfig": {
      "properties": {
        "featureId": {
          "description": "The identifier for the feature flag.",
          "type": "string"
        },
        "value": {
          "description": "The values that define the feature configuration. This should be validated against a schema.",
          "type": "object"
        }
      },
      "required": [
        "featureId",
        "value"
      ],
      "type": "object"
    },
    "ExperimentLocalizations": {
      "additionalProperties": {
        "additionalProperties": {
          "type": "string"
        },
        "type": "object"
      },
      "description": "Per-locale localization substitutions. The top level key is the locale (e.g., \"en-US\" or \"fr\"). Each entry is a mapping of string IDs to their localized equivalents.",
      "type": "object"
    },
    "ExperimentOutcome": {
      "properties": {
        "slug": {
          "description": "Identifier for the outcome.",
          "type": "string"
        },
        "priority": {
          "description": "e.g., \"primary\" or \"secondary\".",
          "type": "string"
        }
      },
      "required": [
        "slug",
        "priority"
      ],
      "type": "object"
    },
    "RandomizationUnit": {
      "description": "A unique, stable identifier for the user used as an input to bucket hashing.",
      "enum": [
        "normandy_id",
        "nimbus_id",
        "user_id",
        "group_id"
      ],
      "type": "string"
    }
  }
}
PK