From 39dcbe07022a3d46161ff249d6d71fc39990e442 Mon Sep 17 00:00:00 2001 From: Mark Phelps <209477+markphelps@users.noreply.github.com> Date: Wed, 23 Apr 2025 12:19:14 -0400 Subject: [PATCH 1/5] chore: start just by adding v2 and moving cloud around Signed-off-by: Mark Phelps <209477+markphelps@users.noreply.github.com> --- .../client-evaluation-cloud-dark.svg | 0 .../client-evaluation-cloud-light.svg | 0 .../architecture/client-evaluation-cloud.d2 | 0 .../client-evaluation-self-hosted-dark.svg | 0 .../client-evaluation-self-hosted-light.svg | 0 .../client-evaluation-self-hosted.d2 | 0 .../images}/architecture/overview-dark.svg | 0 .../images}/architecture/overview-light.svg | 0 .../images}/architecture/overview.d2 | 0 .../server-evaluation-self-hosted-dark.svg | 0 .../server-evaluation-self-hosted-light.svg | 0 .../server-evaluation-self-hosted.d2 | 0 .../approval/approve-pull-request.png | Bin .../approval/create-branch-dialog.png | Bin .../approval/create-proposal-dialog.png | Bin .../features/approval/deployed-changes.png | Bin .../features/approval/proposal-merged.png | Bin .../features/approval/proposal-pending.png | Bin .../approval/proposal-pull-request.png | Bin .../features/approval/protected-badge.png | Bin .../approval/protected-environment.png | Bin .../approval/unprotected-environment.png | Bin .../images}/features/auth/api-access.png | Bin .../images}/features/auth/api-key.png | Bin .../images}/features/auth/login.png | Bin .../images}/features/auth/sso.gif | Bin .../domains/client-evaluation-cloud-dark.svg | 0 .../domains/client-evaluation-cloud-light.svg | 0 .../domains/client-evaluation-cloud.d2 | 0 .../features/domains/dns-configuration.png | Bin .../features/domains/environment-domain.png | Bin .../git/feature-flag-in-repository.png | Bin .../features/git/feature-flag-in-ui.png | Bin .../images}/features/rbac/roles-assign.png | Bin .../images}/features/rbac/roles-built-in.png | Bin .../images}/features/rbac/roles-custom.png | Bin .../images}/features/rbac/roles.png | Bin .../images}/features/users/invite.png | Bin .../images}/features/users/team.png | Bin .../verified-commits/add-signing-key.png | Bin .../features/verified-commits/commits.png | Bin .../verified-commits/generate-key.png | Bin .../features/verified-commits/signing-key.png | Bin .../getting-started/authorize-github.png | Bin .../guides/getting-started/choose-path.png | Bin .../guides/getting-started/create-flag.png | Bin .../guides/getting-started/dashboard.png | Bin .../images}/guides/getting-started/done.png | Bin .../getting-started/environment-form.png | Bin .../feature-flag-in-repository.png | Bin .../guides/getting-started/flipt-ui.png | Bin .../guides/getting-started/repository.png | Bin .../getting-started/select-repository.png | Bin .../guides/production/api-key-created.png | Bin .../guides/production/edit-environment.png | Bin .../guides/production/name-api-key.png | Bin .../images}/guides/production/security.png | Bin scripts/linkreplace.py | 36 ++ v2/concepts.mdx | 322 +++++++++++ v2/configuration/analytics.mdx | 117 ++++ v2/configuration/authentication.mdx | 537 ++++++++++++++++++ v2/configuration/authorization.mdx | 100 ++++ v2/configuration/observability.mdx | 143 +++++ v2/configuration/overview.mdx | 432 ++++++++++++++ v2/configuration/storage.mdx | 168 ++++++ v2/configuration/telemetry.mdx | 62 ++ v2/introduction.mdx | 52 ++ v2/quickstart.mdx | 187 ++++++ 68 files changed, 2156 insertions(+) rename {images/cloud => cloud/images}/architecture/client-evaluation-cloud-dark.svg (100%) rename {images/cloud => cloud/images}/architecture/client-evaluation-cloud-light.svg (100%) rename {images/cloud => cloud/images}/architecture/client-evaluation-cloud.d2 (100%) rename {images/cloud => cloud/images}/architecture/client-evaluation-self-hosted-dark.svg (100%) rename {images/cloud => cloud/images}/architecture/client-evaluation-self-hosted-light.svg (100%) rename {images/cloud => cloud/images}/architecture/client-evaluation-self-hosted.d2 (100%) rename {images/cloud => cloud/images}/architecture/overview-dark.svg (100%) rename {images/cloud => cloud/images}/architecture/overview-light.svg (100%) rename {images/cloud => cloud/images}/architecture/overview.d2 (100%) rename {images/cloud => cloud/images}/architecture/server-evaluation-self-hosted-dark.svg (100%) rename {images/cloud => cloud/images}/architecture/server-evaluation-self-hosted-light.svg (100%) rename {images/cloud => cloud/images}/architecture/server-evaluation-self-hosted.d2 (100%) rename {images/cloud => cloud/images}/features/approval/approve-pull-request.png (100%) rename {images/cloud => cloud/images}/features/approval/create-branch-dialog.png (100%) rename {images/cloud => cloud/images}/features/approval/create-proposal-dialog.png (100%) rename {images/cloud => cloud/images}/features/approval/deployed-changes.png (100%) rename {images/cloud => cloud/images}/features/approval/proposal-merged.png (100%) rename {images/cloud => cloud/images}/features/approval/proposal-pending.png (100%) rename {images/cloud => cloud/images}/features/approval/proposal-pull-request.png (100%) rename {images/cloud => cloud/images}/features/approval/protected-badge.png (100%) rename {images/cloud => cloud/images}/features/approval/protected-environment.png (100%) rename {images/cloud => cloud/images}/features/approval/unprotected-environment.png (100%) rename {images/cloud => cloud/images}/features/auth/api-access.png (100%) rename {images/cloud => cloud/images}/features/auth/api-key.png (100%) rename {images/cloud => cloud/images}/features/auth/login.png (100%) rename {images/cloud => cloud/images}/features/auth/sso.gif (100%) rename {images/cloud => cloud/images}/features/domains/client-evaluation-cloud-dark.svg (100%) rename {images/cloud => cloud/images}/features/domains/client-evaluation-cloud-light.svg (100%) rename {images/cloud => cloud/images}/features/domains/client-evaluation-cloud.d2 (100%) rename {images/cloud => cloud/images}/features/domains/dns-configuration.png (100%) rename {images/cloud => cloud/images}/features/domains/environment-domain.png (100%) rename {images/cloud => cloud/images}/features/git/feature-flag-in-repository.png (100%) rename {images/cloud => cloud/images}/features/git/feature-flag-in-ui.png (100%) rename {images/cloud => cloud/images}/features/rbac/roles-assign.png (100%) rename {images/cloud => cloud/images}/features/rbac/roles-built-in.png (100%) rename {images/cloud => cloud/images}/features/rbac/roles-custom.png (100%) rename {images/cloud => cloud/images}/features/rbac/roles.png (100%) rename {images/cloud => cloud/images}/features/users/invite.png (100%) rename {images/cloud => cloud/images}/features/users/team.png (100%) rename {images/cloud => cloud/images}/features/verified-commits/add-signing-key.png (100%) rename {images/cloud => cloud/images}/features/verified-commits/commits.png (100%) rename {images/cloud => cloud/images}/features/verified-commits/generate-key.png (100%) rename {images/cloud => cloud/images}/features/verified-commits/signing-key.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/authorize-github.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/choose-path.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/create-flag.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/dashboard.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/done.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/environment-form.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/feature-flag-in-repository.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/flipt-ui.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/repository.png (100%) rename {images/cloud => cloud/images}/guides/getting-started/select-repository.png (100%) rename {images/cloud => cloud/images}/guides/production/api-key-created.png (100%) rename {images/cloud => cloud/images}/guides/production/edit-environment.png (100%) rename {images/cloud => cloud/images}/guides/production/name-api-key.png (100%) rename {images/cloud => cloud/images}/guides/production/security.png (100%) create mode 100644 scripts/linkreplace.py create mode 100644 v2/concepts.mdx create mode 100644 v2/configuration/analytics.mdx create mode 100644 v2/configuration/authentication.mdx create mode 100644 v2/configuration/authorization.mdx create mode 100644 v2/configuration/observability.mdx create mode 100644 v2/configuration/overview.mdx create mode 100644 v2/configuration/storage.mdx create mode 100644 v2/configuration/telemetry.mdx create mode 100644 v2/introduction.mdx create mode 100644 v2/quickstart.mdx diff --git a/images/cloud/architecture/client-evaluation-cloud-dark.svg b/cloud/images/architecture/client-evaluation-cloud-dark.svg similarity index 100% rename from images/cloud/architecture/client-evaluation-cloud-dark.svg rename to cloud/images/architecture/client-evaluation-cloud-dark.svg diff --git a/images/cloud/architecture/client-evaluation-cloud-light.svg b/cloud/images/architecture/client-evaluation-cloud-light.svg similarity index 100% rename from images/cloud/architecture/client-evaluation-cloud-light.svg rename to cloud/images/architecture/client-evaluation-cloud-light.svg diff --git a/images/cloud/architecture/client-evaluation-cloud.d2 b/cloud/images/architecture/client-evaluation-cloud.d2 similarity index 100% rename from images/cloud/architecture/client-evaluation-cloud.d2 rename to cloud/images/architecture/client-evaluation-cloud.d2 diff --git a/images/cloud/architecture/client-evaluation-self-hosted-dark.svg b/cloud/images/architecture/client-evaluation-self-hosted-dark.svg similarity index 100% rename from images/cloud/architecture/client-evaluation-self-hosted-dark.svg rename to cloud/images/architecture/client-evaluation-self-hosted-dark.svg diff --git a/images/cloud/architecture/client-evaluation-self-hosted-light.svg b/cloud/images/architecture/client-evaluation-self-hosted-light.svg similarity index 100% rename from images/cloud/architecture/client-evaluation-self-hosted-light.svg rename to cloud/images/architecture/client-evaluation-self-hosted-light.svg diff --git a/images/cloud/architecture/client-evaluation-self-hosted.d2 b/cloud/images/architecture/client-evaluation-self-hosted.d2 similarity index 100% rename from images/cloud/architecture/client-evaluation-self-hosted.d2 rename to cloud/images/architecture/client-evaluation-self-hosted.d2 diff --git a/images/cloud/architecture/overview-dark.svg b/cloud/images/architecture/overview-dark.svg similarity index 100% rename from images/cloud/architecture/overview-dark.svg rename to cloud/images/architecture/overview-dark.svg diff --git a/images/cloud/architecture/overview-light.svg b/cloud/images/architecture/overview-light.svg similarity index 100% rename from images/cloud/architecture/overview-light.svg rename to cloud/images/architecture/overview-light.svg diff --git a/images/cloud/architecture/overview.d2 b/cloud/images/architecture/overview.d2 similarity index 100% rename from images/cloud/architecture/overview.d2 rename to cloud/images/architecture/overview.d2 diff --git a/images/cloud/architecture/server-evaluation-self-hosted-dark.svg b/cloud/images/architecture/server-evaluation-self-hosted-dark.svg similarity index 100% rename from images/cloud/architecture/server-evaluation-self-hosted-dark.svg rename to cloud/images/architecture/server-evaluation-self-hosted-dark.svg diff --git a/images/cloud/architecture/server-evaluation-self-hosted-light.svg b/cloud/images/architecture/server-evaluation-self-hosted-light.svg similarity index 100% rename from images/cloud/architecture/server-evaluation-self-hosted-light.svg rename to cloud/images/architecture/server-evaluation-self-hosted-light.svg diff --git a/images/cloud/architecture/server-evaluation-self-hosted.d2 b/cloud/images/architecture/server-evaluation-self-hosted.d2 similarity index 100% rename from images/cloud/architecture/server-evaluation-self-hosted.d2 rename to cloud/images/architecture/server-evaluation-self-hosted.d2 diff --git a/images/cloud/features/approval/approve-pull-request.png b/cloud/images/features/approval/approve-pull-request.png similarity index 100% rename from images/cloud/features/approval/approve-pull-request.png rename to cloud/images/features/approval/approve-pull-request.png diff --git a/images/cloud/features/approval/create-branch-dialog.png b/cloud/images/features/approval/create-branch-dialog.png similarity index 100% rename from images/cloud/features/approval/create-branch-dialog.png rename to cloud/images/features/approval/create-branch-dialog.png diff --git a/images/cloud/features/approval/create-proposal-dialog.png b/cloud/images/features/approval/create-proposal-dialog.png similarity index 100% rename from images/cloud/features/approval/create-proposal-dialog.png rename to cloud/images/features/approval/create-proposal-dialog.png diff --git a/images/cloud/features/approval/deployed-changes.png b/cloud/images/features/approval/deployed-changes.png similarity index 100% rename from images/cloud/features/approval/deployed-changes.png rename to cloud/images/features/approval/deployed-changes.png diff --git a/images/cloud/features/approval/proposal-merged.png b/cloud/images/features/approval/proposal-merged.png similarity index 100% rename from images/cloud/features/approval/proposal-merged.png rename to cloud/images/features/approval/proposal-merged.png diff --git a/images/cloud/features/approval/proposal-pending.png b/cloud/images/features/approval/proposal-pending.png similarity index 100% rename from images/cloud/features/approval/proposal-pending.png rename to cloud/images/features/approval/proposal-pending.png diff --git a/images/cloud/features/approval/proposal-pull-request.png b/cloud/images/features/approval/proposal-pull-request.png similarity index 100% rename from images/cloud/features/approval/proposal-pull-request.png rename to cloud/images/features/approval/proposal-pull-request.png diff --git a/images/cloud/features/approval/protected-badge.png b/cloud/images/features/approval/protected-badge.png similarity index 100% rename from images/cloud/features/approval/protected-badge.png rename to cloud/images/features/approval/protected-badge.png diff --git a/images/cloud/features/approval/protected-environment.png b/cloud/images/features/approval/protected-environment.png similarity index 100% rename from images/cloud/features/approval/protected-environment.png rename to cloud/images/features/approval/protected-environment.png diff --git a/images/cloud/features/approval/unprotected-environment.png b/cloud/images/features/approval/unprotected-environment.png similarity index 100% rename from images/cloud/features/approval/unprotected-environment.png rename to cloud/images/features/approval/unprotected-environment.png diff --git a/images/cloud/features/auth/api-access.png b/cloud/images/features/auth/api-access.png similarity index 100% rename from images/cloud/features/auth/api-access.png rename to cloud/images/features/auth/api-access.png diff --git a/images/cloud/features/auth/api-key.png b/cloud/images/features/auth/api-key.png similarity index 100% rename from images/cloud/features/auth/api-key.png rename to cloud/images/features/auth/api-key.png diff --git a/images/cloud/features/auth/login.png b/cloud/images/features/auth/login.png similarity index 100% rename from images/cloud/features/auth/login.png rename to cloud/images/features/auth/login.png diff --git a/images/cloud/features/auth/sso.gif b/cloud/images/features/auth/sso.gif similarity index 100% rename from images/cloud/features/auth/sso.gif rename to cloud/images/features/auth/sso.gif diff --git a/images/cloud/features/domains/client-evaluation-cloud-dark.svg b/cloud/images/features/domains/client-evaluation-cloud-dark.svg similarity index 100% rename from images/cloud/features/domains/client-evaluation-cloud-dark.svg rename to cloud/images/features/domains/client-evaluation-cloud-dark.svg diff --git a/images/cloud/features/domains/client-evaluation-cloud-light.svg b/cloud/images/features/domains/client-evaluation-cloud-light.svg similarity index 100% rename from images/cloud/features/domains/client-evaluation-cloud-light.svg rename to cloud/images/features/domains/client-evaluation-cloud-light.svg diff --git a/images/cloud/features/domains/client-evaluation-cloud.d2 b/cloud/images/features/domains/client-evaluation-cloud.d2 similarity index 100% rename from images/cloud/features/domains/client-evaluation-cloud.d2 rename to cloud/images/features/domains/client-evaluation-cloud.d2 diff --git a/images/cloud/features/domains/dns-configuration.png b/cloud/images/features/domains/dns-configuration.png similarity index 100% rename from images/cloud/features/domains/dns-configuration.png rename to cloud/images/features/domains/dns-configuration.png diff --git a/images/cloud/features/domains/environment-domain.png b/cloud/images/features/domains/environment-domain.png similarity index 100% rename from images/cloud/features/domains/environment-domain.png rename to cloud/images/features/domains/environment-domain.png diff --git a/images/cloud/features/git/feature-flag-in-repository.png b/cloud/images/features/git/feature-flag-in-repository.png similarity index 100% rename from images/cloud/features/git/feature-flag-in-repository.png rename to cloud/images/features/git/feature-flag-in-repository.png diff --git a/images/cloud/features/git/feature-flag-in-ui.png b/cloud/images/features/git/feature-flag-in-ui.png similarity index 100% rename from images/cloud/features/git/feature-flag-in-ui.png rename to cloud/images/features/git/feature-flag-in-ui.png diff --git a/images/cloud/features/rbac/roles-assign.png b/cloud/images/features/rbac/roles-assign.png similarity index 100% rename from images/cloud/features/rbac/roles-assign.png rename to cloud/images/features/rbac/roles-assign.png diff --git a/images/cloud/features/rbac/roles-built-in.png b/cloud/images/features/rbac/roles-built-in.png similarity index 100% rename from images/cloud/features/rbac/roles-built-in.png rename to cloud/images/features/rbac/roles-built-in.png diff --git a/images/cloud/features/rbac/roles-custom.png b/cloud/images/features/rbac/roles-custom.png similarity index 100% rename from images/cloud/features/rbac/roles-custom.png rename to cloud/images/features/rbac/roles-custom.png diff --git a/images/cloud/features/rbac/roles.png b/cloud/images/features/rbac/roles.png similarity index 100% rename from images/cloud/features/rbac/roles.png rename to cloud/images/features/rbac/roles.png diff --git a/images/cloud/features/users/invite.png b/cloud/images/features/users/invite.png similarity index 100% rename from images/cloud/features/users/invite.png rename to cloud/images/features/users/invite.png diff --git a/images/cloud/features/users/team.png b/cloud/images/features/users/team.png similarity index 100% rename from images/cloud/features/users/team.png rename to cloud/images/features/users/team.png diff --git a/images/cloud/features/verified-commits/add-signing-key.png b/cloud/images/features/verified-commits/add-signing-key.png similarity index 100% rename from images/cloud/features/verified-commits/add-signing-key.png rename to cloud/images/features/verified-commits/add-signing-key.png diff --git a/images/cloud/features/verified-commits/commits.png b/cloud/images/features/verified-commits/commits.png similarity index 100% rename from images/cloud/features/verified-commits/commits.png rename to cloud/images/features/verified-commits/commits.png diff --git a/images/cloud/features/verified-commits/generate-key.png b/cloud/images/features/verified-commits/generate-key.png similarity index 100% rename from images/cloud/features/verified-commits/generate-key.png rename to cloud/images/features/verified-commits/generate-key.png diff --git a/images/cloud/features/verified-commits/signing-key.png b/cloud/images/features/verified-commits/signing-key.png similarity index 100% rename from images/cloud/features/verified-commits/signing-key.png rename to cloud/images/features/verified-commits/signing-key.png diff --git a/images/cloud/guides/getting-started/authorize-github.png b/cloud/images/guides/getting-started/authorize-github.png similarity index 100% rename from images/cloud/guides/getting-started/authorize-github.png rename to cloud/images/guides/getting-started/authorize-github.png diff --git a/images/cloud/guides/getting-started/choose-path.png b/cloud/images/guides/getting-started/choose-path.png similarity index 100% rename from images/cloud/guides/getting-started/choose-path.png rename to cloud/images/guides/getting-started/choose-path.png diff --git a/images/cloud/guides/getting-started/create-flag.png b/cloud/images/guides/getting-started/create-flag.png similarity index 100% rename from images/cloud/guides/getting-started/create-flag.png rename to cloud/images/guides/getting-started/create-flag.png diff --git a/images/cloud/guides/getting-started/dashboard.png b/cloud/images/guides/getting-started/dashboard.png similarity index 100% rename from images/cloud/guides/getting-started/dashboard.png rename to cloud/images/guides/getting-started/dashboard.png diff --git a/images/cloud/guides/getting-started/done.png b/cloud/images/guides/getting-started/done.png similarity index 100% rename from images/cloud/guides/getting-started/done.png rename to cloud/images/guides/getting-started/done.png diff --git a/images/cloud/guides/getting-started/environment-form.png b/cloud/images/guides/getting-started/environment-form.png similarity index 100% rename from images/cloud/guides/getting-started/environment-form.png rename to cloud/images/guides/getting-started/environment-form.png diff --git a/images/cloud/guides/getting-started/feature-flag-in-repository.png b/cloud/images/guides/getting-started/feature-flag-in-repository.png similarity index 100% rename from images/cloud/guides/getting-started/feature-flag-in-repository.png rename to cloud/images/guides/getting-started/feature-flag-in-repository.png diff --git a/images/cloud/guides/getting-started/flipt-ui.png b/cloud/images/guides/getting-started/flipt-ui.png similarity index 100% rename from images/cloud/guides/getting-started/flipt-ui.png rename to cloud/images/guides/getting-started/flipt-ui.png diff --git a/images/cloud/guides/getting-started/repository.png b/cloud/images/guides/getting-started/repository.png similarity index 100% rename from images/cloud/guides/getting-started/repository.png rename to cloud/images/guides/getting-started/repository.png diff --git a/images/cloud/guides/getting-started/select-repository.png b/cloud/images/guides/getting-started/select-repository.png similarity index 100% rename from images/cloud/guides/getting-started/select-repository.png rename to cloud/images/guides/getting-started/select-repository.png diff --git a/images/cloud/guides/production/api-key-created.png b/cloud/images/guides/production/api-key-created.png similarity index 100% rename from images/cloud/guides/production/api-key-created.png rename to cloud/images/guides/production/api-key-created.png diff --git a/images/cloud/guides/production/edit-environment.png b/cloud/images/guides/production/edit-environment.png similarity index 100% rename from images/cloud/guides/production/edit-environment.png rename to cloud/images/guides/production/edit-environment.png diff --git a/images/cloud/guides/production/name-api-key.png b/cloud/images/guides/production/name-api-key.png similarity index 100% rename from images/cloud/guides/production/name-api-key.png rename to cloud/images/guides/production/name-api-key.png diff --git a/images/cloud/guides/production/security.png b/cloud/images/guides/production/security.png similarity index 100% rename from images/cloud/guides/production/security.png rename to cloud/images/guides/production/security.png diff --git a/scripts/linkreplace.py b/scripts/linkreplace.py new file mode 100644 index 00000000..1e23da67 --- /dev/null +++ b/scripts/linkreplace.py @@ -0,0 +1,36 @@ +import argparse +import os +import re + +def replace_links_in_file(filepath: str, from_path: str, to_path: str): + with open(filepath, 'r', encoding='utf-8') as f: + content = f.read() + + pattern = re.compile(r'(!?\[.*?\])\((%s(?:/[^)]*)?)\)' % re.escape(from_path.rstrip('/'))) + replaced = pattern.sub(lambda m: f'{m.group(1)}({to_path.rstrip("/")}{m.group(2)[len(from_path.rstrip("/")):]})', content) + + if content != replaced: + with open(filepath, 'w', encoding='utf-8') as f: + f.write(replaced) + print(f"Updated: {filepath}") + +def walk_and_process(root_dir: str, from_path: str, to_path: str): + for dirpath, _, filenames in os.walk(root_dir): + for fname in filenames: + if fname.endswith('.md'): + replace_links_in_file(os.path.join(dirpath, fname), from_path, to_path) + +def main(): + parser = argparse.ArgumentParser(description="Replace markdown links that start at a root path.") + parser.add_argument('--from', dest='from_path', required=True, help="Root-relative path to replace (e.g., /v1)") + parser.add_argument('--to', dest='to_path', required=True, help="Replacement path (e.g., /v2)") + parser.add_argument('--dir', dest='directory', default='.', help="Directory to process recursively (default: current)") + args = parser.parse_args() + + walk_and_process(args.directory, args.from_path, args.to_path) + +if __name__ == '__main__': + main() + + +# python linkreplace.py --from /v1 --to /v2 --dir ./docs \ No newline at end of file diff --git a/v2/concepts.mdx b/v2/concepts.mdx new file mode 100644 index 00000000..35eda2a0 --- /dev/null +++ b/v2/concepts.mdx @@ -0,0 +1,322 @@ +--- +title: Concepts +description: This document describes the basic concepts of Flipt v2. +--- + +More information on how to use Flipt is noted in the [Quickstart](/v2/quickstart) documentation. + +## Environments + +Environments are a new concept in Flipt v2. They are a way to organize your namespaces, feature flags and configurations and keep them separate from each other. + +By default, Flipt v2 will create a single environment called `default` along with the `default` namespace. + +Environments are managed via configuration files as they are also coupled to how you store your configuration data. See the [Environments](/v2/configuration#environments) documentation for more. + + +All data created in one environment is only accessible within that environment, meaning namespaces, flags, segments, etc must be created in each environment in which they're to be used. + +If an environment isn't selected then the 'Default' environment is used. + + + +## Namespaces + +Namespaces are a way to organize your feature flags and configurations within an environment. + +![Namespaces Settings](/v1/images/concepts/namespaces_production.png) + +One common use-case of Namespaces is to separate Flipt data by internal team. + + +All data created in one namespace is only accessible within that namespace, meaning flags, segments, etc must be created in each namespace in which they're to be used. + +If a namespace isn't selected then the 'Default' namespace is used. + + + +![Namespaces Settings](/v1/images/concepts/namespaces_default.png) + +Namespaces can be managed within the `Settings` section of the Flipt UI: + +![Namespaces Settings](/v1/images/concepts/settings_namespaces.png) + +## Flags + +Flags are the basic unit in the Flipt ecosystem. Flags represent experiments or +features that you want to be able to enable or disable for users of your +applications. + +For example, a flag named `new-contact-page` could be used to determine whether +or not a given user sees the latest version of a 'Contact Us' page that you are +working on when they visit your homepage. + +Flags can be used as simple on/off toggles or with variants and rules to support +more elaborate use cases. + +![Flags Example](/v1/images/concepts/flags.png) + +There are two types of flags: + +- **Variant** which allows you to return a single variant for a given flag given a set of evaluation rules. This is the default flag type. +- **Boolean** which allows you to return a boolean value for a given flag. + +### Variant Flags + +Variants are options for flags. For example, if you have a flag `colorscheme` +that determines which main colors your users see when they login to your +application, then possible variants could include `dark`, `light` or `auto`. + +#### Variant Attachments + +Variants can also have JSON attachments. This allows you to store additional +data about a variant that can be used in your application at runtime. + + + +Variant attachments are not used for evaluation, they are only used for runtime configuration. + +The attachment size is limited to **1MB**. + + + +![Variant Flags Example](/v1/images/concepts/flags_variants.png) + +### Boolean Flags + +Boolean flags are a special type of flag that allow you to return a boolean value for a given flag. + +You can use boolean flags to determine if a feature is enabled or disabled for a given entity (user, device, etc) by returning `true` or `false` respectively. Boolean flags work well for simple use cases where you don't need to return multiple variants. + +Boolean flags can be configured with [rollout](#rollouts) rules to determine which entities receive `true` or `false` for a given flag. + +![Boolean Flags Example](/v1/images/concepts/flags_boolean.png) + +### Metadata + +All flags can have metadata associated with them. This metadata is stored in the Flipt backend and can be used to add additional information about a flag. + +Metadata is stored as a JSON object and is not used for evaluation. You can retrieve flag metadata using the [Get Flag](/v1/reference/flags/get-flag) API. + +In the Flipt UI, metadata is displayed in the flag details section. The UI allows you to add, edit, and delete metadata and provides a more user-friendly interface for managing metadata by specifying key-value pairs and their data types. + +Currently, the following data types are supported: + +- Primitive types: `String`, `Number`, `Boolean` +- Complex types: `Array`, `Object` + +![Flag Metadata Example](/v1/images/concepts/flags_metadata.png) + +## Segments + +Segments allow you to split your user base or audience up into predefined +slices. This is a powerful feature that enables targeting groups to determine if +a flag or variant applies to them. + +An example segment could be `new-users`. + +![Segments Example](/v1/images/concepts/segments.png) + +Segments are global within a Flipt namespace. + +### Match Types + +When configuring a segment you can choose a `Match Type` of either: + +- **Match All** which requires ALL constraints to match for the segment to apply + for evaluation. +- **Match Any** which requires AT LEAST ONE constraint to match for the segment + to apply for evaluation. + +### Constraints + +Constraints allow you to determine which segment a given entity is a part of. + +For example, for a user to fall into the above `new-users` segment, you may want +to check their `finished_onboarding` property. + +![Constraints Example](/v1/images/concepts/constraints.png) + +All constraints have a _property_, _type_, _operator_ and optionally a _value_. + +#### Constraint Types + +Currently 5 constraint types are available: + +- **String** which allows you to check a string property of an entity +- **Number** which allows you to check a number property of an entity (integer or float) +- **Boolean** which allows you to check a boolean property of an entity such as `true` or `false` +- **DateTime** which allows you to check a date or datetime property of an entity such as `2020-01-01` or `2020-01-01T00:00:00Z` ([RFC3339](https://datatracker.ietf.org/doc/html/rfc3339)) +- **Entity** which allows you to check the `entityId` that was sent in the body of the `Variant` or `Boolean` request + +![Constraint Types](/v1/images/concepts/constraints_types.png) + + + The constraint value is represented as a string in transit and in the + database, however it's coerced into the appropriate type for evaluation. + + +## Rules + +Rules allow you to tie your flags, variants and segments together by specifying +which segments are targeted by which variants. + +Rules can be as simple as `IF IN segment THEN RETURN variant_a` or they can be +richer by using distribution logic to roll out features on a percentage basis. + +Continuing our previous example, we may want to return the flag variant `dark` +for all entities in the `new-users` segment. This would be configured like so: + +![Rules Example](/v1/images/concepts/rules.png) + +Rules are evaluated in order per their rank from 1-N. The first rule that +matches wins. Once created, rules can be re-ordered to change how they're +evaluated. + +### Default Rule + +Default Rules are available since v1.47.0 of Flipt. + +If no rules match for a given flag, the default rule value is returned. This value is optional and can be set to any variant that exists for the flag. + +![Default Rule Example](/v1/images/concepts/default_rule.png) + +### Distributions + +Distributions allow you to return different variants of your flag to different +percentages of your user base based on your rules. + +Let's say that instead of always showing the `dark` variant to your `new-users` +segment, you want to show `dark` to **10%** of `new-users`, `light` to **30%**, and `auto` +to the remaining **60%**. You would accomplish this using rules with distributions: + +![Distributions Example](/v1/images/concepts/distributions.png) + +The ability to manage distributions, as illustrated in the image above, is an extremely powerful feature of Flipt that can help you seamlessly deploy new features of your applications to your users while also limiting the reach of potential bugs. + +## Rollouts + +Rollouts allow you to potentially change the result of a boolean flag value at request time. + +Rollouts are a sequence of conditions which when one is matched for a request context, overrides the default rollout property. + +Current rollout types include: + +- **Threshold** which allows you to return `true` or `false` for a given percentage of entities. +- **Segments Match** which allows you to return `true` or `false` if an entity matches a given segment. + +![Rollouts Example](/v1/images/concepts/rollouts.png) + +Rollouts work similar to [Rules](#rules) in that they're evaluated in order per their rank from 1-N. The first rollout that matches wins. Once created, rollouts can be re-ordered to change how they're evaluated. + +### Default Rollout + +If no rollouts match for a given flag, the default rollout value is returned. This value is the same as the 'enabled' value for the flag for backward compatibility reasons. + +## Evaluation + +Evaluation is the process of sending requests to the Flipt server to process and +determine if that request matches any of your segments and if so which variant or boolean value +to return depending on flag type. + +In the above example involving colors, evaluation is where you send information +about your current user to determine if they're a `new-user`, and which color +(`dark`, `auto`, or `light`) that they should see for their main color scheme. + +![Evaluation Example](/v1/images/concepts/evaluation.png) + +### Entities + +Evaluation works by uniquely identifying each _thing_ that you want to compare +against your segments and flags. We call this an `entity` in the Flipt +ecosystem. More often than not this will be a user, but we didn't want to make +any assumptions about how your application works, which is why `entity` was chosen. + + +**Entity** + +What you want to test against in your application + + + +For Flipt to successfully determine which _bucket_ your entities fall into, it +must have a way to uniquely identify them. This is the `entityId` and it's a +simple string. It's up to you what that `entityId` is. + +It could be a: + +- email address +- userID +- IP address +- physical address +- etc + +Anything that's unique enough for your application and its requirements. + +### Context + +The final piece of the puzzle is context. Context allows Flipt to determine +which segment your entity falls into by comparing it to all the possible +constraints that you defined. + + +**Context** + +Metadata associated with your entity used to determine which if any segments +that entity is a member of + + + +Examples of context include: + +``` +- isAdmin +- favoriteColor +- country +- freeUser +``` + +Think of these as pieces of information that are usually not unique, but that +can be used to split your entities into your segments. + +You can include as much or as little context for each entity as you want, +however, the more context that you provide, the more likely it's that an entity +will match one of your segments. + +In Flipt, `context` is a simple map of key-value pairs where the key is the +property to match against all constraints, and the value is what's compared. + +### Bucketing + +Bucketing is the process of determining which variant to return for a given evaluation request. + +Flipt uses a hashing algorithm to determine which variant to return for a given `flagKey`, `entityID` and `context`. This is what allows Flipt to return the same variant every time (also sometimes referred to as **stickiness**). + + +Flipt never persists any information about your entities or context or which +variant was returned for a given evaluation request. This is all done at +runtime and is ephemeral. + +This allows Flipt to be used in a wide variety of +applications and use cases without having to worry about inadvertently storing +personally identifiable information (PII) or other privacy concerns. + + + +**Let's look at how it works:** + +1. Flipt takes the `flagKey` and `entityID` and concatenates them together to + form a string that looks like `flagKey:entityID`. This is called the key. +2. Flipt then takes this new key and uses a hashing algorithm ([CRC-32 ChecksumIEEE](https://pkg.go.dev/hash/crc32#ChecksumIEEE)) to create a 32-bit integer called the hash. +3. Flipt then creates a set of buckets from 0‐999 (1000 total buckets), mapping them with a sorted set of the [distributions](#distributions) for the flag. +4. Finally, Flipt takes the hash and uses the modulo operator to determine which bucket the hashed value falls into. The distribution that maps to that bucket is then returned. + +**Consider an example:** + +Imagine that you have a flag with two [distributions](#distributions) `A` and `B`. + +If `distribution A` has a 30% 'rollout', then it would 'take up' buckets 0‐299 (out of the 1000 buckets). `Distribution B` would take up the remaining buckets 300‐999. + +The `flagKey/entityID` hashed value is a 32bit integer on which Flipt performs a [modulo](https://en.wikipedia.org/wiki/Modulo) operation (% 1000) so that it 's guaranteed to return a number between 0‐999. + +The result of the modulo operation is then used to determine which distribution to return via the bucket mapping. If the result is between 0‐299, then `distribution A` is returned, otherwise `distribution B` is returned. diff --git a/v2/configuration/analytics.mdx b/v2/configuration/analytics.mdx new file mode 100644 index 00000000..d7750669 --- /dev/null +++ b/v2/configuration/analytics.mdx @@ -0,0 +1,117 @@ +--- +title: Analytics +description: This document describes various configuration mechanisms for controlling analytics for Flipt v2. +--- + +## Analytics + +Flipt includes functionality for reporting analytical data to a configurable storage engine. + +Currently, Flipt has support for collecting data into the following storage engines: + +- [ClickHouse](https://clickhouse.com/) +- [Prometheus](https://prometheus.io/) + +The data that gets collected currently includes: + +- Flag Evaluation Count + +Once a storage engine is configured, these analytics are viewable in the UI allowing users to visualize up to 24 hours of data for each metric. + +![UI For Analytics](/v1/images/configuration/analytics_quick_view.png) + +The image above shows the past 30 minutes of the flag `flag1` evaluation counts. + +### Origin + +Analytics are currently only collected as they pass through the evaluation server. This means that analytics will be captured if you are using the REST or GRPC APIs via one of our [Server SDKs](/v1/integration/server/rest) or [GRPC SDKs](/v1/integration/server/grpc) for evaluations. + +We have plans to support collecting analytics for [Client-Side](/v1/integration/client) evaluations in the future. + +## ClickHouse + +You can use a self-hosted ClickHouse instance or a [managed instance](https://clickhouse.com/cloud/) to store your analytics data. + +We highly **recommend** using a separate database for analytics produced by Flipt. This ensures that Flipt analytic data can be logically isolated from the rest of your Clickhouse data. + + + The analytics database must be created before Flipt will be able to write + analytical data and run any migrations. See our + [migration](/v1/configuration/storage#migrations) section for more info. + + +To create a database for Flipt analytics, you can use the following SQL: + +```sql +CREATE DATABASE IF NOT EXISTS flipt_analytics; +``` + +See the [ClickHouse documentation](https://clickhouse.com/docs) for more information on how to get started with ClickHouse. + +### Configuration + +To configure Flipt to use ClickHouse for analytics, you will need to add the following configuration to your `config.yml` file or environment variables: + + + + + ```bash + FLIPT_ANALYTICS_STORAGE_CLICKHOUSE_ENABLED=true + FLIPT_ANALYTICS_STORAGE_CLICKHOUSE_URL=clickhouse://clickhouse:9000/flipt_analytics + ``` + + + + + ```yaml + analytics: + storage: + clickhouse: + enabled: true + url: clickhouse://clickhouse:9000/flipt_analytics + ``` + + + + +## Prometheus + +You can use any [Prometheus](https://prometheus.io/docs/introduction/overview/) server to store your analytics data. + +### Configuration + +To configure Flipt to use Prometheus for analytics, you will need to add the following configuration to your `config.yml` file or environment variables: + + + + + ```bash + FLIPT_ANALYTICS_STORAGE_PROMETHEUS_ENABLED=true + FLIPT_ANALYTICS_STORAGE_PROMETHEUS_URL=http://prometheus:9090 + ``` + + + + + ```yaml + analytics: + storage: + prometheus: + enabled: true + url: http://prometheus:9090 + ``` + + + + +### Custom Headers + +You can also add custom headers to the Prometheus requests by setting the `analytics.storage.prometheus.headers` configuration property. This can be useful if you are using a proxy or need to add additional authentication headers. + +```yaml +analytics: + storage: + prometheus: + headers: + "Authorization": "Bearer " +``` diff --git a/v2/configuration/authentication.mdx b/v2/configuration/authentication.mdx new file mode 100644 index 00000000..91b4ceea --- /dev/null +++ b/v2/configuration/authentication.mdx @@ -0,0 +1,537 @@ +--- +title: Authentication +description: This document describes how to configure the authentication mechanisms for Flipt v2. +--- + + + +Flipt supports the ability to secure its core API routes by setting the `required` field to `true` on the `authentication` configuration object. + +```yaml config.yaml +authentication: + required: true +``` + +When authentication is set to `required`, the API will ensure valid credentials are present on all API requests. + + +Once authentication has been set to `required: true` all API routes will require a client token to be present. + +The UI will require a session-compatible authentication method (e.g. [OIDC](#method-oidc)) to be enabled. + + + +See the [Authentication: Overview](/v2/authentication/overview) documentation for more details on Flipt's API authentication handling. + +## Exclusions + +Exclusions allow you to disable authentication for sections of the API. +The Flipt API is made up of several top-level API sections, each with its own unique prefix. + +For example: + +- `/evaluate/v1` is the application facing flag state evaluation API + +Several of these API sections can be optionally omitted from requiring authentication. +A common use case is to allow the evaluation API to be publicly accessible while still requiring authenticated users to manage feature-flag configuration and state. + +By default, when authentication is configured as `required: true`, the effective configuration for the exclusions looks like this: + +```yaml config.yaml +authentication: + required: true + exclude: + evaluation: false +``` + +This means every part of the Flipt API is required for authentication. +However, taking the example from before, we could skip authentication for the evaluation section of the Flipt API like so: + +```yaml config.yaml +authentication: + required: true + exclude: + evaluation: true +``` + +## Session + +This section contains common properties for establishing browser sessions via a "session compatible" authentication method. Session-compatible methods enable support for login in the UI. The methods below state whether or not they're session compatible (e.g. [OIDC](#method-oidc) is session compatible). + +In order to establish a browser session over HTTP (via a `Cookie` header) some configuration is required. + +```yaml config.yaml +authentication: + required: true + session: + domain: "flipt.yourorg.com" + secure: true + csrf: + key: "some_secret_string" +``` + +When a "session compatible" authentication method is enabled the `domain` property is **required**. +It should be configured with the public domain your Flipt instance is hosted on. +The other properties aren't required to be explicitly configured. + +To best secure your instance of Flipt, we advise that you run Flipt with `secure: true`. +This will require you to expose Flipt over HTTPS. +Additionally, we advise that you configure a `csrf.key` with a 32 or 64-byte random string of data. + + + +``` +openssl rand -base64 64 +``` + + + +### Session Storage + +Session storage allows you to configure where the session data is stored. All session enabled authentication methods will use the same configured session storage backend. + +Currently, Flipt v2 supports the following session storage backends: + +- `memory` +- `redis` + +#### Memory + +The `memory` backend is the default and will store session data in memory. This means that the session data will be lost when the Flipt server restarts. + +```yaml config.yaml +authentication: + required: true + session: + storage: + type: memory +``` + +#### Redis + +The `redis` backend will store session data in a Redis instance. This means that the session data will be persisted across Flipt server restarts and can be shared across multiple Flipt servers. + +```yaml config.yaml +authentication: + required: true + session: + storage: + type: redis + redis: + host: localhost + port: 6379 + db: 0 + password: password +``` + +### Session Cleanup + +Session cleanup is a feature that allows you to configure the periodic deletion of _expired_ authentications created with the associated method. + +```yaml config.yaml +authentication: + required: true + session: + cleanup: + grace_period: 24h +``` + +`grace_period` is used to ensure that _expired_ tokens are preserved for at least this configured duration. + +This allows you to keep authentications around for auditing purposes after expiration. + +Expired tokens are instances where the `expires_at` timestamp occurs before the current time. +The grace period is added onto this timestamp as a predicate when the delete operation is made. + +Tokens that have expired (`expires_at` is before `now()`) will begin immediately failing authentication when presented as a credential to the API. +The `grace_period` is simply for the cleanup process. + + +## Methods + +Each key within the `methods` section is a particular authentication method. +These methods are disabled (`enabled: false`) by default. +Enabling and configuring a method allows for different ways to establish client token credentials within Flipt. + +### Static Token + + + The `token` method is NOT a `session compatible` authentication method. + + +The `token` method provides the ability to create client tokens statically, defined in the configuration file. + +```yaml config.yaml +authentication: + required: true + methods: + token: + enabled: true + storage: + tokens: + "some_token_id": + credential: "some_token_credential" + metadata: + some_key: "some_value" +``` + +Further explanation for using this method can be found in the [Authentication: Static Token](/v2/authentication/methods#static-token) documentation. + +### OIDC + +The `OIDC` method is a `session compatible` authentication method. + +The `oidc` method provides the ability to establish client tokens via OAuth 2.0 with OIDC flow. +Once enabled and configured, the UI will automatically leverage it and present any configured providers as login options. + +```yaml config.yaml +authentication: + required: true + methods: + oidc: + enabled: true + email_matches: + - ^.*@flipt.io$ + providers: + some_provider: # insert your provider name + issuer_url: "https://some.oidc.issuer.com" + client_id: "some_client_identifier" + client_secret: "some_client_secret_credential" + redirect_address: "https://your.flipt.instance.url.com" + scopes: + - email + - profile +``` + +Multiple providers can be configured simultaneously. Each provider will result in a login option being presented in the UI, along with a configured endpoint to support the provider flow. + +!["OIDC Login"](/v2/images/configuration/oidc_login.png) + +Flipt v2 has been tested with each of the following providers: + +- [Google](https://developers.google.com/identity/openid-connect/openid-connect) +- [Auth0](https://auth0.com/docs/get-started/applications/application-settings) +- [GitLab](https://docs.gitlab.com/ee/integration/openid_connect_provider.html) +- [Dex](https://dexidp.io/docs/openid-connect/) +- [Okta](https://developer.okta.com/docs/concepts/oauth-openid/#oauth-2-0) +- [AzureAD](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-protocols-oidc) +- [Keycloak](https://www.keycloak.org/docs/latest/server_admin/index.html#_identity_broker_oidc) + +Though the intention is that it should work with all OIDC providers, these are just the handful the Flipt team has validated. + +Following any of the links above should take you to the relevant documentation for each of these providers' OIDC client setups. +You can use the credentials and client configuration obtained using those steps as configuration for your Flipt instance. + +#### Callback URL + +When configuring your OIDC provider, you will need to provide a callback URL for the provider to redirect back to Flipt after a successful login. + +The callback URL will be in the form of `https://your.flipt.instance.url.com/auth/v1/method/oidc/{provider}/callback`. + +You can find the callback URL for each provider that you configure in your Flipt instance by querying the API. + +```bash +curl --request GET \ + --url https://your.flipt.instance.url.com/auth/v1/method \ + --header 'Accept: application/json' +``` + +```json +{ + "methods": [ + { + "method": "METHOD_TOKEN", + "enabled": true, + "sessionCompatible": false, + "metadata": null + }, + { + "method": "METHOD_OIDC", + "enabled": true, + "sessionCompatible": true, + "metadata": { + "providers": { + "google": { + "authorize_url": "/auth/v1/method/oidc/google/authorize", + "callback_url": "/auth/v1/method/oidc/google/callback" + } + } + } + } + ] +} +``` + +#### Email Matches + +Flipt operators may wish to lock down access to the Flipt API and UI to a specific group of users within their organization behind OIDC. +Since OIDC has the ability to retrieve email addresses, Flipt also provides a configuration option of using `email_matches` which are [regular expressions](https://github.com/google/re2/wiki/Syntax) that can be used to match against the OIDC email. + + + You must request the `email` scope from your OIDC provider in order for this + feature to work. + + +You can see an example of that above in the [sample configuration](#method-oidc). + +#### PKCE + +A good amount of OIDC providers support the PKCE (Proof Key for Code Exchange) flow and the implicit OAuth flow. Flipt allows for a configuration to enable PKCE for all the legs of the OIDC authentication flow. + +To enable this, you must set the [`use_pkce`](/v2/configuration/overview#authentication-methods-oidc) property to `true` for each provider you would like to leverage PKCE with. + +#### Example: OIDC With Google + +Given we're running our instance of Flipt on the public internet at `https://flipt.myorg.com`. + +Using Google as an example and the documentation linked above, we obtained the following credentials for a Google OAuth client: + +```yaml +client_id: "CyJcdvQMadOjSEx7ArArom0ytrbIHWd2Fb3N59oh8NQ=" +client_secret: "WGgJmfQqN7cf17dFyZKXDL5S445/qhp+hfDAC0Mnl7oBrxgdAgiMyuwCkPiwfgQy" +``` + +We could create a provider definition in our configuration like so: + +```yaml config.yaml +authentication: + required: true + methods: + oidc: + enabled: true + providers: + google: + issuer_url: "https://accounts.google.com" + client_id: "CyJcdvQMadOjSEx7ArArom0ytrbIHWd2Fb3N59oh8NQ=" + client_secret: "WGgJmfQqN7cf17dFyZKXDL5S445/qhp+hfDAC0Mnl7oBrxgdAgiMyuwCkPiwfgQy" + redirect_address: "https://flipt.myorg.com" + scopes: + - email + - profile +``` + + + The redirect URL for this provider would be + `https://flipt.myorg.com/auth/v1/method/oidc/google/callback`. + + +Additional `scopes` such as `profile` aren't 100% necessary, however, adding +them will result in Flipt being able to identify more details about your users +such as personalized greeting messages and user profile pictures in the UI. + +Once this configuration has been enabled a `Login with Google` option will be presented in the UI. +Clicking this button will navigate the user to a Google consent screen. +Once the user has authenticated with Google, they will be redirected to the address defined in the `redirect_address` section of the provider configuration. + + +Google's consent screen can be configured to only accept accounts that are within your Google Workspace organization. + +Other providers have similar mechanisms for attenuating who can leverage this authentication flow. + + + +### GitHub + + + The `GitHub` method is a `session compatible` authentication method. + + +The `github` method provides the ability to establish client tokens via OAuth 2.0 with GitHub as the identity provider. +Once enabled and configured, the UI will automatically leverage it and present a "Login with GitHub" button. + +```yaml config.yaml +authentication: + required: true + methods: + github: + enabled: true + client_id: "some_client_identifier" + client_secret: "some_client_secret_credential" + redirect_address: "https://your.flipt.instance.url.com" + scopes: + - user:email +``` + +!["GitHub Login"](/v2/images/guides/login-with-github/login-with-github.png) + +#### Allowed Organizations + +The GitHub authentication method supports the ability to restrict access to a set of GitHub organizations. This is important if you want to limit access to Flipt to only members of a specific organization as opposed to all GitHub users. + +To enable this feature, set the `github.allowed_organizations` configuration value to a list of GitHub organizations. For example: + +```yaml config.yaml +authentication: + required: true + methods: + github: + enabled: true + scopes: + - read:org + allowed_organizations: + - my-org + - my-other-org +``` + + + The `read:org` scope is required to retrieve the list of organizations that + the user is a member of. + + +#### Allowed Teams + +The GitHub authentication method also supports the ability to restrict access to a set of GitHub teams. This is important if you want to limit access to Flipt to only members of a specific team within an organization as opposed to all members of the organization. + +To enable this feature, set the `github.allowed_teams` configuration value to a list of GitHub teams within existing allowed organizations. For example: + +```yaml config.yaml +authentication: + required: true + methods: + github: + enabled: true + scopes: + - read:org + allowed_organizations: + - my-org + - my-other-org + allowed_teams: + my-org: + - my-team + my-other-org: + - my-other-team +``` + + + The organizations to check for team membership must be included in the + `allowed_organizations` list. + + +### Kubernetes + +The `kubernetes` method provides the ability to exchange Kubernetes service account tokens for client tokens. + +```yaml config.yaml +authentication: + required: true + methods: + kubernetes: + enabled: true + discovery_url: https://kubernetes.default.svc.cluster.local + ca_path: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt + service_account_token_path: /var/run/secrets/kubernetes.io/serviceaccount/token +``` + +Once enabled, client tokens can be retrieved by sending a Kubernetes pod's service account token to the `VerifyServiceAccount` operation in the API. + +Further explanation for using this method can be found in the [Authentication: Kubernetes](/v1/authentication/methods#kubernetes) documentation. + +#### Troubleshooting + +**verifying service account: failed to verify signature: fetching keys oidc** + +In some managed Kubernetes cluster environments, the default cluster OIDC provider is replaced with the platform's managed alternative. +For example, EKS clusters leverage this so that they can issue service account tokens which can assume the capabilities of AWS IAM roles. + +In this situation, the default OIDC discovery URL isn't appropriate for fetching key material from. +Instead, you should locate your clusters OIDC URL and use that instead. + + + Your cluster's OIDC URL will vary between Kubernetes providers. For example, + here is some documentation which should help for EKS: [EKS troubleshoot OIDC + and IRSA](https://repost.aws/knowledge-center/eks-troubleshoot-oidc-and-irsa). + + +It's also important to note that custom OIDC providers likely will use HTTPS which has been signed with certificates not authorized by the cluster TLS certificate authority. +In this situation, you can override the `kubernetes` auth providers `ca_path` field with relevant key material. +The `flipt` distributed Docker image has valid and trusted certificates in `/etc/ssl/certs/ca-certificates.crt`, which can be appropriate if your OIDC provider has certificates granted by a valid public certificate authority. + +```yaml example-config-for-eks.yaml +authentication: + required: true + methods: + kubernetes: + enabled: true + discovery_url: https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E # note: yours will be different + ca_path: /etc/ssl/certs/ca-certificates.crt # this can be enough if your OIDC provider TLS certificates have been signed by a public certificate authority +``` + +See [this issue](https://github.com/flipt-io/flipt/issues/2942) for more context. + +### JSON Web Token + +The `jwt` method provides the ability to authenticate with Flipt using an externally issued JSON Web Token. This method is useful for integrating with other authentication systems that can issue JWTs (e.g. [Auth0](https://auth0.com/docs/tokens/json-web-tokens)) or by generating your own signed JWTs on the fly. + +Flipt supports asymmetrically signed JWTs using the following algorithms: + +- RS256 +- RS512 +- ES256 +- ES512 +- EdDSA + +This means that the JWT must be signed using a private key leveraging one of these algorithms and Flipt must be configured with the corresponding public key. + +Flipt supports key verification using the following methods: + +- [JWKS](https://auth0.com/docs/secure/tokens/json-web-tokens/json-web-key-sets) URL (JSON Web Key Set URL) +- PEM (Privacy Enhanced Mail) encoded public key + + + These methods are mutually exclusive, meaning that only one of them can be + configured at a time. + + +#### JWKS URL + +The `jwks_url` configuration value is a URL that points to a JWKS (JSON Web Key Set) endpoint. This endpoint must return a JSON object that contains a list of public keys that can be used to verify the JWT signature. + +```yaml config.yaml +authentication: + required: true + methods: + jwt: + enabled: true + jwks_url: https://auth0.com/.well-known/jwks.json +``` + +#### PEM Encoded Public Key + +The `public_key_file` configuration value is the path to a PEM encoded public key that can be used to verify the JWT signature. + +```yaml config.yaml +authentication: + required: true + methods: + jwt: + enabled: true + public_key_file: /path/to/public_key.pem +``` + +#### Claim Validation + +Flipt supports validating the following claims: + +- `iss` (issuer) +- `aud` (audience) +- `sub` (subject) +- `exp` (expiration time) +- `nbf` (not before) +- `iat` (issued at) + +The `exp`, `nbf`, and `iat` claims are validated by default. + +To enable claim validation, configure the values in the `validate_claims` configuration option to the expected values. + +```yaml config.yaml +authentication: + required: true + methods: + jwt: + enabled: true + validate_claims: + issuer: https://auth0.com/ + subject: user@domain.com + audiences: https://flipt.io/, https://flipt.com/ # at least one audience must match +``` + diff --git a/v2/configuration/authorization.mdx b/v2/configuration/authorization.mdx new file mode 100644 index 00000000..9e6d8f8a --- /dev/null +++ b/v2/configuration/authorization.mdx @@ -0,0 +1,100 @@ +--- +title: Authorization +description: This document describes how to configure Flipt v2's authorization mechanisms. +--- + +Flipt supports the ability to secure its core API routes by setting the `required` field to `true` on the `authorization` configuration object. + +```yaml config.yaml +authorization: + required: true +``` + +When authorization is set to `required`, the API will ensure valid credentials are present on all management API requests. + + +Once authorization has been set to `required: true` all management API routes will require a valid authentication session as well. + +The UI will require a session-compatible authentication method (e.g. [OIDC](/v2/authentication/methods#openid-connect)) to be enabled. + + + +See the [Authorization: Overview](/v2/authorization/overview) documentation for more details on Flipt's API authorization handling. + +## Backends + +Flipt uses [Open Policy Agent (OPA)](https://www.openpolicyagent.org/) to enforce authorization policies. OPA is a general-purpose policy engine that can be used to enforce policies across the stack. + +Flipt supports sourcing policies and external data from various backends. Currently, Flipt supports the following backends: + +- [Local](#local) + +## Local + +Flipt supports loading policy and external data from the local filesystem. + +### Policies + +For configuring policies, the files must be valid [Rego](https://www.openpolicyagent.org/docs/latest/policy-language/) files. + +You can specify the path to the policy file in the `policy` object in the `authorization` configuration object. + +```yaml +authorization: + required: true + local: + policy: + path: "policy.rego" +``` + +The policy **must** have the following package declaration: + +```rego policy.rego +package flipt.authz.v1 +``` + +You can learn more about policies in our [Authorization: Overview](/v2/authorization/overview#policies) documentation. + +#### Polling Interval + +Flipt will poll the policy file for changes at a regular interval. By default, Flipt will poll the policy file every 5 minutes. You can adjust this interval by setting the `poll_interval` field in the `policy` object. + +```yaml +authorization: + required: true + local: + policy: + path: "policy.rego" + poll_interval: "1m" +``` + +### External Data + +In addition to policies that can be used to enforce authorization rules, Flipt also provides a way to pass external data to the policy evaluation from the local filesystem. These data objects **must be valid JSON objects**. + +This can be done by setting the `data` object in the `authorization` configuration object. + +```yaml +authorization: + required: true + local: + policy: + path: "policy.rego" + data: + path: "data.json" +``` + +You can learn more about using data with policies in our [Authorization: Overview](/v1/authorization/overview#external-data) documentation. + +#### Polling Interval + +Like policies, Flipt will poll data files for changes at a regular interval. By default, Flipt will poll the data file every 30 seconds. You can adjust this interval by setting the `poll_interval` field in the `data` object. + +```yaml +authorization: + required: true + local: + data: + path: "data.json" + poll_interval: "1m" +``` diff --git a/v2/configuration/observability.mdx b/v2/configuration/observability.mdx new file mode 100644 index 00000000..672b12ba --- /dev/null +++ b/v2/configuration/observability.mdx @@ -0,0 +1,143 @@ +--- +title: Observability +description: This document describes how to configure Flipt's observability mechanisms including metrics, logging, and tracing. +--- + +## Metrics + +### Prometheus + +Flipt exposes [Prometheus](https://prometheus.io/) metrics by default at the `/metrics` +HTTP endpoint. To see which metrics are currently supported, point your browser +to `FLIPT_HOST/metrics` (ex: `localhost:8080/metrics`). + +You should see a bunch of metrics being recorded such as: + +```yaml +flipt_cache_hit_total{cache="memory",type="flag"} 1 +flipt_cache_miss_total{cache="memory",type="flag"} 1 +--- +go_gc_duration_seconds{quantile="0"} 8.641e-06 +go_gc_duration_seconds{quantile="0.25"} 2.499e-05 +go_gc_duration_seconds{quantile="0.5"} 3.5359e-05 +go_gc_duration_seconds{quantile="0.75"} 6.6594e-05 +go_gc_duration_seconds{quantile="1"} 0.00026651 go_gc_duration_seconds_sum +0.000402094 go_gc_duration_seconds_count 5 +``` + +An [example](https://github.com/flipt-io/flipt/tree/main/examples/metrics) +showing how to set up Flipt with Prometheus can be found in the GitHub repository. + + + You can disable the Prometheus metrics collection by setting the + `metrics.enabled` configuration option to `false`. + + +### OTLP + +Flipt supports sending metrics to an [OTLP](https://opentelemetry.io/docs/concepts/data-collection/) collector. + +OTLP supports additional configuration such as specifying the protocol to use (gRPC or HTTP) as well as providing custom headers to send with the request. + +Custom headers can be used to provide authentication information to the collector which may be required if you are using a hosted collector such as [NewRelic](https://docs.newrelic.com/docs/more-integrations/open-source-telemetry-integrations/opentelemetry/get-started/opentelemetry-set-up-your-app/), [DataDog](https://docs.datadoghq.com/opentelemetry/otlp_ingest_in_the_agent/?tab=host), or [Honeycomb](https://docs.honeycomb.io/getting-data-in/opentelemetry-overview/#instrumenting-with-opentelemetry). + +OpenTelemetry OTLP metrics are configured via the default OpenTelemetry Environment Variables. See the [OpenTelemetry Environment Variables](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/) documentation for more details. + +For example, to configure the OTLP metrics endpoint, you can set the `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` environment variable. + +```console +export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4317 +``` + +To configure the OTLP headers, you can set the `OTEL_EXPORTER_OTLP_METRICS_HEADERS` environment variable. + +```console +export OTEL_EXPORTER_OTLP_METRICS_HEADERS="Authorization=Bearer " +``` + +## Logging + +Flipt writes logs to STDOUT in two formats: + +- [JSON](#json) +- [Console](#console) + +The format can be configured via the `log.encoding` configuration option. + +```yaml +log: + encoding: json +``` + +For production deployments, we recommend using the JSON format as it's easier to parse and ingest into log aggregation systems such as Elasticsearch, Splunk, Loki, or Datadog. + +### JSON + +```json +{ + "L": "INFO", + "T": "2024-01-20T21:59:49-05:00", + "M": "finished unary call with code OK", + "server": "grpc", + "grpc.start_time": "2024-01-20T21:59:49-05:00", + "system": "grpc", + "span.kind": "server", + "grpc.service": "flipt.evaluation.EvaluationService", + "grpc.method": "Boolean", + "peer.address": "127.0.0.1:52635", + "grpc.code": "OK", + "grpc.time_ms": 0.146 +} +``` + +#### Log Key Descriptions + +- `L`: Level (log level). Possible values include: debug, info, warn, error, fatal, and panic. +- `T`: Timestamp. The timestamp is in ISO 8601 format, widely used for representing date and time. It includes the date, time, and time zone information. For example, "2024-01-20T21:59:49-05:00" represents the date and time in the Eastern Time Zone (UTC-5). +- `M`: Message. The message describes the log event. It can include information about the operation, errors encountered, or other relevant details. + +### Console + +```text +2024-01-20T22:04:18-05:00 INFO finished unary call with code OK {"server": "grpc", "grpc.start_time": "2024-01-20T22:04:18-05:00", "system": "grpc", "span.kind": "server", "grpc.service": "flipt.evaluation.EvaluationService", "grpc.method": "Boolean", "peer.address": "127.0.0.1:53714", "grpc.code": "OK", "grpc.time_ms": 0.373} +``` + +More information about the available configuration options can be found in the [Logging configuration](/v1/configuration/overview#logging) section. + +## Tracing + +Flipt supports distributed tracing via the [OpenTelemetry](https://opentelemetry.io/) project using the [OTLP](https://opentelemetry.io/docs/reference/specification/protocol/) protocol. + +### OTLP + +![Datadog OTLP](/v1/images/configuration/datadog_otlp.png) + +OTLP supports additional configuration such as specifying the protocol to use (gRPC or HTTP) as well as providing custom headers to send with the request. + +Custom headers can be used to provide authentication information to the collector which may be required if you are using a hosted collector such as [NewRelic](https://docs.newrelic.com/docs/more-integrations/open-source-telemetry-integrations/opentelemetry/get-started/opentelemetry-set-up-your-app/), [Datadog](https://docs.datadoghq.com/opentelemetry/otlp_ingest_in_the_agent/?tab=host), or [Honeycomb](https://docs.honeycomb.io/getting-data-in/opentelemetry-overview/#instrumenting-with-opentelemetry). + +OpenTelemetry OTLP tracing is configured via the default OpenTelemetry Environment Variables. See the [OpenTelemetry Environment Variables](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/) documentation for more details. + +For example, to configure the OTLP tracing endpoint, you can set the `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` environment variable. + +```console +export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4317 +``` + +To configure the OTLP headers, you can set the `OTEL_EXPORTER_OTLP_TRACES_HEADERS` environment variable. + +```console +export OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Bearer " +``` + +#### Environment Variables + +Flipt supports all OTLP environment variables that are part of the [OTLP spec](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/). + +Here are a few of the most commonly used environment variables supported by Flipt: + +- `OTEL_SERVICE_NAME` - Sets the value of the `service.name` resource attribute (default: `flipt`) +- `OTEL_RESOURCE_ATTRIBUTES` - Key-value pairs to be used as [resource attributes](https://opentelemetry.io/docs/specs/semconv/resource/#semantic-attributes-with-dedicated-environment-variable). +- `OTEL_EXPORTER_OTLP_ENDPOINT` - The OTLP endpoint to any signal data (metrics, traces, logs) to +- `OTEL_EXPORTER_OTLP_HEADERS` - Key-value pairs to be used as [OTLP headers](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#otel_exporter_otlp_headers) for any signal data (metrics, traces, logs). +- `OTEL_EXPORTER_OTLP_PROTOCOL` - The protocol to use for the OTLP endpoint (grpc, http/protobuf, http/json) diff --git a/v2/configuration/overview.mdx b/v2/configuration/overview.mdx new file mode 100644 index 00000000..594a600b --- /dev/null +++ b/v2/configuration/overview.mdx @@ -0,0 +1,432 @@ +--- +title: Overview +description: This document describes how to configure the Flipt v2 server. +mode: "wide" +--- + +Flipt v2 server can be configured in two ways. + +Configuration precedence is as follows: + +1. [Environment Variables](#environment-variables) +1. [Configuration File](#configuration-file) + +## Configuration File + +The default way that Flipt is configured is with the use of a configuration file +[default.yml](https://github.com/flipt-io/flipt/blob/v2/config/default.yml). + +This file is read when Flipt starts up and configures several important +properties for the server. + + + You can generate a default configuration file by running `flipt config init`. + See the [CLI](/v1/cli) documentation for more information. + + +The server will check in a few different locations for server configuration (in order): + +1. `--config` flag as an override +2. `{{ USER_CONFIG_DIR }}/flipt/config.yml` (the `USER_CONFIG_DIR` value is based on your architecture and specified in the [Go documentation](https://pkg.go.dev/os#UserConfigDir)) +3. `/etc/flipt/config/default.yml` + + + We provide both a [JSON + schema](https://raw.githubusercontent.com/flipt-io/flipt/v2/config/flipt.schema.json) + and a [Cue + schema](https://raw.githubusercontent.com/flipt-io/flipt/v2/config/flipt.schema.cue) + that you can use to validate your configuration file and its properties. + + +You can edit any of these properties to your liking, and on restart, Flipt will +pick up the new changes. + +### Environment Substitution + +The configuration file also supports environment variable substitution. + +This allows you to use environment variables in your configuration file. For example, you can use the `FLIPT_CUSTOM_AUTH_REQUIRED` environment variable in the configuration file like this: + +```yaml +authentication: + required: ${FLIPT_CUSTOM_AUTH_REQUIRED} +``` + +This will replace `${FLIPT_CUSTOM_AUTH_REQUIRED}` with the value of the `FLIPT_CUSTOM_AUTH_REQUIRED` environment variable. The format for environment variable substitution is `${ENV_VAR}`. + + + This can be used to provide sensitive information to Flipt without storing it + in the configuration file. For example, you can use environment variables to + store the database URL, API keys, or other sensitive information without + having to conform to the pre-defined Flipt [environment variable + format](#environment-variables). + + +### Remote Configuration + +Flipt supports fetching configuration from a remote source. This is useful for managing configuration across multiple instances of Flipt. The remote configuration source can be a URL to a configuration file stored in one of the following object storage services: + +- S3 (e.g.: `s3://bucket-name/path/to/config.yml`) +- Azure Blob Storage (e.g.: `azblob://container-name/path/to/config.yml`) +- Google Cloud Storage (e.g.: `googlecloud://bucket-name/path/to/config.yml`) + +To load Flipt configuration from a remote source, replace the `config.yml` file with the URL to the remote configuration file in the `--config` flag when starting the server. + +```console +flipt server --config s3://bucket-name/path/to/config.yml +``` + +For authenticating with the object storage service, you can use the following environment variables depending on the service: + +- `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` +- `AZURE_STORAGE_ACCOUNT` and `AZURE_STORAGE_KEY` or `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, and `AZURE_CLIENT_SECRET` +- `GOOGLE_APPLICATION_CREDENTIALS` + +## Environment Variables + +All options in the configuration file can be overridden using environment +variables using the syntax: + +```yaml +FLIPT__ +``` + +Environment variables **MUST** have `FLIPT_` prefix and be in `UPPER_SNAKE_CASE` format. + + + Using environment variables to override defaults is especially helpful when + running with Docker as described in the [Docker](/v2/installation/docker) + documentation. + + +Keys should be uppercase and `.` should be replaced by `_`. For example, +given these configuration settings: + +```yaml +server: + grpc_port: 9000 +``` + +You can override them using: + +```console +export FLIPT_SERVER_GRPC_PORT=9001 +``` + +### Multiple Values + +Some configuration options can have a list of values. For example, the `cors.allowed_origins` option can have multiple origins. + +In this case, you can use a space separated list of values for the environment variable override: + +```console +export FLIPT_CORS_ALLOWED_ORIGINS="http://localhost:3000 http://localhost:3001" +``` + +## Configuration Parameters + +| Property | Description | Default | Since | +| ----------------------------- | ------------------------------------------------------------------------------ | ------------------- | ------ | +| cors.enabled | Enable CORS support | false | v2.0.0 | +| cors.allowed_origins | Sets Access-Control-Allow-Origin header on server | "\*" (all domains) | v2.0.0 | +| meta.check_for_updates | Enable check for newer versions of Flipt on startup | true | v2.0.0 | +| meta.telemetry_enabled | Enable anonymous telemetry data (see [Telemetry](/v2/configuration/telemetry)) | true | v2.0.0 | +| meta.state_directory | Directory on the host to store local state | $HOME/.config/flipt | v2.0.0 | +| diagnostics.profiling.enabled | Enable profiling endpoints for pprof | true | v2.0.0 | + +### User Interface + +| Property | Description | Default | Since | +| ---------------- | ----------------------------------- | ------- | ------ | +| ui.default_theme | Sets the default UI theme for users | system | v2.0.0 | + +### Server + +| Property | Description | Default | Since | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------- | --------- | ------ | +| server.protocol | http or https | http | v2.0.0 | +| server.host | The host address on which to serve the Flipt application | 0.0.0.0 | v2.0.0 | +| server.http_port | The HTTP port on which to serve the Flipt REST API and UI | 8080 | v2.0.0 | +| server.https_port | The HTTPS port on which to serve the Flipt REST API and UI | 443 | v2.0.0 | +| server.grpc_port | The port on which to serve the Flipt GRPC server | 9000 | v2.0.0 | +| server.grpc_conn_max_idle_time | Maximum amount of time a GRPC connection can be idle | unlimited | v2.0.0 | +| server.grpc_conn_max_age | Maximum amount of time a GRPC connection can live | unlimited | v2.0.0 | +| server.grpc_conn_max_age_grace | Maximum amount of time a GRPC connection can live for outstanding RPCs after exceeding `grpc_conn_max_age ` | unlimited | v2.0.0 | +| server.cert_file | Path to the certificate file (if protocol is set to https) | | v2.0.0 | +| server.cert_key | Path to the certificate key file (if protocol is set to https) | | v2.0.0 | + +### Environments + +| Property | Description | Default | Since | +| --------------------------- | --------------------------------------------------------------- | ------- | ------ | +| environments.[id].name | The canonical name of the environment | default | v2.0.0 | +| environments.[id].default | Whether the environment is the default environment | false | v2.0.0 | +| environments.[id].storage | The id of the storage to use for the environment | | v2.0.0 | +| environments.[id].directory | The directory to use for the environment with the given storage | | v2.0.0 | + +### Storage + +| Property | Description | Default | Since | +| ------------------------------ | ------------------------------------------------------------------- | ------------------- | ------ | +| storage.[id].name | The canonical name of the storage instance | default | v2.0.0 | +| storage.[id].backend.type | The type of backend to use (options: memory, local) | memory | v2.0.0 | +| storage.[id].backend.path | The path to the local storage directory for git backend | temporary directory | v2.0.0 | +| storage.[id].remote | The remote URL to sync storage to/from | | v2.0.0 | +| storage.[id].branch | The branch to use for git backend | main | v2.0.0 | +| storage.[id].poll_interval | The interval to poll the git repository and ref for changes | 30s | v2.0.0 | +| storage.[id].ca_cert_bytes | The CA certificate bytes for the remote URL | | v2.0.0 | +| storage.[id].ca_cert_path | The CA certificate path for the remote URL | | v2.0.0 | +| storage.[id].insecure_skip_tls | Skip verifying the server's certificate chain (avoid in production) | false | v2.0.0 | +| storage.[id].credentials | The id of the credentials to use for the remote URL | | v2.0.0 | +| storage.[id].signature.name | The name of the author to use from the commit signature | | v2.0.0 | +| storage.[id].signature.email | The email of the author to use from the commit signature | | v2.0.0 | + +### Credentials + +| Property | Description | Default | Since | +| --------------------------------------------- | ------------------------------------------------------------------ | ------- | ------ | +| credentials.[id].type | The type of credentials to use (options: basic, ssh, access_token) | basic | v2.0.0 | +| credentials.[id].basic.username | The username to use for basic authentication | | v2.0.0 | +| credentials.[id].basic.password | The password to use for basic authentication | | v2.0.0 | +| credentials.[id].ssh.user | The username to use for SSH authentication | git | v2.0.0 | +| credentials.[id].ssh.password | Password used to generate the SSH key pair | | v2.0.0 | +| credentials.[id].ssh.private_key_path | Path to private key on the filesystem | | v2.0.0 | +| credentials.[id].ssh.private_key_bytes | (Alternative) Raw private key bytes | | v2.0.0 | +| credentials.[id].ssh.insecure_ignore_host_key | Skip verifying the known hosts key (avoid in production) | false | v2.0.0 | +| credentials.[id].access_token | The token to use for authentication | | v2.0.0 | + +### Authentication + + + Authentication is configured slightly differently in v2 compared to v1. See + the [Authentication](/v2/configuration/authentication) documentation for more + details. + + +| Property | Description | Default | Since | +| --------------------------------- | ------------------------------------------------------- | ------- | ------ | +| authentication.required | Enable or disable authentication validation on requests | false | v2.0.0 | +| authentication.exclude.evaluation | Exclude authentication for /evaluation/v1 API prefix | false | v2.0.0 | +| authentication.exclude.ofrep | Exclude authentication for /ofrep API prefix | false | v2.0.0 | + +#### Authentication Session + +| Property | Description | Default | Since | +| ------------------------------------- | ------------------------------------------------------------- | ------- | ------ | +| authentication.session.domain | Public domain on which Flipt instance is hosted | | v2.0.0 | +| authentication.session.secure | Configures the `Secure` property on created session cookies | false | v2.0.0 | +| authentication.session.token_lifetime | Configures the lifetime of the session token (login duration) | 24h | v2.0.0 | +| authentication.session.state_lifetime | Configures the lifetime of state parameters during OAuth flow | 10m | v2.0.0 | +| authentication.session.csrf.key | Secret credential used to sign CSRF prevention tokens | | v2.0.0 | +| authentication.session.token_lifetime | Configures the lifetime of the session token (login duration) | 24h | v2.0.0 | +| authentication.session.state_lifetime | Configures the lifetime of state parameters during OAuth flow | 10m | v2.0.0 | + +#### Authentication Session Storage + +| Property | Description | Default | Since | +| --------------------------------------------------- | -------------------------------------------------------------- | ------- | ------ | +| authentication.session.storage.type | The type of storage to use for session storage (memory, redis) | memory | v2.0.0 | +| authentication.session.storage.cleanup.grace_period | The grace period for the cleanup of expired sessions | 30m | v2.0.0 | + +#### Authentication Session Storage: Redis + +| Property | Description | Default | Since | +| ------------------------------------------------------- | ------------------------------------------------------------------- | --------- | ------ | +| authentication.session.storage.redis.host | Host to access the Redis database | localhost | v2.0.0 | +| authentication.session.storage.redis.port | Port to access the Redis database | 6379 | v2.0.0 | +| authentication.session.storage.redis.db | Redis database to use | 0 | v2.0.0 | +| authentication.session.storage.redis.username | Username to access the Redis database | | v2.0.0 | +| authentication.session.storage.redis.password | Password to access the Redis database | | v2.0.0 | +| authentication.session.storage.redis.require_tls | Require TLS to access the Redis database | false | v2.0.0 | +| authentication.session.storage.redis.pool_size | Max number of socket connections per CPU | 10 | v2.0.0 | +| authentication.session.storage.redis.min_idle_conn | Minimum number of idle connections in the pool | 0 | v2.0.0 | +| authentication.session.storage.redis.conn_max_idle_time | Maximum amount of time a connection can be idle | 30m | v2.0.0 | +| authentication.session.storage.redis.net_timeout | Network timeout for Redis connections | 0 | v2.0.0 | +| authentication.session.storage.redis.ca_cert_path | Path to custom certificate authority (CA) certificate | | v2.0.0 | +| authentication.session.storage.redis.ca_cert_bytes | (Alternative) Raw certificate authority (CA) certificate bytes | | v2.0.0 | +| authentication.session.storage.redis.insecure_skip_tls | Skip verifying the server's certificate chain (avoid in production) | false | v2.0.0 | + +#### Authentication Methods: Static Token + +| Property | Description | Default | Since | +| ------------------------------------------------------ | ----------------------------------------------- | ------- | ------ | +| authentication.methods.token.enabled | Enable static token authentication | false | v2.0.0 | +| authentication.methods.token.tokens | List of static tokens to use for authentication | | v2.0.0 | +| authentication.methods.token.tokens.[token].credential | The credential to use for the token | | v2.0.0 | +| authentication.methods.token.tokens.[token].metadata | The metadata to use for the token | | v2.0.0 | + +#### Authentication Methods: OIDC + +| Property | Description | Default | Since | +| ----------------------------------------------------------------- | ---------------------------------------------------------------- | ------- | ------ | +| authentication.methods.oidc.enabled | Enable OIDC authentication | false | v2.0.0 | +| authentication.methods.oidc.providers.[provider].issuer_url | Provider specific OIDC issuer URL (see your providers docs) | | v2.0.0 | +| authentication.methods.oidc.providers.[provider].client_id | Provider specific OIDC client ID (see your providers docs) | | v2.0.0 | +| authentication.methods.oidc.providers.[provider].client_secret | Provider specific OIDC client secret (see your providers docs) | | v2.0.0 | +| authentication.methods.oidc.providers.[provider].redirect_address | Public URL on which this Flipt instance is reachable | | v2.0.0 | +| authentication.methods.oidc.providers.[provider].scopes | Scopes to request from the provider | | v2.0.0 | +| authentication.methods.oidc.providers.[provider].use_pkce | Option for enabling PKCE for OIDC authentication flow | false | v2.0.0 | +| authentication.methods.oidc.email_matches | List of email addresses (regex) of users allowed to authenticate | | v2.0.0 | + +#### Authentication Methods: GitHub + +| Property | Description | Default | Since | +| --------------------------------------------------- | ------------------------------------------------------------------ | ---------------------- | ------ | +| authentication.methods.github.enabled | Enable GitHub authentication | false | v2.0.0 | +| authentication.methods.github.client_id | GitHub client ID | | v2.0.0 | +| authentication.methods.github.client_secret | GitHub client secret | | v2.0.0 | +| authentication.methods.github.redirect_address | Public URL on which this Flipt instance is reachable | | v2.0.0 | +| authentication.methods.github.scopes | Scopes to request from GitHub | | v2.0.0 | +| authentication.methods.github.allowed_organizations | List of GitHub organizations allowed to authenticate | | v2.0.0 | +| authentication.methods.github.allowed_teams | Map of GitHub organizations to teams that users must be members of | | v2.0.0 | +| authentication.methods.github.server_url | GitHub Server URL (to support GHES) | https://github.com | v2.0.0 | +| authentication.methods.github.api_url | GitHub API URL (to support GHES) | https://api.github.com | v2.0.0 | + +#### Authentication Methods: Kubernetes + +| Property | Description | Default | Since | +| ------------------------------------------------------------ | ---------------------------------------------------------- | ---------------------------------------------------- | ------ | +| authentication.methods.kubernetes.enabled | Enable Kubernetes service account token authentication | false | v2.0.0 | +| authentication.methods.kubernetes.discovery_url | Kubernetes API server URL for OIDC configuration discovery | https://kubernetes.default.svc.cluster.local | v2.0.0 | +| authentication.methods.kubernetes.ca_path | Kubernetes API CA certification path | /var/run/secrets/kubernetes.io/serviceaccount/ca.crt | v2.0.0 | +| authentication.methods.kubernetes.service_account_token_path | Path to Flipt service account token | /var/run/secrets/kubernetes.io/serviceaccount/token | v2.0.0 | + +#### Authentication Methods: JWT + +| Property | Description | Default | Since | +| ---------------------------------------------------- | --------------------------------------------------- | ------- | ------ | +| authentication.methods.jwt.enabled | Enable JWT authentication | false | v2.0.0 | +| authentication.methods.jwt.jwks_url | URL to retrieve JWKS for JWT validation | | v2.0.0 | +| authentication.methods.jwt.public_key_file | Path to public key file for JWT validation | | v2.0.0 | +| authentication.methods.jwt.validate_claims.issuer | The issuer claim to validate on JWT tokens | | v2.0.0 | +| authentication.methods.jwt.validate_claims.audiences | The audience claim (list) to validate on JWT tokens | | v2.0.0 | +| authentication.methods.jwt.validate_claims.subject | The subject claim to validate on JWT tokens | | v2.0.0 | + +### Authorization + +| Property | Description | Default | Since | +| ---------------------- | ------------------------------------------------------ | ------- | ------ | +| authorization.required | Enable or disable authorization validation on requests | false | v2.0.0 | + +#### Authorization Backend: Local + +| Property | Description | Default | Since | +| ---------------------------------------- | -------------------------------------------- | ------- | ------ | +| authorization.local.policy.path | Path to the local policy file | | v2.0.0 | +| authorization.local.policy.poll_interval | Interval to poll the policy file for changes | 5m | v2.0.0 | +| authorization.local.data.path | Path to the local data file | | v2.0.0 | +| authorization.local.data.poll_interval | Interval to poll the data file for changes | 30s | v2.0.0 | + +### Analytics + +| Property | Description | Default | Since | +| ----------------------------- | ----------------------------------------------- | ------- | ------ | +| analytics.buffer.flush_period | Duration to wait before sending events to sinks | 10s | v2.0.0 | + +#### Analytics: Clickhouse + +| Property | Description | Default | Since | +| ------------------------------------ | ----------------------------------- | ------- | ------ | +| analytics.storage.clickhouse.enabled | Enable Clickhouse support | false | v2.0.0 | +| analytics.storage.clickhouse.url | URL to connect to clickhouse server | | v2.0.0 | + +#### Analytics: Prometheus + +| Property | Description | Default | Since | +| ------------------------------------ | ----------------------------------------------------------------------- | ------- | ------ | +| analytics.storage.prometheus.enabled | Enable Prometheus support | false | v2.0.0 | +| analytics.storage.prometheus.url | URL to connect to prometheus server | | v2.0.0 | +| analytics.storage.prometheus.headers | Additional headers to send with Prometheus requests (map[string]string) | | v2.0.0 | + +### Logging + +| Property | Description | Default | Since | +| ---------------- | -------------------------------------------------------------------------------- | ------- | ------ | +| log.level | Level at which messages are logged (debug, info, warn, error, fatal, panic) | info | v2.0.0 | +| log.grpc_level | Level at which gRPC messages are logged (debug, info, warn, error, fatal, panic) | error | v2.0.0 | +| log.file | File to log to instead of STDOUT | | v2.0.0 | +| log.encoding | Encoding to use for logging (json, console) | console | v2.0.0 | +| log.keys.time | Structured logging key used when outputting log timestamp | T | v2.0.0 | +| log.keys.level | Structured logging key used when outputting log level | L | v2.0.0 | +| log.keys.message | Structured logging key used when outputting log message | M | v2.0.0 | + +#### Logging: OTLP + +Flipt v2 supports the new [OpenTelemetry OTLP logging specification](https://opentelemetry.io/docs/specs/otel/logs/). To enable OTLP logging, set the `OTLP_LOGS_EXPORTER` environment variable + +```console +export OTLP_LOGS_EXPORTER=otlp +``` + + + OpenTelemetry logging is in addition to the existing logging configuration. It + does not replace the ability to log to a file or stdout/stderr. + + +OpenTelemetry OTLP logging is configured via the default OpenTelemetry Environment Variables. See the [OpenTelemetry Environment Variables](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/) documentation for more details. + +For example, to configure the OTLP logging endpoint, you can set the `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` environment variable. + +```console +export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://localhost:4317 +``` + +### Metrics + +| Property | Description | Default | Since | +| ---------------- | -------------------------------------- | ---------- | ------ | +| metrics.enabled | Enable metrics support | true | v2.0.0 | +| metrics.exporter | The exporter to use (prometheus, otlp) | prometheus | v2.0.0 | + +#### Metrics: OTLP + +OpenTelemetry OTLP metrics are configured via the default OpenTelemetry Environment Variables. See the [OpenTelemetry Environment Variables](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/) documentation for more details. + +For example, to configure the OTLP metrics endpoint, you can set the `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` environment variable. + +```console +export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:4317 +``` + +To configure the OTLP headers, you can set the `OTEL_EXPORTER_OTLP_METRICS_HEADERS` environment variable. + +```console +export OTEL_EXPORTER_OTLP_METRICS_HEADERS="Authorization=Bearer " +``` + +### Tracing + +| Property | Description | Default | Since | +| --------------- | ---------------------- | ------- | ------ | +| tracing.enabled | Enable tracing support | false | v2.0.0 | + +The only supported tracing backend is OTLP. + +#### Tracing: OTLP + +OpenTelemetry OTLP tracing is configured via the default OpenTelemetry Environment Variables. See the [OpenTelemetry Environment Variables](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/) documentation for more details. + +For example, to configure the OTLP tracing endpoint, you can set the `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` environment variable. + +```console +export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://localhost:4317 +``` + +To configure the OTLP headers, you can set the `OTEL_EXPORTER_OTLP_TRACES_HEADERS` environment variable. + +```console +export OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Bearer " +``` + +## Deprecations + +From time to time configuration options will need to be deprecated and +eventually removed. Deprecated configuration options will be removed after \~6 +months from the time they were deprecated. + +All deprecated configuration options will be removed from the documentation, +however, they will still work as expected until they're removed. A warning will +be logged in the Flipt logs when a deprecated configuration option is used. + +All deprecated options are listed in the [DEPRECATIONS](https://github.com/flipt-io/flipt/blob/v2/DEPRECATIONS.md) file +in the Flipt repository as well as the [CHANGELOG](https://github.com/flipt-io/flipt/blob/v2/CHANGELOG.md). diff --git a/v2/configuration/storage.mdx b/v2/configuration/storage.mdx new file mode 100644 index 00000000..2550d85b --- /dev/null +++ b/v2/configuration/storage.mdx @@ -0,0 +1,168 @@ +--- +title: Storage +description: This document describes how to configure Flipt v2's storage backend mechanisms. +--- + +Flipt v2 stores all of its resources in git repositories. This section describes how those git repositories are persisted and managed. + +## Identifiers + +Each storage backend has an identifier that is used to reference the storage backend in the configuration, such as when specifying the storage backend for an environment. + +Identifiers can be any string value but must be unique. Flipt creates a `default` identifier for you automatically if you don't specify one. + +In the following example, we've defined two storage backends: + +- `foo` is a local storage backend that will serve Flipt flag state from a local directory. +- `bar` is a memory storage backend that will serve Flipt flag state from an in-memory store. + +```yaml +storage: + foo: + name: "foo" + backend: + type: local + path: "/path/to/foo/repository" + bar: + name: "bar" + backend: + type: memory +``` + +## Backends + +Flipt v2 supports the following storage backends: + +- [Local](#local) +- [Memory](#memory) + +### Local + +The purpose of this backend type is to support serving Flipt flag state directly from your local filesystem in a git repository. + +This allows the the data to be persisted between server restarts. + +Flipt will periodically rebuild its state from the local disk every 10 seconds. + +```yaml +storage: + backend: + type: local + path: "." +``` + +The above configuration will create a local storage backend with the identifier `default` and serve Flipt flag state from the current working directory. + +### Memory + +The purpose of this backend type is to support serving Flipt flag state from an in-memory store. + +This is useful for development and testing purposes where you don't want to persist flag state to disk. + +```yaml +storage: + backend: + type: memory +``` + +The above configuration will create a memory storage backend with the identifier `default` and serve Flipt flag state from an in-memory store. + +## Git Remotes + +Flipt v2 supports syncing flag state to and from a remote git repository. + +```yaml +storage: + backend: + type: memory + remote: "https://github.com/flipt-io/example.git" + branch: "main" + poll_interval: "30s" + credentials: "github" +``` + +This configuration will create a git storage backend with the identifier `default` in memory and will sync flag state to and from the remote repository. + +### Conflict Resolution + +Conflicts can occur when syncing flag state to and from a remote repository. The conflict resolution strategy in Flipt v2 is currently rudimentary and we aim to improve this in future releases. + +When syncing flag state to and from a remote repository, Flipt will behave as follows: + +- Remote state is synced to the local storage backend using the configured `poll_interval` +- On writes to the Flipt server, the local storage backend will create a new commit and push it to the remote repository +- Flipt keeps track of the last commit hash for each storage backend +- If a write is made to a flag state file that has been modified since the last commit, Flipt will refuse to push the changes to the remote repository and will instead return an error +- If a write is made to a flag state file that has not been modified since the last commit, Flipt will push the changes to the remote repository + +### Credentials + +Credentials enable the ability to authenticate with the remote repository. + +Supported authentication schemes are: + +- `basic` +- `ssh` +- `access_token` + +Credentials are configured using the `credentials` configuration section and use identifiers to reference the credentials in the configuration. + + + This means that you can use the same credentials for multiple storage backends + if needed. + + +#### Basic + +Basic authentication is a username and password pair. + + + When using GitHub and their [PATs (Personal Access + Tokens)](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens), + `basic` authentication should be used. GitHub expects you to supply a valid + `username` and provide your PAT as the `password` parameter. + + +```yaml +credentials: + github: + type: basic + username: < username > + password: < github-personal-access-token > +``` + +#### SSH + +In order to configure a git remote with SSH, you will need to generate an SSH key-pair and configure your repository provider with the public key. + +GitHub has some excellent documentation regarding how to generate and install your credentials [here](https://docs.github.com/en/authentication/connecting-to-github-with-ssh). + +Once you have your private key credentials you will need to configure Flipt to use them. +This can be done via the `storage.git.authentication.ssh` configuration section: + +```yaml +credentials: + github: + type: ssh + user: git + private_key_path: ~/.ssh/id_rsa + private_key_bytes: # alternatively pass the raw bytes inline +``` + + + `insecure_ignore_host_key` is not encouraged for production use, and is + `false` by default. Instead, you are advised to put the key fingerprint in the + known hosts file where you are running Flipt. For example, for GitHub you can + do `ssh-keyscan github.com >> ~/.ssh/known_hosts` on the Flipt host. + + +#### Access Token + +Access tokens are a type of credential that are used to authenticate with a remote repository. These can be used for any remote repository provider that supports access tokens. + +```yaml +credentials: + gitlab: + type: access_token + token: < gitlab-access-token > +``` diff --git a/v2/configuration/telemetry.mdx b/v2/configuration/telemetry.mdx new file mode 100644 index 00000000..bbc6a98c --- /dev/null +++ b/v2/configuration/telemetry.mdx @@ -0,0 +1,62 @@ +--- +title: Telemetry +description: This document describes how to configure Flipt v2's telemetry outputs as well as what data is captured. +--- + +## Telemetry + +Flipt developers rely on anonymous usage data to help prioritize new features and improve the product. The information collected is completely anonymous, +never shared with external entities, and you can opt-out at any time. + +The telemetry data is collected by default, but you can disable it by following the instructions below. + +Telemetry is only collected when Flipt is running, **once at startup** and then every **4 hours**. + +### What Kind of Data is Collected? + +- Flipt version (i.e.: v2.0.0) +- Operating system (i.e.: Linux) +- Architecture (i.e.: amd64) + +We use [Jitsu](https://jitsu.com/) to collect the data. Only the Flipt team has access to the raw data. + +Here is an example of the telemetry data sent to Jitsu: + +```json +{ + "version": "2.0", + "uuid": "1545d8a8-7a66-4d8d-a158-0a1c576c68a6", + "lastTimestamp": "2023-04-25T01:01:51Z", + "flipt": { + "version": "v2.0.0", + "os": "linux", + "arch": "amd64" + } +} +``` + +You can always view the current schema of the telemetry data and see how it's collected on +[GitHub](https://github.com/flipt-io/flipt/blob/main/internal/telemetry/telemetry.go). + +### How To Disable Telemetry + +Telemetry collection can be disabled in several ways: + +#### Configuration File + +```yaml +meta: + telemetry_enabled: false +``` + +#### Environment Variables + +```shell +export FLIPT_META_TELEMETRY_ENABLED=false +``` + +Telemetry can also be disabled by setting the [DO_NOT_TRACK](https://consoledonottrack.com/) environment variable to `true` or `1`: + +```shell +export DO_NOT_TRACK=true +``` diff --git a/v2/introduction.mdx b/v2/introduction.mdx new file mode 100644 index 00000000..41b650a1 --- /dev/null +++ b/v2/introduction.mdx @@ -0,0 +1,52 @@ +--- +title: Introduction +description: This document describes the features and benefits of Flipt v2. +mode: "wide" +--- + +Flipt v2 is a major new version of Flipt that is built to be Git-native and +support a more flexible and powerful feature management platform. + + + Flipt v2 is currently in beta and is not recommended for production use. + + +## Features + +Flipt v2 introduces a number of new features and capabilities that are not available in v1 while maintaining backwards compatibility with v1. + +### Git-Native + +Flipt v2 is built to be Git-native, meaning that your feature flags and configurations are stored in your own Git repositories. This allows you to use your existing Git workflow and tools to manage your feature flags and configurations. + +We modeled Flipt v2 after our [Flipt Cloud](/cloud/overview) product, but with the ability to self-host. + +While Flipt v1 has the ability to read flag data from a Git repository, Flipt v2 takes this one step further by allowing you to write flag data to a Git repository using the Flipt v2 API and UI. + +We believe that Git is the best way to manage configuration data. We also believe that feature flags are a type of configuration data, and as such, they should be stored in the same way. + +By combining the power of Git with a user-friendly interface, Flipt v2 offers the best of both worlds: the robustness and version control of Git-backed storage, and the ease of use of a modern feature flag management system. + +### Multi-Environment + +Flipt v2 introduces the concept of environments, which are an additional layer above Flipt v1's concept of [Namespaces](/v1/concepts#namespace). + +Environments allow you to manage your feature flags and configurations in different several ways including: + +- Different Git repositories +- Different directories within the same Git repository +- Different branches within the same directory + +Each environment has its own set of namespaces, feature flags and configurations, and is completely isolated from the others. + +### No External Dependencies + +Flipt v2 is a standalone binary that does not depend on any external services. This means that you can run Flipt v2 on any machine that has a compatible operating system. + +V2 does not require any database or cache by default. Even the git-backed storage is local by default either in memory or on disk. You can configure Flipt v2 to sync your local git-backed storage to a remote git repository such as GitHub, GitLab, or Bitbucket. + +### Declarative APIs + +Flipt v2 introduces a declarative API for managing feature flags and configurations. This allows you to manage your feature flags and configurations in a declarative way, using a simple JSON schema. + +Flipt v2 works on the principle of managing resources. A resource is a collection of related configurations that are managed together. Feature flags are just one type of resource and are managed through the Flipt v2 API. diff --git a/v2/quickstart.mdx b/v2/quickstart.mdx new file mode 100644 index 00000000..683f60bb --- /dev/null +++ b/v2/quickstart.mdx @@ -0,0 +1,187 @@ +--- +title: Quickstart +description: This document describes how to get started with Flipt v2. +mode: "wide" +--- + +## Introduction + +This document will walk you through creating your first feature flag in Flipt v2. + +## Setup + +Before getting started, make sure the Flipt server is up and running on your +host on your chosen ports. See [Installation](/v2/installation) for more. + + + +```console Binary +curl -fsSL https://get.flipt.io/install/v2 | sh +``` + +```console Docker +docker run -d \ + -p 8080:8080 \ + -p 9000:9000 \ + -v $HOME/flipt:/var/opt/flipt \ + docker.flipt.io/flipt/flipt:v2 +``` + +```console Kubernetes/Helm +helm repo add flipt https://helm.flipt.io +helm install flipt flipt/flipt/v2 +``` + +```console Homebrew +brew install flipt-io/brew/flipt@v2 +``` + + + +In this example, we'll use the default location of http://localhost:8080. + +## Environments and Namespaces + +Flipt v2 introduces the concept of environments in addition to namespaces. + +By default, Flipt v2 will create a single environment called `default` along with the `default` namespace. + +// TODO: add screenshot of environments/namespace picker + +Environments are managed via configuration files. See the [Environments](/v2/concepts#environments) documentation for more. + +## Flags and Variants + +First, we'll create a flag and variants that we will use to evaluate against in the default environment and namespace. + +### Create a Flag + +A flag is the basic entity in Flipt. Flags can represent features in your +applications that you want to enable/disable for your users. + +To create a flag: + +1. Open the UI at http://localhost:8080. +2. Click `New Flag`. +3. Populate the details of the flag as shown. +4. Click `Enabled` so the flag will be enabled once created. +5. Click `Create`. + +!["Create Flag"](/v1/images/getting_started/create_flag.png) + +### Create Variants + +Variants allow you to return different values for your flags based on rules that +you define. + +To create a variant: + +1. On the Flag Details page for the new flag you created, click `New Variant`. +2. Populate the details of the variant as shown. +3. Click `Create`. +4. Create one more variant populating the information as you wish. + +!["Create Variant"](/v1/images/getting_started/create_variant.png) + +Click `Flags` in the navigation menu and you should now see your newly created +flag in the list. + +## Segments and Constraints + +Next, we'll create a segment with a constraint that will be used to determine the +reach of your flag. + +### Create a Segment + +Segments are used to split your user base into subsets. + +To create a segment: + +1. From the navigation click `Segments`. +2. Click `New Segment`. +3. Populate the details of the segment as shown. +4. Click `Create`. + +!["Create Segment"](/v1/images/getting_started/create_segment.png) + +### Create a Constraint + +Constraints are used to target a specific segment. + + + Constraints aren't required to match a segment. A segment with no constraints + will match every request by default. + + +To create a constraint: + +1. On the Segment Details page for the new segment you created, click + `New Constraint`. +2. Populate the details of the constraint as shown. +3. Click `Create`. + +!["Create Constraint"](/v1/images/getting_started/create_constraint.png) + +Click `Segments` in the navigation menu and you should now see your newly +created segment in the list. + +## Rules and Distributions + +Finally, we'll create a rule defining a distribution for your flag and variants. +Rules allow you to define which variant gets returned when you +evaluate a specific flag that falls into a given segment. + +### Create a Rule + +To create a rule: + +1. Go back to the flag you created at the beginning. +2. Scroll down and click the `Rules` tab. +3. Click `New Rule`. +4. Next to `Segment` choose or search for the segment you created earlier. +5. Next to `Type` choose `Multi-Variate`. +6. You should see the two variants that you created earlier, with a percentage + of `50%` each. +7. Click `Create`. + +!["Create"](/v1/images/getting_started/create_rule.png) + +A distribution is a way of assigning a percentage for which entities evaluated +get a specific variant. The higher the percentage assigned, the more likely it +is that any entity will get that specific variant. + + + You could just as easily have picked `Single Variant` instead of + `Multi-Variate` when setting up your rule. This would effectively mean you + have a single distribution, a variant with `100%` chance of being returned. + + +## Evaluation Console + +After creating the above flag, segment and targeting rule, you're now ready to +test how this would work in your application. + +The Flipt UI contains an Evaluation Console to allow you to experiment +with different requests to see how they would be evaluated. + +The main ideas behind how evaluation works are described in more detail in the +[Concepts](/v1/concepts#evaluation) documentation. + +To test evaluation: + +1. Navigate to the `Console` page from the main navigation. +2. Select or search for the flag you created earlier. +3. Notice that the `Entity ID` field is pre-populated with a random UUID. This represents + the ID that you would use to uniquely identify entities (ex: users) that you + want to test against your flags. +4. Click `Evaluate`. +5. Note the pane to the right has been populated with the evaluation + response from the server, informing you that this request would match the + segment that you created earlier, and return one of the variants defined. +6. Experiment with different values for the `Request Context` and `Entity ID` fields. + +!["Evaluation Console"](/v1/images/getting_started/evaluation_console.png) + +That's it! You're now ready to integrate Flipt into your applications and start +defining your flags and segments that will enable you to seamlessly rollout +new features to your users while reducing risk. From 40156e98313382c095570b3515a91eb0d7966828 Mon Sep 17 00:00:00 2001 From: Mark Phelps <209477+markphelps@users.noreply.github.com> Date: Wed, 23 Apr 2025 12:21:35 -0400 Subject: [PATCH 2/5] chore: fix urls Signed-off-by: Mark Phelps <209477+markphelps@users.noreply.github.com> --- cloud/features/approval-workflows.mdx | 20 ++++++++--------- cloud/features/authentication.mdx | 8 +++---- cloud/features/custom-domains.mdx | 4 ++-- cloud/features/git-backed-storage.mdx | 4 ++-- cloud/features/rbac.mdx | 8 +++---- cloud/features/user-management.mdx | 4 ++-- cloud/features/verified-commits.mdx | 8 +++---- cloud/guides/getting-started.mdx | 20 ++++++++--------- cloud/guides/production.mdx | 8 +++---- scripts/linkreplace.py | 2 +- v2/concepts.mdx | 32 +++++++++++++-------------- v2/configuration/analytics.mdx | 8 +++---- v2/configuration/authentication.mdx | 2 +- v2/configuration/authorization.mdx | 2 +- v2/configuration/observability.mdx | 4 ++-- v2/configuration/overview.mdx | 2 +- v2/introduction.mdx | 2 +- v2/quickstart.mdx | 14 ++++++------ 18 files changed, 76 insertions(+), 76 deletions(-) mode change 100644 => 100755 scripts/linkreplace.py diff --git a/cloud/features/approval-workflows.mdx b/cloud/features/approval-workflows.mdx index 366a74cf..cd2d31d0 100644 --- a/cloud/features/approval-workflows.mdx +++ b/cloud/features/approval-workflows.mdx @@ -6,7 +6,7 @@ mode: "wide" Flipt Cloud provides a built-in approval workflow system that allows you to easily manage and track the proposal and approval process for your flags, ensuring that they are approved by the appropriate stakeholders before they are released to production. -![Proposal Merged](/images/cloud/features/approval/proposal-merged.png) +![Proposal Merged](/cloud/images/features/approval/proposal-merged.png) ## Overview @@ -28,7 +28,7 @@ The approval workflow system is designed to fit into this process, and to make i When you create an environment in Flipt Cloud, you can choose to protect the environment. This will require that all flag and other configuration changes go through a review and approval process before they are served from the environment. -![Protected Environment](/images/cloud/features/approval/protected-environment.png) +![Protected Environment](/cloud/images/features/approval/protected-environment.png) In our Git backed storage model, all environments have a default branch. If you chose an existing repository and branch when creating the environment and that branch is protected, the environment itself will be protected by default. @@ -39,17 +39,17 @@ In our Git backed storage model, all environments have a default branch. If you Protected environments are read-only and can only be changed by going through the proposal/approval process. If you are in a protected environment, you will see the 'Protected' badge in the top right of the environment. -![Protected Environment Badge](/images/cloud/features/approval/protected-badge.png) +![Protected Environment Badge](/cloud/images/features/approval/protected-badge.png) ## Approval Process To make a change for a protected environment, you will need to put the environment into 'editing mode' by clicking on the 'Protected' badge. This will prompt a confirmation dialog asking you to confirm that you want to create a proposal branch to make your changes. -![Create Branch Dialog](/images/cloud/features/approval/create-branch-dialog.png) +![Create Branch Dialog](/cloud/images/features/approval/create-branch-dialog.png) Once you click 'Create Branch', you will be redirected to a new environment that is no longer protected. This environment is a full read/write replica of the protected environment, but any changes you make will not be deployed to the protected environment until they are approved and merged. -![Unprotected Environment](/images/cloud/features/approval/unprotected-environment.png) +![Unprotected Environment](/cloud/images/features/approval/unprotected-environment.png) You can make changes to the unprotected environment, and they will be captured in the proposal branch. Once you are ready to deploy your changes, you can create a pull request into the protected environment. @@ -57,25 +57,25 @@ You can make changes to the unprotected environment, and they will be captured i After making the changes you want to propose, you can create a proposal by clicking on the 'Propose' button in the top right of the screen. This will again prompt a confirmation dialog asking you to confirm that you want to create a new pull request in your repository and add it to the approval workflow. -![Create Proposal Dialog](/images/cloud/features/approval/create-proposal-dialog.png) +![Create Proposal Dialog](/cloud/images/features/approval/create-proposal-dialog.png) Once you click 'Create Proposal', you will see a badge in the top right of the screen indicating that a proposal is pending, with a link to the proposal pull request. -![Proposal Pending Badge](/images/cloud/features/approval/proposal-pending.png) +![Proposal Pending Badge](/cloud/images/features/approval/proposal-pending.png) Clicking on the badge will take you to the proposal pull request. -![Proposal Pull Request](/images/cloud/features/approval/proposal-pull-request.png) +![Proposal Pull Request](/cloud/images/features/approval/proposal-pull-request.png) ## Approve and Merge Your team can review the proposal and approve it by clicking on the 'Approve' button in the pull request. Once the proposal is approved, you will be able to merge the pull request into the protected environment. -![Approve Pull Request](/images/cloud/features/approval/approve-pull-request.png) +![Approve Pull Request](/cloud/images/features/approval/approve-pull-request.png) Once the pull request is merged, the changes will be deployed to the protected environment. -![Deployed Changes](/images/cloud/features/approval/deployed-changes.png) +![Deployed Changes](/cloud/images/features/approval/deployed-changes.png) You can leverage GitHub's existing [Code diff --git a/cloud/features/authentication.mdx b/cloud/features/authentication.mdx index 33bbfff9..7e2ee1e9 100644 --- a/cloud/features/authentication.mdx +++ b/cloud/features/authentication.mdx @@ -10,7 +10,7 @@ You get social login, passwordless authentication, and multi-factor authenticati We also support custom authentication providers, so you can integrate with your existing identity management system. -![Authentication](/images/cloud/features/auth/login.png) +![Authentication](/cloud/images/features/auth/login.png) This flexibility allows you to choose the authentication method that best fits your organization's needs, whether you're a small startup or a large enterprise. @@ -18,7 +18,7 @@ This flexibility allows you to choose the authentication method that best fits y Flipt Cloud supports Single Sign-On (SSO) with popular identity providers like Okta, Microsoft Active Directory, and Google Workspace. With SSO, your team members can log in to Flipt using their existing credentials, making it easy to manage access and permissions. -![Single Sign-On](/images/cloud/features/auth/sso.gif) +![Single Sign-On](/cloud/images/features/auth/sso.gif) SSO also enhances security by reducing the number of passwords your team members need to remember and ensuring that access is granted only to authorized users. @@ -28,8 +28,8 @@ You can even set up custom SAML and OIDC providers, so you can use your existing To access the Flipt API for evaluation requests, you can generate API keys for each environment that you create. This key is used to authenticate your requests to the API and is available in the environment settings. -![API Access](/images/cloud/features/auth/api-access.png) +![API Access](/cloud/images/features/auth/api-access.png) API keys are securely stored in Flipt Cloud and are used to authenticate requests made through our SDKs. -![API Key](/images/cloud/features/auth/api-key.png) +![API Key](/cloud/images/features/auth/api-key.png) diff --git a/cloud/features/custom-domains.mdx b/cloud/features/custom-domains.mdx index b1d84c05..de3b7292 100644 --- a/cloud/features/custom-domains.mdx +++ b/cloud/features/custom-domains.mdx @@ -76,11 +76,11 @@ Using custom domains with Flipt Cloud is a simple three step process: 1. **Configure the Domain**: Once enabled, you can add your custom domain to your Flipt Cloud environment in the Flipt Cloud UI. -![Environment Domain](/images/cloud/features/domains/environment-domain.png) +![Environment Domain](/cloud/images/features/domains/environment-domain.png) 2. **Configure the DNS**: You'll need to configure the DNS for your custom domain to point to your existing Flipt Cloud environment. -![DNS Configuration](/images/cloud/features/domains/dns-configuration.png) +![DNS Configuration](/cloud/images/features/domains/dns-configuration.png) 3. **Update Your SDKs**: Once the DNS has propagated, you simply need to update your SDKs to use the new domain. diff --git a/cloud/features/git-backed-storage.mdx b/cloud/features/git-backed-storage.mdx index 0c3e147a..ca33b929 100644 --- a/cloud/features/git-backed-storage.mdx +++ b/cloud/features/git-backed-storage.mdx @@ -8,7 +8,7 @@ mode: "wide" Flipt Cloud is unique in that it uses your existing Git repositories for your feature flags and configurations. This means that your feature flag data is stored in a Git repository of your choosing, which allows you to use your existing Git workflow and tools. -![Git-Backed Storage](/images/cloud/features/git/feature-flag-in-repository.png) +![Git-Backed Storage](/cloud/images/features/git/feature-flag-in-repository.png) Flipt Cloud manages your feature flags in what we call [Environments](/cloud/concepts#environments). @@ -34,7 +34,7 @@ As developers ourselves, we understand the power of Git. It allows you to review Because we mirror your flag data in Git, you always have the ability to 'break the glass' and make changes directly to the Git repository if needed. -![Flipt UI](/images/cloud/features/git/feature-flag-in-ui.png) +![Flipt UI](/cloud/images/features/git/feature-flag-in-ui.png) We believe that Git is the best way to manage configuration data. We also believe that feature flags are a type of configuration data, and as such, they should be in the same way. diff --git a/cloud/features/rbac.mdx b/cloud/features/rbac.mdx index fba91991..98612423 100644 --- a/cloud/features/rbac.mdx +++ b/cloud/features/rbac.mdx @@ -6,7 +6,7 @@ mode: "wide" Role-based access control allows you to define custom roles and permissions for your team members. -![Roles](/images/cloud/features/rbac/roles.png) +![Roles](/cloud/images/features/rbac/roles.png) You can create roles with specific permissions, such as read-only access to feature flags or the ability to create new flags. This gives you fine-grained control over who can do what in Flipt Cloud and your Flipt instances. @@ -24,7 +24,7 @@ Flipt Cloud comes with several built-in roles that you can assign to your team m - **Editor**: Can create and update most resources, but cannot delete them. Cannot access organization settings. - **Viewer**: Read-only access to most resources, cannot create or update them. Cannot access organization settings. -![Built-In Roles](/images/cloud/features/rbac/roles-built-in.png) +![Built-In Roles](/cloud/images/features/rbac/roles-built-in.png) Built-in roles cannot be modified or deleted, but you can create custom roles with specific permissions to meet your organization's needs. @@ -32,7 +32,7 @@ Built-in roles cannot be modified or deleted, but you can create custom roles wi You can create custom roles with any permissions you need. For example, you can create a role that allows users to create and update feature flags and segments, but not delete them. -![Custom Roles](/images/cloud/features/rbac/roles-custom.png) +![Custom Roles](/cloud/images/features/rbac/roles-custom.png) ## Assigning Roles @@ -43,7 +43,7 @@ You can assign roles to team members after you invite them to your organization invited to your organization. -![Assign Roles](/images/cloud/features/rbac/roles-assign.png) +![Assign Roles](/cloud/images/features/rbac/roles-assign.png) ## Role Scope diff --git a/cloud/features/user-management.mdx b/cloud/features/user-management.mdx index bbc0cc16..0dc0012d 100644 --- a/cloud/features/user-management.mdx +++ b/cloud/features/user-management.mdx @@ -6,11 +6,11 @@ mode: "wide" Flipt Cloud makes it easy to manage your team members and their permissions. You can invite users in your organization, assign roles, and control access to features and data. -![User Management](/images/cloud/features/users/team.png) +![User Management](/cloud/images/features/users/team.png) With features like [Role-Based Access Control](/cloud/features/rbac), you can ensure that team members have the right level of access to the features they need, while keeping sensitive data secure. -![Invite Users](/images/cloud/features/users/invite.png) +![Invite Users](/cloud/images/features/users/invite.png) ## Just in Time User Provisioning diff --git a/cloud/features/verified-commits.mdx b/cloud/features/verified-commits.mdx index 199d33cd..04e38575 100644 --- a/cloud/features/verified-commits.mdx +++ b/cloud/features/verified-commits.mdx @@ -8,7 +8,7 @@ Verify Flipt's commits to your GitHub repository with SSH signing keys. This ens You can learn more about GitHub's commit verification in the [GitHub documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification). -![Signed Commits](/images/cloud/features/verified-commits/commits.png) +![Signed Commits](/cloud/images/features/verified-commits/commits.png) Verified Commits are only available on our Team plan and above. See our @@ -21,11 +21,11 @@ To verify commits with Flipt Cloud, we'll need to create a signing key, as Flipt needs to be able to sign the commits it creates itself. -![Generate Key](/images/cloud/features/verified-commits/generate-key.png) +![Generate Key](/cloud/images/features/verified-commits/generate-key.png) To do this, head to your user settings in Flipt Cloud, and click 'Generate Key'. -![Signing Key](/images/cloud/features/verified-commits/signing-key.png) +![Signing Key](/cloud/images/features/verified-commits/signing-key.png) Copy the key as you'll need to add it to GitHub in the next step. @@ -38,7 +38,7 @@ It must be a signing key, rather than an authentication key, as we don't want this key to be able to push to your repositories, just to verify commits. -![Add Key](/images/cloud/features/verified-commits/add-signing-key.png) +![Add Key](/cloud/images/features/verified-commits/add-signing-key.png) ## How We Store Your Key diff --git a/cloud/guides/getting-started.mdx b/cloud/guides/getting-started.mdx index f80b1601..e85641c9 100644 --- a/cloud/guides/getting-started.mdx +++ b/cloud/guides/getting-started.mdx @@ -26,7 +26,7 @@ Before you get started with Flipt Cloud, you need to have the following: Once you are logged in, you will see the Flipt Cloud dashboard. Click on `Create Environment`. -![Create Environment](/images/cloud/guides/getting-started/dashboard.png) +![Create Environment](/cloud/images/guides/getting-started/dashboard.png) @@ -34,7 +34,7 @@ Once you are logged in, you will see the Flipt Cloud dashboard. Click on `Create Give your environment a name and description to help you identify it later. -![Name Environment](/images/cloud/guides/getting-started/environment-form.png) +![Name Environment](/cloud/images/guides/getting-started/environment-form.png) @@ -42,7 +42,7 @@ Give your environment a name and description to help you identify it later. If you haven't already connected your GitHub account, you'll be prompted to install our GitHub App in your organization. -![Authorize GitHub](/images/cloud/guides/getting-started/authorize-github.png) +![Authorize GitHub](/cloud/images/guides/getting-started/authorize-github.png) Select the repositories you want to allow Flipt Cloud to access, or select all repositories. @@ -52,7 +52,7 @@ Select the repositories you want to allow Flipt Cloud to access, or select all r Select the repository you want to store your feature flags and configurations in, or create a new one. -![Select Repository](/images/cloud/guides/getting-started/select-repository.png) +![Select Repository](/cloud/images/guides/getting-started/select-repository.png) You can also specify a branch or use the default branch. @@ -69,7 +69,7 @@ Optionally choose a path for your feature flags and configurations. You can choose to store your feature flags and configurations in the root of your repository, or in a subdirectory. If it doesn't exist, it will be created. -![Choose Path](/images/cloud/guides/getting-started/choose-path.png) +![Choose Path](/cloud/images/guides/getting-started/choose-path.png) @@ -77,7 +77,7 @@ You can choose to store your feature flags and configurations in the root of you Finally, click on `Done` to create your environment. -![Create Environment](/images/cloud/guides/getting-started/done.png) +![Create Environment](/cloud/images/guides/getting-started/done.png) @@ -87,7 +87,7 @@ You will be redirected to the environment dashboard. Click on your new environment to open up the Flipt UI. -![Flipt UI](/images/cloud/guides/getting-started/flipt-ui.png) +![Flipt UI](/cloud/images/guides/getting-started/flipt-ui.png) @@ -95,7 +95,7 @@ Click on your new environment to open up the Flipt UI. Create a new feature flag by clicking on the `Flags` menu and then clicking on the `New Flag` button. - ![Create Feature Flag](/images/cloud/guides/getting-started/create-flag.png) + ![Create Feature Flag](/cloud/images/guides/getting-started/create-flag.png) See the [Getting Started](/introduction#create-a-flag) guide in Open Source for more information on how to create a feature flag. @@ -107,7 +107,7 @@ Click on your new environment to open up the Flipt UI. Go to your repository in GitHub and you will see the feature flag you created. - ![Repository](/images/cloud/guides/getting-started/repository.png) + ![Repository](/cloud/images/guides/getting-started/repository.png) The feature flag will be stored in the path you specified, or in the root of your repository if you didn't specify a path. @@ -116,7 +116,7 @@ Click on your new environment to open up the Flipt UI. in your repository. - ![Feature Flag in Repository](/images/cloud/guides/getting-started/feature-flag-in-repository.png) + ![Feature Flag in Repository](/cloud/images/guides/getting-started/feature-flag-in-repository.png) diff --git a/cloud/guides/production.mdx b/cloud/guides/production.mdx index 66a1e801..8d211474 100644 --- a/cloud/guides/production.mdx +++ b/cloud/guides/production.mdx @@ -34,7 +34,7 @@ From the Flipt Cloud dashboard, find the environment you want to create an API k Click on the `Edit` link. -![Edit Environment](/images/cloud/guides/production/edit-environment.png) +![Edit Environment](/cloud/images/guides/production/edit-environment.png) @@ -42,7 +42,7 @@ Click on the `Edit` link. Click on the `Security` tab and then click on the `Create API Key` button. -![Security](/images/cloud/guides/production/security.png) +![Security](/cloud/images/guides/production/security.png) @@ -50,11 +50,11 @@ Click on the `Security` tab and then click on the `Create API Key` button. Give your API a name to help you identify it later and click on the `Create` button. -![Name API Key](/images/cloud/guides/production/name-api-key.png) +![Name API Key](/cloud/images/guides/production/name-api-key.png) Copy the API key to your clipboard and save it in a secure location. You will not be able to access the API key after you leave this page. -![API Key Created](/images/cloud/guides/production/api-key-created.png) +![API Key Created](/cloud/images/guides/production/api-key-created.png) diff --git a/scripts/linkreplace.py b/scripts/linkreplace.py old mode 100644 new mode 100755 index 1e23da67..df5eba0a --- a/scripts/linkreplace.py +++ b/scripts/linkreplace.py @@ -17,7 +17,7 @@ def replace_links_in_file(filepath: str, from_path: str, to_path: str): def walk_and_process(root_dir: str, from_path: str, to_path: str): for dirpath, _, filenames in os.walk(root_dir): for fname in filenames: - if fname.endswith('.md'): + if fname.endswith('.mdx'): replace_links_in_file(os.path.join(dirpath, fname), from_path, to_path) def main(): diff --git a/v2/concepts.mdx b/v2/concepts.mdx index 35eda2a0..11db97cc 100644 --- a/v2/concepts.mdx +++ b/v2/concepts.mdx @@ -24,7 +24,7 @@ If an environment isn't selected then the 'Default' environment is used. Namespaces are a way to organize your feature flags and configurations within an environment. -![Namespaces Settings](/v1/images/concepts/namespaces_production.png) +![Namespaces Settings](/images/concepts/namespaces_production.png) One common use-case of Namespaces is to separate Flipt data by internal team. @@ -35,11 +35,11 @@ If a namespace isn't selected then the 'Default' namespace is used. -![Namespaces Settings](/v1/images/concepts/namespaces_default.png) +![Namespaces Settings](/images/concepts/namespaces_default.png) Namespaces can be managed within the `Settings` section of the Flipt UI: -![Namespaces Settings](/v1/images/concepts/settings_namespaces.png) +![Namespaces Settings](/images/concepts/settings_namespaces.png) ## Flags @@ -54,7 +54,7 @@ working on when they visit your homepage. Flags can be used as simple on/off toggles or with variants and rules to support more elaborate use cases. -![Flags Example](/v1/images/concepts/flags.png) +![Flags Example](/images/concepts/flags.png) There are two types of flags: @@ -80,7 +80,7 @@ The attachment size is limited to **1MB**. -![Variant Flags Example](/v1/images/concepts/flags_variants.png) +![Variant Flags Example](/images/concepts/flags_variants.png) ### Boolean Flags @@ -90,13 +90,13 @@ You can use boolean flags to determine if a feature is enabled or disabled for a Boolean flags can be configured with [rollout](#rollouts) rules to determine which entities receive `true` or `false` for a given flag. -![Boolean Flags Example](/v1/images/concepts/flags_boolean.png) +![Boolean Flags Example](/images/concepts/flags_boolean.png) ### Metadata All flags can have metadata associated with them. This metadata is stored in the Flipt backend and can be used to add additional information about a flag. -Metadata is stored as a JSON object and is not used for evaluation. You can retrieve flag metadata using the [Get Flag](/v1/reference/flags/get-flag) API. +Metadata is stored as a JSON object and is not used for evaluation. You can retrieve flag metadata using the [Get Flag](/reference/flags/get-flag) API. In the Flipt UI, metadata is displayed in the flag details section. The UI allows you to add, edit, and delete metadata and provides a more user-friendly interface for managing metadata by specifying key-value pairs and their data types. @@ -105,7 +105,7 @@ Currently, the following data types are supported: - Primitive types: `String`, `Number`, `Boolean` - Complex types: `Array`, `Object` -![Flag Metadata Example](/v1/images/concepts/flags_metadata.png) +![Flag Metadata Example](/images/concepts/flags_metadata.png) ## Segments @@ -115,7 +115,7 @@ a flag or variant applies to them. An example segment could be `new-users`. -![Segments Example](/v1/images/concepts/segments.png) +![Segments Example](/images/concepts/segments.png) Segments are global within a Flipt namespace. @@ -135,7 +135,7 @@ Constraints allow you to determine which segment a given entity is a part of. For example, for a user to fall into the above `new-users` segment, you may want to check their `finished_onboarding` property. -![Constraints Example](/v1/images/concepts/constraints.png) +![Constraints Example](/images/concepts/constraints.png) All constraints have a _property_, _type_, _operator_ and optionally a _value_. @@ -149,7 +149,7 @@ Currently 5 constraint types are available: - **DateTime** which allows you to check a date or datetime property of an entity such as `2020-01-01` or `2020-01-01T00:00:00Z` ([RFC3339](https://datatracker.ietf.org/doc/html/rfc3339)) - **Entity** which allows you to check the `entityId` that was sent in the body of the `Variant` or `Boolean` request -![Constraint Types](/v1/images/concepts/constraints_types.png) +![Constraint Types](/images/concepts/constraints_types.png) The constraint value is represented as a string in transit and in the @@ -167,7 +167,7 @@ richer by using distribution logic to roll out features on a percentage basis. Continuing our previous example, we may want to return the flag variant `dark` for all entities in the `new-users` segment. This would be configured like so: -![Rules Example](/v1/images/concepts/rules.png) +![Rules Example](/images/concepts/rules.png) Rules are evaluated in order per their rank from 1-N. The first rule that matches wins. Once created, rules can be re-ordered to change how they're @@ -179,7 +179,7 @@ evaluated. If no rules match for a given flag, the default rule value is returned. This value is optional and can be set to any variant that exists for the flag. -![Default Rule Example](/v1/images/concepts/default_rule.png) +![Default Rule Example](/images/concepts/default_rule.png) ### Distributions @@ -190,7 +190,7 @@ Let's say that instead of always showing the `dark` variant to your `new-users` segment, you want to show `dark` to **10%** of `new-users`, `light` to **30%**, and `auto` to the remaining **60%**. You would accomplish this using rules with distributions: -![Distributions Example](/v1/images/concepts/distributions.png) +![Distributions Example](/images/concepts/distributions.png) The ability to manage distributions, as illustrated in the image above, is an extremely powerful feature of Flipt that can help you seamlessly deploy new features of your applications to your users while also limiting the reach of potential bugs. @@ -205,7 +205,7 @@ Current rollout types include: - **Threshold** which allows you to return `true` or `false` for a given percentage of entities. - **Segments Match** which allows you to return `true` or `false` if an entity matches a given segment. -![Rollouts Example](/v1/images/concepts/rollouts.png) +![Rollouts Example](/images/concepts/rollouts.png) Rollouts work similar to [Rules](#rules) in that they're evaluated in order per their rank from 1-N. The first rollout that matches wins. Once created, rollouts can be re-ordered to change how they're evaluated. @@ -223,7 +223,7 @@ In the above example involving colors, evaluation is where you send information about your current user to determine if they're a `new-user`, and which color (`dark`, `auto`, or `light`) that they should see for their main color scheme. -![Evaluation Example](/v1/images/concepts/evaluation.png) +![Evaluation Example](/images/concepts/evaluation.png) ### Entities diff --git a/v2/configuration/analytics.mdx b/v2/configuration/analytics.mdx index d7750669..f5d79115 100644 --- a/v2/configuration/analytics.mdx +++ b/v2/configuration/analytics.mdx @@ -18,15 +18,15 @@ The data that gets collected currently includes: Once a storage engine is configured, these analytics are viewable in the UI allowing users to visualize up to 24 hours of data for each metric. -![UI For Analytics](/v1/images/configuration/analytics_quick_view.png) +![UI For Analytics](/images/configuration/analytics_quick_view.png) The image above shows the past 30 minutes of the flag `flag1` evaluation counts. ### Origin -Analytics are currently only collected as they pass through the evaluation server. This means that analytics will be captured if you are using the REST or GRPC APIs via one of our [Server SDKs](/v1/integration/server/rest) or [GRPC SDKs](/v1/integration/server/grpc) for evaluations. +Analytics are currently only collected as they pass through the evaluation server. This means that analytics will be captured if you are using the REST or GRPC APIs via one of our [Server SDKs](/integration/server/rest) or [GRPC SDKs](/integration/server/grpc) for evaluations. -We have plans to support collecting analytics for [Client-Side](/v1/integration/client) evaluations in the future. +We have plans to support collecting analytics for [Client-Side](/integration/client) evaluations in the future. ## ClickHouse @@ -37,7 +37,7 @@ We highly **recommend** using a separate database for analytics produced by Flip The analytics database must be created before Flipt will be able to write analytical data and run any migrations. See our - [migration](/v1/configuration/storage#migrations) section for more info. + [migration](/configuration/storage#migrations) section for more info. To create a database for Flipt analytics, you can use the following SQL: diff --git a/v2/configuration/authentication.mdx b/v2/configuration/authentication.mdx index 91b4ceea..e9782da7 100644 --- a/v2/configuration/authentication.mdx +++ b/v2/configuration/authentication.mdx @@ -424,7 +424,7 @@ authentication: Once enabled, client tokens can be retrieved by sending a Kubernetes pod's service account token to the `VerifyServiceAccount` operation in the API. -Further explanation for using this method can be found in the [Authentication: Kubernetes](/v1/authentication/methods#kubernetes) documentation. +Further explanation for using this method can be found in the [Authentication: Kubernetes](/authentication/methods#kubernetes) documentation. #### Troubleshooting diff --git a/v2/configuration/authorization.mdx b/v2/configuration/authorization.mdx index 9e6d8f8a..e4da3335 100644 --- a/v2/configuration/authorization.mdx +++ b/v2/configuration/authorization.mdx @@ -84,7 +84,7 @@ authorization: path: "data.json" ``` -You can learn more about using data with policies in our [Authorization: Overview](/v1/authorization/overview#external-data) documentation. +You can learn more about using data with policies in our [Authorization: Overview](/authorization/overview#external-data) documentation. #### Polling Interval diff --git a/v2/configuration/observability.mdx b/v2/configuration/observability.mdx index 672b12ba..ce4bbdca 100644 --- a/v2/configuration/observability.mdx +++ b/v2/configuration/observability.mdx @@ -102,7 +102,7 @@ For production deployments, we recommend using the JSON format as it's easier to 2024-01-20T22:04:18-05:00 INFO finished unary call with code OK {"server": "grpc", "grpc.start_time": "2024-01-20T22:04:18-05:00", "system": "grpc", "span.kind": "server", "grpc.service": "flipt.evaluation.EvaluationService", "grpc.method": "Boolean", "peer.address": "127.0.0.1:53714", "grpc.code": "OK", "grpc.time_ms": 0.373} ``` -More information about the available configuration options can be found in the [Logging configuration](/v1/configuration/overview#logging) section. +More information about the available configuration options can be found in the [Logging configuration](/configuration/overview#logging) section. ## Tracing @@ -110,7 +110,7 @@ Flipt supports distributed tracing via the [OpenTelemetry](https://opentelemetry ### OTLP -![Datadog OTLP](/v1/images/configuration/datadog_otlp.png) +![Datadog OTLP](/images/configuration/datadog_otlp.png) OTLP supports additional configuration such as specifying the protocol to use (gRPC or HTTP) as well as providing custom headers to send with the request. diff --git a/v2/configuration/overview.mdx b/v2/configuration/overview.mdx index 594a600b..ac82fa38 100644 --- a/v2/configuration/overview.mdx +++ b/v2/configuration/overview.mdx @@ -21,7 +21,7 @@ properties for the server. You can generate a default configuration file by running `flipt config init`. - See the [CLI](/v1/cli) documentation for more information. + See the [CLI](/cli) documentation for more information. The server will check in a few different locations for server configuration (in order): diff --git a/v2/introduction.mdx b/v2/introduction.mdx index 41b650a1..a5471cf9 100644 --- a/v2/introduction.mdx +++ b/v2/introduction.mdx @@ -29,7 +29,7 @@ By combining the power of Git with a user-friendly interface, Flipt v2 offers th ### Multi-Environment -Flipt v2 introduces the concept of environments, which are an additional layer above Flipt v1's concept of [Namespaces](/v1/concepts#namespace). +Flipt v2 introduces the concept of environments, which are an additional layer above Flipt v1's concept of [Namespaces](/concepts#namespace). Environments allow you to manage your feature flags and configurations in different several ways including: diff --git a/v2/quickstart.mdx b/v2/quickstart.mdx index 683f60bb..26072fb5 100644 --- a/v2/quickstart.mdx +++ b/v2/quickstart.mdx @@ -67,7 +67,7 @@ To create a flag: 4. Click `Enabled` so the flag will be enabled once created. 5. Click `Create`. -!["Create Flag"](/v1/images/getting_started/create_flag.png) +!["Create Flag"](/images/getting_started/create_flag.png) ### Create Variants @@ -81,7 +81,7 @@ To create a variant: 3. Click `Create`. 4. Create one more variant populating the information as you wish. -!["Create Variant"](/v1/images/getting_started/create_variant.png) +!["Create Variant"](/images/getting_started/create_variant.png) Click `Flags` in the navigation menu and you should now see your newly created flag in the list. @@ -102,7 +102,7 @@ To create a segment: 3. Populate the details of the segment as shown. 4. Click `Create`. -!["Create Segment"](/v1/images/getting_started/create_segment.png) +!["Create Segment"](/images/getting_started/create_segment.png) ### Create a Constraint @@ -120,7 +120,7 @@ To create a constraint: 2. Populate the details of the constraint as shown. 3. Click `Create`. -!["Create Constraint"](/v1/images/getting_started/create_constraint.png) +!["Create Constraint"](/images/getting_started/create_constraint.png) Click `Segments` in the navigation menu and you should now see your newly created segment in the list. @@ -144,7 +144,7 @@ To create a rule: of `50%` each. 7. Click `Create`. -!["Create"](/v1/images/getting_started/create_rule.png) +!["Create"](/images/getting_started/create_rule.png) A distribution is a way of assigning a percentage for which entities evaluated get a specific variant. The higher the percentage assigned, the more likely it @@ -165,7 +165,7 @@ The Flipt UI contains an Evaluation Console to allow you to experiment with different requests to see how they would be evaluated. The main ideas behind how evaluation works are described in more detail in the -[Concepts](/v1/concepts#evaluation) documentation. +[Concepts](/concepts#evaluation) documentation. To test evaluation: @@ -180,7 +180,7 @@ To test evaluation: segment that you created earlier, and return one of the variants defined. 6. Experiment with different values for the `Request Context` and `Entity ID` fields. -!["Evaluation Console"](/v1/images/getting_started/evaluation_console.png) +!["Evaluation Console"](/images/getting_started/evaluation_console.png) That's it! You're now ready to integrate Flipt into your applications and start defining your flags and segments that will enable you to seamlessly rollout From 5120ee9ba92db5d61738185859297afd0bc569b9 Mon Sep 17 00:00:00 2001 From: Mark Phelps <209477+markphelps@users.noreply.github.com> Date: Wed, 23 Apr 2025 12:23:04 -0400 Subject: [PATCH 3/5] chore: fix v1 telemetry Signed-off-by: Mark Phelps <209477+markphelps@users.noreply.github.com> --- configuration/telemetry.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration/telemetry.mdx b/configuration/telemetry.mdx index a49b8d9d..9d46345d 100644 --- a/configuration/telemetry.mdx +++ b/configuration/telemetry.mdx @@ -19,9 +19,9 @@ Telemetry is only collected when Flipt is running, **once at startup** and then - Cache backend (i.e.: Redis) - Authentication methods (i.e.: OIDC) -We use [Segment](https://segment.com) to collect the data. Only the Flipt team has access to the raw data. +We use [Jitsu](https://jitsu.com/) to collect the data. Only the Flipt team has access to the raw data. -Here is an example of the telemetry data sent to Segment: +Here is an example of the telemetry data sent to Jitsu: ```json { From 0c97263c95b8c928422550b4df36f9316eb0418b Mon Sep 17 00:00:00 2001 From: Mark Phelps <209477+markphelps@users.noreply.github.com> Date: Thu, 24 Apr 2025 15:35:25 -0400 Subject: [PATCH 4/5] feat: get v2 docs started Signed-off-by: Mark Phelps <209477+markphelps@users.noreply.github.com> --- cloud/architecture.mdx | 16 +- cloud/features/custom-domains.mdx | 4 +- docs.json | 622 +++++++++--------- introduction.mdx | 9 +- snippets/cloud.mdx | 8 + snippets/v2-alpha.mdx | 7 + v2/concepts.mdx | 36 +- v2/configuration/authentication.mdx | 12 +- v2/configuration/authorization.mdx | 12 +- v2/configuration/environments.mdx | 87 +++ v2/configuration/observability.mdx | 23 +- v2/configuration/overview.mdx | 5 +- v2/configuration/storage.mdx | 44 +- v2/configuration/telemetry.mdx | 4 +- v2/images/concepts/environments.png | Bin 0 -> 200454 bytes .../environments/storage-dark.svg | 182 +++++ .../environments/storage-light.svg | 110 ++++ .../configuration/environments/storage.d2 | 65 ++ .../storage/credentials-dark.svg | 171 +++++ .../storage/credentials-light.svg | 99 +++ .../configuration/storage/credentials.d2 | 58 ++ v2/images/quickstart/default_environment.png | Bin 0 -> 186355 bytes v2/introduction.mdx | 18 +- v2/quickstart.mdx | 42 +- 24 files changed, 1236 insertions(+), 398 deletions(-) create mode 100644 snippets/cloud.mdx create mode 100644 snippets/v2-alpha.mdx create mode 100644 v2/configuration/environments.mdx create mode 100644 v2/images/concepts/environments.png create mode 100644 v2/images/configuration/environments/storage-dark.svg create mode 100644 v2/images/configuration/environments/storage-light.svg create mode 100644 v2/images/configuration/environments/storage.d2 create mode 100644 v2/images/configuration/storage/credentials-dark.svg create mode 100644 v2/images/configuration/storage/credentials-light.svg create mode 100644 v2/images/configuration/storage/credentials.d2 create mode 100644 v2/images/quickstart/default_environment.png diff --git a/cloud/architecture.mdx b/cloud/architecture.mdx index 0632c297..e8d8e124 100644 --- a/cloud/architecture.mdx +++ b/cloud/architecture.mdx @@ -20,11 +20,11 @@ This allows Flipt Cloud to work for both mono-repo and multi-repo architectures. ## Control Plane @@ -53,11 +53,11 @@ Flipt Cloud supports evaluation for our [client-side SDKs](/integration/client) [Server-side SDKs](/integration/server) including [OpenFeature SDKs](/integration/openfeature) are also supported but currently require you to run your own Flipt instances. @@ -72,11 +72,11 @@ To scale evaluation requests and serve feature flag evaluations via our server-s ### Client-Side Evaluation @@ -85,11 +85,11 @@ You can also run your own Flipt Open Source instances and configure our client-s For more information on how to deploy Flipt Open Source and how to configure it to source flag data from your Git repository, please refer to the [Moving to Production](/cloud/guides/production) guide. diff --git a/cloud/features/custom-domains.mdx b/cloud/features/custom-domains.mdx index de3b7292..7492a99e 100644 --- a/cloud/features/custom-domains.mdx +++ b/cloud/features/custom-domains.mdx @@ -17,11 +17,11 @@ This is useful if you want to use a domain (or subdomain) that you already own i diff --git a/docs.json b/docs.json index f6c328f2..c83aa86c 100644 --- a/docs.json +++ b/docs.json @@ -9,197 +9,326 @@ }, "favicon": "/favicon.svg", "navigation": { - "anchors": [ + "versions": [ { - "anchor": "Open Source", - "icon": "book-open", + "version": "v1", "tabs": [ { "tab": "Open Source", - "groups": [ - { - "group": "Overview", - "pages": ["introduction", "concepts"] - }, - { - "group": "Use Cases", - "pages": [ - "usecases/overview", - "usecases/cloudnative", - "usecases/edge", - "usecases/gitops" - ] - }, + "anchors": [ { - "group": "Installation", - "pages": [ - "installation/overview", - "installation/docker", - "installation/kubernetes" - ] - }, - { - "group": "Integration", - "pages": [ - "integration/overview", + "anchor": "Documentation", + "icon": "book-open", + "groups": [ { - "group": "Server-Side SDKs", + "group": "Overview", + "pages": ["introduction", "concepts"] + }, + { + "group": "Use Cases", "pages": [ - "integration/server/rest", - "integration/server/grpc" + "usecases/overview", + "usecases/cloudnative", + "usecases/edge", + "usecases/gitops" ] }, - "integration/client", - "integration/openfeature", - "integration/examples" - ] - }, - { - "group": "Guides", - "pages": [ { - "group": "User Guides", + "group": "Installation", "pages": [ - "guides/user/get-going-with-gitops", - "guides/user/using-references" + "installation/overview", + "installation/docker", + "installation/kubernetes" + ] + }, + { + "group": "Integration", + "pages": [ + "integration/overview", + { + "group": "Server-Side SDKs", + "pages": [ + "integration/server/rest", + "integration/server/grpc" + ] + }, + "integration/client", + "integration/openfeature", + "integration/examples" ] }, { - "group": "Operations Guides", + "group": "Guides", "pages": [ { - "group": "Deployment", + "group": "User Guides", "pages": [ - "guides/operation/deployment/deploy-to-flyio", - "guides/operation/deployment/deploy-to-kubernetes" + "guides/user/get-going-with-gitops", + "guides/user/using-references" ] }, { - "group": "Authentication", + "group": "Operations Guides", "pages": [ - "guides/operation/authentication/login-with-google", - "guides/operation/authentication/login-with-github", - "guides/operation/authentication/login-with-keycloak" + { + "group": "Deployment", + "pages": [ + "guides/operation/deployment/deploy-to-flyio", + "guides/operation/deployment/deploy-to-kubernetes" + ] + }, + { + "group": "Authentication", + "pages": [ + "guides/operation/authentication/login-with-google", + "guides/operation/authentication/login-with-github", + "guides/operation/authentication/login-with-keycloak" + ] + }, + { + "group": "Authorization", + "pages": [ + "guides/operation/authorization/rbac-with-keycloak" + ] + } ] }, { - "group": "Authorization", + "group": "Migration Guides", "pages": [ - "guides/operation/authorization/rbac-with-keycloak" + "guides/migration/launchdarkly/overview", + "guides/migration/launchdarkly/openfeature", + "guides/migration/launchdarkly/flipt" ] } ] }, { - "group": "Migration Guides", + "group": "Configuration", + "pages": [ + "configuration/overview", + "configuration/analytics", + { + "group": "Auditing", + "pages": [ + "configuration/auditing/overview", + "configuration/auditing/webhooks" + ] + }, + "configuration/authentication", + "configuration/authorization", + "configuration/observability", + "configuration/storage", + "configuration/caching", + "configuration/telemetry", + "configuration/experimental" + ] + }, + { + "group": "CLI", + "pages": [ + "cli/overview", + { + "group": "Commands", + "pages": [ + { + "group": "config", + "pages": [ + "cli/commands/config/init", + "cli/commands/config/edit" + ] + }, + { + "group": "bundle", + "pages": [ + "cli/commands/bundle/build", + "cli/commands/bundle/list", + "cli/commands/bundle/pull", + "cli/commands/bundle/push" + ] + }, + "cli/commands/evaluate", + "cli/commands/export", + "cli/commands/import", + "cli/commands/migrate", + "cli/commands/validate" + ] + } + ] + }, + { + "group": "Authentication", + "pages": [ + "authentication/overview", + "authentication/methods", + "authentication/using-tokens", + "authentication/using-jwts" + ] + }, + { + "group": "Authorization", + "pages": ["authorization/overview"] + }, + { + "group": "Operations", + "pages": [ + "operations/architecture", + "operations/deployment", + "operations/import-export", + "operations/production", + "operations/upgrading" + ] + }, + { + "group": "Tooling", "pages": [ - "guides/migration/launchdarkly/overview", - "guides/migration/launchdarkly/openfeature", - "guides/migration/launchdarkly/flipt" + "tooling/github-actions", + "tooling/model-context-protocol" ] } ] }, { - "group": "Configuration", - "pages": [ - "configuration/overview", - "configuration/analytics", + "anchor": "API Reference", + "icon": "code", + "groups": [ + { + "group": "Overview", + "pages": ["reference/overview"] + }, { - "group": "Auditing", + "group": "Authentication", "pages": [ - "configuration/auditing/overview", - "configuration/auditing/webhooks" + "reference/authentication/list-tokens", + "reference/authentication/get-token", + "reference/authentication/delete-token", + "reference/authentication/create-token", + "reference/authentication/get-self", + "reference/authentication/expire-self" ] }, - "configuration/authentication", - "configuration/authorization", - "configuration/observability", - "configuration/storage", - "configuration/caching", - "configuration/telemetry", - "configuration/experimental" - ] - }, - { - "group": "CLI", - "pages": [ - "cli/overview", { - "group": "Commands", + "group": "Evaluation", "pages": [ - { - "group": "config", - "pages": [ - "cli/commands/config/init", - "cli/commands/config/edit" - ] - }, - { - "group": "bundle", - "pages": [ - "cli/commands/bundle/build", - "cli/commands/bundle/list", - "cli/commands/bundle/pull", - "cli/commands/bundle/push" - ] - }, - "cli/commands/evaluate", - "cli/commands/export", - "cli/commands/import", - "cli/commands/migrate", - "cli/commands/validate" + "reference/evaluation/boolean-evaluation", + "reference/evaluation/variant-evaluation", + "reference/evaluation/batch-evaluation" + ] + }, + { + "group": "OpenFeature Evaluation", + "pages": [ + "reference/openfeature/overview", + "reference/openfeature/configuration", + "reference/openfeature/flag-evaluation", + "reference/openfeature/bulk-evaluation" + ] + }, + { + "group": "Namespaces", + "pages": [ + "reference/namespaces/list-namespaces", + "reference/namespaces/create-namespace", + "reference/namespaces/get-namespace", + "reference/namespaces/delete-namespace", + "reference/namespaces/update-namespace" + ] + }, + { + "group": "Flags", + "pages": [ + "reference/flags/list-flags", + "reference/flags/create-flag", + "reference/flags/get-flag", + "reference/flags/delete-flag", + "reference/flags/update-flag" + ] + }, + { + "group": "Variants", + "pages": [ + "reference/variants/create-variant", + "reference/variants/delete-variant", + "reference/variants/update-variant" + ] + }, + { + "group": "Segments", + "pages": [ + "reference/segments/list-segment", + "reference/segments/create-segment", + "reference/segments/get-segment", + "reference/segments/delete-segment", + "reference/segments/update-segment" + ] + }, + { + "group": "Constraints", + "pages": [ + "reference/constraints/create-constraint", + "reference/constraints/delete-constraint", + "reference/constraints/update-constraint" + ] + }, + { + "group": "Rollouts", + "pages": [ + "reference/rollouts/list-rollouts", + "reference/rollouts/create-rollout", + "reference/rollouts/order-rollouts", + "reference/rollouts/get-rollout", + "reference/rollouts/delete-rollout", + "reference/rollouts/update-rollout" + ] + }, + { + "group": "Rules", + "pages": [ + "reference/rules/list-rules", + "reference/rules/create-rule", + "reference/rules/order-rules", + "reference/rules/get-rule", + "reference/rules/delete-rule", + "reference/rules/update-rule" + ] + }, + { + "group": "Distributions", + "pages": [ + "reference/distributions/create-distribution", + "reference/distributions/delete-distribution", + "reference/distributions/update-distribution" ] } ] }, { - "group": "Authentication", - "pages": [ - "authentication/overview", - "authentication/methods", - "authentication/using-tokens", - "authentication/using-jwts" - ] + "anchor": "Changelog", + "icon": "clock", + "pages": ["changelog/overview"] }, { - "group": "Authorization", - "pages": ["authorization/overview"] + "anchor": "Blog", + "href": "https://blog.flipt.io", + "icon": "newspaper" }, { - "group": "Operations", - "pages": [ - "operations/architecture", - "operations/deployment", - "operations/import-export", - "operations/production", - "operations/upgrading" - ] + "anchor": "Community", + "href": "https://community.flipt.io", + "icon": "discourse" }, { - "group": "Tooling", - "pages": [ - "tooling/github-actions", - "tooling/model-context-protocol" - ] - } - ] - }, - { - "tab": "Changelog", - "groups": [ + "anchor": "Discord", + "href": "https://flipt.io/discord", + "icon": "discord" + }, { - "group": "Changelog", - "pages": ["changelog/overview"] + "anchor": "GitHub", + "href": "https://git.new/flipt", + "icon": "github" } ] - } - ] - }, - { - "anchor": "Flipt Cloud", - "icon": "cloud", - "tabs": [ + }, { "tab": "Flipt Cloud", "groups": [ @@ -237,143 +366,94 @@ ] }, { - "anchor": "API Reference", - "icon": "code", + "version": "v2", "tabs": [ { - "tab": "API Reference", - "groups": [ - { - "group": "Overview", - "pages": ["reference/overview"] - }, - { - "group": "Authentication", - "pages": [ - "reference/authentication/list-tokens", - "reference/authentication/get-token", - "reference/authentication/delete-token", - "reference/authentication/create-token", - "reference/authentication/get-self", - "reference/authentication/expire-self" - ] - }, - { - "group": "Evaluation", - "pages": [ - "reference/evaluation/boolean-evaluation", - "reference/evaluation/variant-evaluation", - "reference/evaluation/batch-evaluation" - ] - }, - { - "group": "OpenFeature Evaluation", - "pages": [ - "reference/openfeature/overview", - "reference/openfeature/configuration", - "reference/openfeature/flag-evaluation", - "reference/openfeature/bulk-evaluation" - ] - }, + "tab": "Open Source", + "icon": "book-open", + "anchors": [ { - "group": "Namespaces", - "pages": [ - "reference/namespaces/list-namespaces", - "reference/namespaces/create-namespace", - "reference/namespaces/get-namespace", - "reference/namespaces/delete-namespace", - "reference/namespaces/update-namespace" + "anchor": "Documentation", + "groups": [ + { + "group": "Overview", + "pages": [ + "/v2/introduction", + "/v2/quickstart", + "/v2/concepts" + ] + }, + { + "group": "Configuration", + "pages": [ + "v2/configuration/overview", + "v2/configuration/environments", + "v2/configuration/storage", + "v2/configuration/authentication", + "v2/configuration/authorization", + "v2/configuration/observability", + "v2/configuration/telemetry" + ] + } ] }, { - "group": "Flags", - "pages": [ - "reference/flags/list-flags", - "reference/flags/create-flag", - "reference/flags/get-flag", - "reference/flags/delete-flag", - "reference/flags/update-flag" - ] + "anchor": "Blog", + "href": "https://blog.flipt.io", + "icon": "newspaper" }, { - "group": "Variants", - "pages": [ - "reference/variants/create-variant", - "reference/variants/delete-variant", - "reference/variants/update-variant" - ] + "anchor": "Community", + "href": "https://community.flipt.io", + "icon": "discourse" }, { - "group": "Segments", - "pages": [ - "reference/segments/list-segment", - "reference/segments/create-segment", - "reference/segments/get-segment", - "reference/segments/delete-segment", - "reference/segments/update-segment" - ] + "anchor": "Discord", + "href": "https://flipt.io/discord", + "icon": "discord" }, { - "group": "Constraints", - "pages": [ - "reference/constraints/create-constraint", - "reference/constraints/delete-constraint", - "reference/constraints/update-constraint" - ] - }, + "anchor": "GitHub", + "href": "https://git.new/flipt", + "icon": "github" + } + ] + }, + { + "tab": "Flipt Cloud", + "groups": [ { - "group": "Rollouts", + "group": "Overview", "pages": [ - "reference/rollouts/list-rollouts", - "reference/rollouts/create-rollout", - "reference/rollouts/order-rollouts", - "reference/rollouts/get-rollout", - "reference/rollouts/delete-rollout", - "reference/rollouts/update-rollout" + "cloud/overview", + "cloud/benefits", + "cloud/concepts", + "cloud/architecture" ] }, { - "group": "Rules", + "group": "Features", "pages": [ - "reference/rules/list-rules", - "reference/rules/create-rule", - "reference/rules/order-rules", - "reference/rules/get-rule", - "reference/rules/delete-rule", - "reference/rules/update-rule" + "cloud/features/authentication", + "cloud/features/git-backed-storage", + "cloud/features/approval-workflows", + "cloud/features/rbac", + "cloud/features/user-management", + "cloud/features/verified-commits", + "cloud/features/custom-domains" ] }, { - "group": "Distributions", + "group": "Guides", "pages": [ - "reference/distributions/create-distribution", - "reference/distributions/delete-distribution", - "reference/distributions/update-distribution" + "cloud/guides/getting-started", + "cloud/guides/production", + "cloud/guides/configuring-environments" ] } ] } ] - }, - { - "anchor": "Blog", - "href": "https://blog.flipt.io", - "icon": "newspaper" - }, - { - "anchor": "Community", - "href": "https://community.flipt.io", - "icon": "discourse" - }, - { - "anchor": "Discord", - "href": "https://flipt.io/discord", - "icon": "discord" - }, - { - "anchor": "GitHub", - "href": "https://git.new/flipt", - "icon": "github" } ] }, @@ -424,56 +504,12 @@ }, "redirects": [ { - "source": "/experimental/filesystem-backends", - "destination": "/configuration/storage" - }, - { - "source": "/self-hosted", - "destination": "/installation" - }, - { - "source": "/self-hosted/overview", - "destination": "/installation/overview" - }, - { - "source": "/self-hosted/docker", - "destination": "/installation/docker" - }, - { - "source": "/self-hosted/kubernetes", - "destination": "/installation/kubernetes" - }, - { - "source": "/integration/rest", - "destination": "/integration/server/rest" - }, - { - "source": "/integration/grpc", - "destination": "/integration/server/grpc" - }, - { - "source": "/guides/get-going-with-gitops", - "destination": "/guides/user/get-going-with-gitops" - }, - { - "source": "/guides/using-references", - "destination": "/guides/user/using-references" - }, - { - "source": "/guides/deploy-to-flyio", - "destination": "/guides/operation/deployment/deploy-to-flyio" - }, - { - "source": "/guides/deploy-to-kubernetes", - "destination": "/guides/operation/deployment/deploy-to-kubernetes" - }, - { - "source": "/guides/login-with-google", - "destination": "/guides/operation/authentication/login-with-google" + "source": "/self-hosted/:slug*", + "destination": "/installation/:slug*" }, { - "source": "/guides/login-with-github", - "destination": "/guides/operation/authentication/login-with-github" + "source": "/integration/:slug*", + "destination": "/integration/server/:slug*" } ] } diff --git a/introduction.mdx b/introduction.mdx index d22601ba..b89181d2 100644 --- a/introduction.mdx +++ b/introduction.mdx @@ -10,14 +10,9 @@ simulate an evaluation request from your applications. For more information on any of the concepts described, please see the [Concepts](/concepts) documentation. - - Flipt Cloud is a fully managed feature management platform that - enables you to continue to use Flipt's feature management capabilities with - zero maintenance. +import Cloud from "/snippets/cloud.mdx"; -Own your feature data, backed by Git. - - + ## Setup diff --git a/snippets/cloud.mdx b/snippets/cloud.mdx new file mode 100644 index 00000000..b77a6eda --- /dev/null +++ b/snippets/cloud.mdx @@ -0,0 +1,8 @@ + + Flipt Cloud is a fully managed feature management platform that + enables you to continue to use Flipt's feature management capabilities with + zero maintenance. + +Own your feature data, backed by Git. + + diff --git a/snippets/v2-alpha.mdx b/snippets/v2-alpha.mdx new file mode 100644 index 00000000..a8be0682 --- /dev/null +++ b/snippets/v2-alpha.mdx @@ -0,0 +1,7 @@ + + Flipt v2 is currently in alpha and is not recommended for production use. + +These docs are a work in progress and incomplete. We are working hard to +improve the docs and make Flipt v2 available for production use. + + diff --git a/v2/concepts.mdx b/v2/concepts.mdx index 11db97cc..c6661478 100644 --- a/v2/concepts.mdx +++ b/v2/concepts.mdx @@ -3,6 +3,10 @@ title: Concepts description: This document describes the basic concepts of Flipt v2. --- +import V2Alpha from "/snippets/v2-alpha.mdx"; + + + More information on how to use Flipt is noted in the [Quickstart](/v2/quickstart) documentation. ## Environments @@ -11,6 +15,8 @@ Environments are a new concept in Flipt v2. They are a way to organize your name By default, Flipt v2 will create a single environment called `default` along with the `default` namespace. +-- TODO add screenshot + Environments are managed via configuration files as they are also coupled to how you store your configuration data. See the [Environments](/v2/configuration#environments) documentation for more. @@ -24,7 +30,7 @@ If an environment isn't selected then the 'Default' environment is used. Namespaces are a way to organize your feature flags and configurations within an environment. -![Namespaces Settings](/images/concepts/namespaces_production.png) +-- TODO add screenshot One common use-case of Namespaces is to separate Flipt data by internal team. @@ -35,11 +41,11 @@ If a namespace isn't selected then the 'Default' namespace is used. -![Namespaces Settings](/images/concepts/namespaces_default.png) +-- TODO add screenshot Namespaces can be managed within the `Settings` section of the Flipt UI: -![Namespaces Settings](/images/concepts/settings_namespaces.png) +-- TODO add screenshot ## Flags @@ -54,7 +60,7 @@ working on when they visit your homepage. Flags can be used as simple on/off toggles or with variants and rules to support more elaborate use cases. -![Flags Example](/images/concepts/flags.png) +-- TODO add screenshot There are two types of flags: @@ -80,7 +86,7 @@ The attachment size is limited to **1MB**. -![Variant Flags Example](/images/concepts/flags_variants.png) +-- TODO add screenshot ### Boolean Flags @@ -90,7 +96,7 @@ You can use boolean flags to determine if a feature is enabled or disabled for a Boolean flags can be configured with [rollout](#rollouts) rules to determine which entities receive `true` or `false` for a given flag. -![Boolean Flags Example](/images/concepts/flags_boolean.png) +-- TODO add screenshot ### Metadata @@ -105,7 +111,7 @@ Currently, the following data types are supported: - Primitive types: `String`, `Number`, `Boolean` - Complex types: `Array`, `Object` -![Flag Metadata Example](/images/concepts/flags_metadata.png) +-- TODO add screenshot ## Segments @@ -115,7 +121,7 @@ a flag or variant applies to them. An example segment could be `new-users`. -![Segments Example](/images/concepts/segments.png) +-- TODO add screenshot Segments are global within a Flipt namespace. @@ -135,7 +141,7 @@ Constraints allow you to determine which segment a given entity is a part of. For example, for a user to fall into the above `new-users` segment, you may want to check their `finished_onboarding` property. -![Constraints Example](/images/concepts/constraints.png) +-- TODO add screenshot All constraints have a _property_, _type_, _operator_ and optionally a _value_. @@ -149,7 +155,7 @@ Currently 5 constraint types are available: - **DateTime** which allows you to check a date or datetime property of an entity such as `2020-01-01` or `2020-01-01T00:00:00Z` ([RFC3339](https://datatracker.ietf.org/doc/html/rfc3339)) - **Entity** which allows you to check the `entityId` that was sent in the body of the `Variant` or `Boolean` request -![Constraint Types](/images/concepts/constraints_types.png) +-- TODO add screenshot The constraint value is represented as a string in transit and in the @@ -167,7 +173,7 @@ richer by using distribution logic to roll out features on a percentage basis. Continuing our previous example, we may want to return the flag variant `dark` for all entities in the `new-users` segment. This would be configured like so: -![Rules Example](/images/concepts/rules.png) +-- TODO add screenshot Rules are evaluated in order per their rank from 1-N. The first rule that matches wins. Once created, rules can be re-ordered to change how they're @@ -179,7 +185,7 @@ evaluated. If no rules match for a given flag, the default rule value is returned. This value is optional and can be set to any variant that exists for the flag. -![Default Rule Example](/images/concepts/default_rule.png) +-- TODO add screenshot ### Distributions @@ -190,7 +196,7 @@ Let's say that instead of always showing the `dark` variant to your `new-users` segment, you want to show `dark` to **10%** of `new-users`, `light` to **30%**, and `auto` to the remaining **60%**. You would accomplish this using rules with distributions: -![Distributions Example](/images/concepts/distributions.png) +-- TODO add screenshot The ability to manage distributions, as illustrated in the image above, is an extremely powerful feature of Flipt that can help you seamlessly deploy new features of your applications to your users while also limiting the reach of potential bugs. @@ -205,7 +211,7 @@ Current rollout types include: - **Threshold** which allows you to return `true` or `false` for a given percentage of entities. - **Segments Match** which allows you to return `true` or `false` if an entity matches a given segment. -![Rollouts Example](/images/concepts/rollouts.png) +-- TODO add screenshot Rollouts work similar to [Rules](#rules) in that they're evaluated in order per their rank from 1-N. The first rollout that matches wins. Once created, rollouts can be re-ordered to change how they're evaluated. @@ -223,7 +229,7 @@ In the above example involving colors, evaluation is where you send information about your current user to determine if they're a `new-user`, and which color (`dark`, `auto`, or `light`) that they should see for their main color scheme. -![Evaluation Example](/images/concepts/evaluation.png) +-- TODO add screenshot ### Entities diff --git a/v2/configuration/authentication.mdx b/v2/configuration/authentication.mdx index e9782da7..ca2a754f 100644 --- a/v2/configuration/authentication.mdx +++ b/v2/configuration/authentication.mdx @@ -3,8 +3,6 @@ title: Authentication description: This document describes how to configure the authentication mechanisms for Flipt v2. --- - - Flipt supports the ability to secure its core API routes by setting the `required` field to `true` on the `authentication` configuration object. ```yaml config.yaml @@ -21,8 +19,6 @@ The UI will require a session-compatible authentication method (e.g. [OIDC](#met -See the [Authentication: Overview](/v2/authentication/overview) documentation for more details on Flipt's API authentication handling. - ## Exclusions Exclusions allow you to disable authentication for sections of the API. @@ -146,7 +142,6 @@ The grace period is added onto this timestamp as a predicate when the delete ope Tokens that have expired (`expires_at` is before `now()`) will begin immediately failing authentication when presented as a credential to the API. The `grace_period` is simply for the cleanup process. - ## Methods Each key within the `methods` section is a particular authentication method. @@ -175,8 +170,6 @@ authentication: some_key: "some_value" ``` -Further explanation for using this method can be found in the [Authentication: Static Token](/v2/authentication/methods#static-token) documentation. - ### OIDC The `OIDC` method is a `session compatible` authentication method. @@ -205,7 +198,7 @@ authentication: Multiple providers can be configured simultaneously. Each provider will result in a login option being presented in the UI, along with a configured endpoint to support the provider flow. -!["OIDC Login"](/v2/images/configuration/oidc_login.png) +-- TODO: add screenshot Flipt v2 has been tested with each of the following providers: @@ -352,7 +345,7 @@ authentication: - user:email ``` -!["GitHub Login"](/v2/images/guides/login-with-github/login-with-github.png) +-- TODO: add screenshot #### Allowed Organizations @@ -534,4 +527,3 @@ authentication: subject: user@domain.com audiences: https://flipt.io/, https://flipt.com/ # at least one audience must match ``` - diff --git a/v2/configuration/authorization.mdx b/v2/configuration/authorization.mdx index e4da3335..a75a068f 100644 --- a/v2/configuration/authorization.mdx +++ b/v2/configuration/authorization.mdx @@ -1,6 +1,6 @@ --- title: Authorization -description: This document describes how to configure Flipt v2's authorization mechanisms. +description: This document describes how to configure the authorization mechanisms for Flipt v2. --- Flipt supports the ability to secure its core API routes by setting the `required` field to `true` on the `authorization` configuration object. @@ -15,12 +15,10 @@ When authorization is set to `required`, the API will ensure valid credentials a Once authorization has been set to `required: true` all management API routes will require a valid authentication session as well. -The UI will require a session-compatible authentication method (e.g. [OIDC](/v2/authentication/methods#openid-connect)) to be enabled. +The UI will require a session-compatible authentication method (e.g. OIDC) to be enabled. -See the [Authorization: Overview](/v2/authorization/overview) documentation for more details on Flipt's API authorization handling. - ## Backends Flipt uses [Open Policy Agent (OPA)](https://www.openpolicyagent.org/) to enforce authorization policies. OPA is a general-purpose policy engine that can be used to enforce policies across the stack. @@ -50,11 +48,9 @@ authorization: The policy **must** have the following package declaration: ```rego policy.rego -package flipt.authz.v1 +package flipt.authz.v2 ``` -You can learn more about policies in our [Authorization: Overview](/v2/authorization/overview#policies) documentation. - #### Polling Interval Flipt will poll the policy file for changes at a regular interval. By default, Flipt will poll the policy file every 5 minutes. You can adjust this interval by setting the `poll_interval` field in the `policy` object. @@ -84,8 +80,6 @@ authorization: path: "data.json" ``` -You can learn more about using data with policies in our [Authorization: Overview](/authorization/overview#external-data) documentation. - #### Polling Interval Like policies, Flipt will poll data files for changes at a regular interval. By default, Flipt will poll the data file every 30 seconds. You can adjust this interval by setting the `poll_interval` field in the `data` object. diff --git a/v2/configuration/environments.mdx b/v2/configuration/environments.mdx new file mode 100644 index 00000000..bb78c327 --- /dev/null +++ b/v2/configuration/environments.mdx @@ -0,0 +1,87 @@ +--- +title: Environments +description: This document describes how environments are configured for Flipt v2. +--- + +Flipt v2 supports the ability to configure multiple environments, allowing the user to switch between them in the UI as well as at evaluation time. + +Environments are unique to other Flipt resources in that they are not created or managed via the Flipt API or UI. Instead, they are defined in the Flipt server configuration file as they are tightly coupled to the [storage configuration](/v2/configuration/storage). + +## Identifiers + +Each environment has an identifier that is used to reference the environment in the configuration and in the UI/API and is used to determine the environment that will be used when evaluating flags. + +Identifiers can be any string value but must be unique. Flipt creates a `default` identifier and environment for you automatically if you don't specify one. + +```yaml +environments: + local: # id + name: "local" + default: true + + staging: # id + name: "staging" + storage: "staging" +``` + +## Storage + +Each environment has a storage configuration field that is used to determine the storage backend that will be used for the environment. + +The storage configuration is a reference to the [storage backend](/v2/configuration/storage) that will be used for the environment. + +```yaml +environments: + local: + storage: "local" +``` + +In the above configuration, the `local` environment will use the `local` storage backend as defined in the [storage configuration](/v2/configuration/storage). + + +This mapping between environments and storage backends means that multiple environments can share the same storage backend. + +For example you could have all environments share the same storage which syncs to a single git repository. + + + + + + +### Directories + +Each environment has an optional `directory` configuration field that is used to determine the directory that will be used to store the environment's resources. + +This is only required if multiple environments share the same storage backend, as Flipt needs to know where to ultimately store the state without conflicting with other environments. + +```yaml +environments: + foo: + directory: "foo" + storage: "local" + bar: + directory: "bar" + storage: "local" +``` + +In the above configuration, the `foo` and `bar` environments will use the same `local` storage backend but will store their resources in different directories. + +## Default + +Each environment has a default configuration field that is used to determine if the environment is the default environment. + +The default environment is the environment that will be used when no other environment is specified. + +```yaml +environments: + local: + default: true +``` + +This means that if no environment is specified when performing actions such as flag evaluation, creation, or updates, the `local` environment will be used. This will also be the environment that is selected in the UI by default. diff --git a/v2/configuration/observability.mdx b/v2/configuration/observability.mdx index ce4bbdca..ef3ad246 100644 --- a/v2/configuration/observability.mdx +++ b/v2/configuration/observability.mdx @@ -1,6 +1,6 @@ --- title: Observability -description: This document describes how to configure Flipt's observability mechanisms including metrics, logging, and tracing. +description: This document describes how to configure observability mechanisms including metrics, logging, and tracing for Flipt v2. --- ## Metrics @@ -104,6 +104,27 @@ For production deployments, we recommend using the JSON format as it's easier to More information about the available configuration options can be found in the [Logging configuration](/configuration/overview#logging) section. +### OTLP + +Flipt v2 supports the new [OpenTelemetry OTLP logging specification](https://opentelemetry.io/docs/specs/otel/logs/). To enable OTLP logging, set the `OTLP_LOGS_EXPORTER` environment variable + +```console +export OTLP_LOGS_EXPORTER=otlp +``` + + + OpenTelemetry logging is in addition to the existing logging configuration. It + does not replace the ability to log to a file or stdout/stderr. + + +OpenTelemetry OTLP logging is configured via the default OpenTelemetry Environment Variables. See the [OpenTelemetry Environment Variables](https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/) documentation for more details. + +For example, to configure the OTLP logging endpoint, you can set the `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` environment variable. + +```console +export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://localhost:4317 +``` + ## Tracing Flipt supports distributed tracing via the [OpenTelemetry](https://opentelemetry.io/) project using the [OTLP](https://opentelemetry.io/docs/reference/specification/protocol/) protocol. diff --git a/v2/configuration/overview.mdx b/v2/configuration/overview.mdx index ac82fa38..ee7448cb 100644 --- a/v2/configuration/overview.mdx +++ b/v2/configuration/overview.mdx @@ -4,8 +4,6 @@ description: This document describes how to configure the Flipt v2 server. mode: "wide" --- -Flipt v2 server can be configured in two ways. - Configuration precedence is as follows: 1. [Environment Variables](#environment-variables) @@ -95,8 +93,7 @@ Environment variables **MUST** have `FLIPT_` prefix and be in `UPPER_SNAKE_CASE` Using environment variables to override defaults is especially helpful when - running with Docker as described in the [Docker](/v2/installation/docker) - documentation. + running with Docker. Keys should be uppercase and `.` should be replaced by `_`. For example, diff --git a/v2/configuration/storage.mdx b/v2/configuration/storage.mdx index 2550d85b..a5f3449d 100644 --- a/v2/configuration/storage.mdx +++ b/v2/configuration/storage.mdx @@ -1,6 +1,6 @@ --- title: Storage -description: This document describes how to configure Flipt v2's storage backend mechanisms. +description: This document describes how to configure the storage backend mechanisms for Flipt v2. --- Flipt v2 stores all of its resources in git repositories. This section describes how those git repositories are persisted and managed. @@ -9,22 +9,22 @@ Flipt v2 stores all of its resources in git repositories. This section describes Each storage backend has an identifier that is used to reference the storage backend in the configuration, such as when specifying the storage backend for an environment. -Identifiers can be any string value but must be unique. Flipt creates a `default` identifier for you automatically if you don't specify one. +Identifiers can be any string value but must be unique. Flipt creates a `default` identifier and storage backend for you automatically if you don't specify one. In the following example, we've defined two storage backends: -- `foo` is a local storage backend that will serve Flipt flag state from a local directory. -- `bar` is a memory storage backend that will serve Flipt flag state from an in-memory store. +- `staging` is a local storage backend that will serve Flipt flag state from a local directory. +- `development` is a memory storage backend that will serve Flipt flag state from an in-memory store. ```yaml storage: - foo: - name: "foo" + staging: # id + name: "staging" backend: type: local - path: "/path/to/foo/repository" - bar: - name: "bar" + path: "/path/to/staging/repository" + development: # id + name: "development" backend: type: memory ``` @@ -73,15 +73,16 @@ Flipt v2 supports syncing flag state to and from a remote git repository. ```yaml storage: - backend: - type: memory - remote: "https://github.com/flipt-io/example.git" - branch: "main" - poll_interval: "30s" - credentials: "github" + staging: + backend: + type: memory + remote: "https://github.com/flipt-io/example.git" + branch: "main" + poll_interval: "30s" + credentials: "github" ``` -This configuration will create a git storage backend with the identifier `default` in memory and will sync flag state to and from the remote repository. +This configuration will create a git storage backend with the identifier `staging` in memory and will sync flag state to and from the remote repository. ### Conflict Resolution @@ -97,7 +98,7 @@ When syncing flag state to and from a remote repository, Flipt will behave as fo ### Credentials -Credentials enable the ability to authenticate with the remote repository. +Credentials enable the ability to authenticate with remote repositories. Supported authentication schemes are: @@ -112,6 +113,15 @@ Credentials are configured using the `credentials` configuration section and use if needed. + + + #### Basic Basic authentication is a username and password pair. diff --git a/v2/configuration/telemetry.mdx b/v2/configuration/telemetry.mdx index bbc6a98c..dc4305be 100644 --- a/v2/configuration/telemetry.mdx +++ b/v2/configuration/telemetry.mdx @@ -1,10 +1,8 @@ --- title: Telemetry -description: This document describes how to configure Flipt v2's telemetry outputs as well as what data is captured. +description: This document describes how to configure telemetry outputs as well as what data is captured for Flipt v2. --- -## Telemetry - Flipt developers rely on anonymous usage data to help prioritize new features and improve the product. The information collected is completely anonymous, never shared with external entities, and you can opt-out at any time. diff --git a/v2/images/concepts/environments.png b/v2/images/concepts/environments.png new file mode 100644 index 0000000000000000000000000000000000000000..1269acee631b595dd4bfdbf3396884099f121dce GIT binary patch literal 200454 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∾Hos2LIcBd%^3sOsXPA4W#{V>$1fL! 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

tb;tlEbV?XF@(1PhJy(2T53h+A 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 S&DtH#00f?{elF{r5}E)_`$=#B literal 0 HcmV?d00001 diff --git a/v2/images/configuration/environments/storage-dark.svg b/v2/images/configuration/environments/storage-dark.svg new file mode 100644 index 00000000..95cfc05d --- /dev/null +++ b/v2/images/configuration/environments/storage-dark.svg @@ -0,0 +1,182 @@ +Environment A(path: /env-a)Environment B(path: /env-b)Environment CFilesystem BackendIn-Memory BackendGitHub Repo AGitHub Repo B optional syncoptional sync + + + + + + + + + + + diff --git a/v2/images/configuration/environments/storage-light.svg b/v2/images/configuration/environments/storage-light.svg new file mode 100644 index 00000000..9a61d322 --- /dev/null +++ b/v2/images/configuration/environments/storage-light.svg @@ -0,0 +1,110 @@ +Environment A(path: /env-a)Environment B(path: /env-b)Environment CFilesystem BackendIn-Memory BackendGitHub Repo AGitHub Repo B optional syncoptional sync + + + + + + + + + + + diff --git a/v2/images/configuration/environments/storage.d2 b/v2/images/configuration/environments/storage.d2 new file mode 100644 index 00000000..694c7396 --- /dev/null +++ b/v2/images/configuration/environments/storage.d2 @@ -0,0 +1,65 @@ +vars: { + d2-config: { + layout-engine: elk + } +} + +direction: right + +style: { + fill: transparent +} + +classes: { + github: { + shape: image + icon: https://icons.terrastruct.com/dev%2Fgithub.svg + style.font-size: 24 + style.fill: transparent + style.stroke-width: 1 + } + box: { + style.fill: transparent + } + solid: { + style.stroke-width: 1 + } + dashed: { + style.stroke-width: 1 + style.stroke-dash: 5 + } +} + +E1: "Environment A\n(path: /env-a)" { + class: box +} +E2: "Environment B\n(path: /env-b)" { + class: box +} +E3: "Environment C" { + class: box +} + +FS: "Filesystem Backend" { + class: box +} +MEM: "In-Memory Backend" { + class: box +} + +GitFS: "GitHub Repo A" { + class: github +} + +GitMEM: "GitHub Repo B" { + class: github +} + +# Environment to Storage mappings +E1 -> FS { class: solid } +E2 -> FS { class: solid } +E3 -> MEM { class: solid } + +# Storage to Git remotes +FS <-> GitFS: "optional sync" { class: dashed } +MEM <-> GitMEM: "optional sync" { class: dashed } diff --git a/v2/images/configuration/storage/credentials-dark.svg b/v2/images/configuration/storage/credentials-dark.svg new file mode 100644 index 00000000..ceb8f05e --- /dev/null +++ b/v2/images/configuration/storage/credentials-dark.svg @@ -0,0 +1,171 @@ +Storage AStorage BGitHub Repo AGitHub Repo BGitHub Credentials + + + + + + + diff --git a/v2/images/configuration/storage/credentials-light.svg b/v2/images/configuration/storage/credentials-light.svg new file mode 100644 index 00000000..c479a7d2 --- /dev/null +++ b/v2/images/configuration/storage/credentials-light.svg @@ -0,0 +1,99 @@ +Storage AStorage BGitHub Repo AGitHub Repo BGitHub Credentials + + + + + + + diff --git a/v2/images/configuration/storage/credentials.d2 b/v2/images/configuration/storage/credentials.d2 new file mode 100644 index 00000000..8f517370 --- /dev/null +++ b/v2/images/configuration/storage/credentials.d2 @@ -0,0 +1,58 @@ +vars: { + d2-config: { + layout-engine: elk + } +} + +direction: right + +style: { + fill: transparent +} + +classes: { + github: { + shape: image + icon: https://icons.terrastruct.com/dev%2Fgithub.svg + style.font-size: 24 + style.fill: transparent + style.stroke-width: 1 + } + box: { + style.fill: transparent + } + solid: { + style.stroke-width: 1 + } + dashed: { + style.stroke-width: 1 + style.stroke-dash: 5 + } +} + +SA: "Storage A" { + class: box +} +SB: "Storage B" { + class: box +} + +GitA: "GitHub Repo A" { + class: github +} + +GitB: "GitHub Repo B" { + class: github +} + +Creds: "GitHub Credentials" { + class: box + near: center-right +} + +# Storage to Git remotes +SA <-> GitA { class: solid } +SB <-> GitB { class: solid } + +Creds -> GitA { class: solid } +Creds -> GitB { class: solid } diff --git a/v2/images/quickstart/default_environment.png b/v2/images/quickstart/default_environment.png new file mode 100644 index 0000000000000000000000000000000000000000..fcef34bfa3d6fbb04f55f2d07d8b28c10e722e93 GIT binary patch literal 186355 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�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 KUs3u__x}gp=(6?z literal 0 HcmV?d00001 diff --git a/v2/introduction.mdx b/v2/introduction.mdx index a5471cf9..012aa809 100644 --- a/v2/introduction.mdx +++ b/v2/introduction.mdx @@ -4,14 +4,14 @@ description: This document describes the features and benefits of Flipt v2. mode: "wide" --- +import V2Alpha from "/snippets/v2-alpha.mdx"; + + + Flipt v2 is a major new version of Flipt that is built to be Git-native and support a more flexible and powerful feature management platform. - - Flipt v2 is currently in beta and is not recommended for production use. - - -## Features +## Differences from v1 Flipt v2 introduces a number of new features and capabilities that are not available in v1 while maintaining backwards compatibility with v1. @@ -21,12 +21,20 @@ Flipt v2 is built to be Git-native, meaning that your feature flags and configur We modeled Flipt v2 after our [Flipt Cloud](/cloud/overview) product, but with the ability to self-host. +import Cloud from "/snippets/cloud.mdx"; + + + While Flipt v1 has the ability to read flag data from a Git repository, Flipt v2 takes this one step further by allowing you to write flag data to a Git repository using the Flipt v2 API and UI. We believe that Git is the best way to manage configuration data. We also believe that feature flags are a type of configuration data, and as such, they should be stored in the same way. By combining the power of Git with a user-friendly interface, Flipt v2 offers the best of both worlds: the robustness and version control of Git-backed storage, and the ease of use of a modern feature flag management system. +### Real-Time Client Updates (In Development) + +Flipt v2 introduces a new streaming API that allows you to subscribe to changes on the Flipt server and update the state of the flags accordingly in real-time. This means you'll be able to see changes to flags and configurations as they are made, without having to poll the Flipt server for updates. + ### Multi-Environment Flipt v2 introduces the concept of environments, which are an additional layer above Flipt v1's concept of [Namespaces](/concepts#namespace). diff --git a/v2/quickstart.mdx b/v2/quickstart.mdx index 26072fb5..e5230537 100644 --- a/v2/quickstart.mdx +++ b/v2/quickstart.mdx @@ -4,36 +4,30 @@ description: This document describes how to get started with Flipt v2. mode: "wide" --- -## Introduction +import V2Alpha from "/snippets/v2-alpha.mdx"; -This document will walk you through creating your first feature flag in Flipt v2. + ## Setup Before getting started, make sure the Flipt server is up and running on your -host on your chosen ports. See [Installation](/v2/installation) for more. +host on your chosen ports. - + + Our pre-release version is built nightly and only available as a Docker image at the moment. -```console Binary -curl -fsSL https://get.flipt.io/install/v2 | sh -``` +Once we release a stable version, we'll update the installation instructions to include binary, Helm, and Homebrew installation options. + + + + ```console Docker docker run -d \ -p 8080:8080 \ -p 9000:9000 \ -v $HOME/flipt:/var/opt/flipt \ - docker.flipt.io/flipt/flipt:v2 -``` - -```console Kubernetes/Helm -helm repo add flipt https://helm.flipt.io -helm install flipt flipt/flipt/v2 -``` - -```console Homebrew -brew install flipt-io/brew/flipt@v2 + docker.flipt.io/flipt/flipt:v2-nightly ``` @@ -46,7 +40,7 @@ Flipt v2 introduces the concept of environments in addition to namespaces. By default, Flipt v2 will create a single environment called `default` along with the `default` namespace. -// TODO: add screenshot of environments/namespace picker +-- TODO add screenshot Environments are managed via configuration files. See the [Environments](/v2/concepts#environments) documentation for more. @@ -67,7 +61,7 @@ To create a flag: 4. Click `Enabled` so the flag will be enabled once created. 5. Click `Create`. -!["Create Flag"](/images/getting_started/create_flag.png) +-- TODO add screenshot ### Create Variants @@ -81,7 +75,7 @@ To create a variant: 3. Click `Create`. 4. Create one more variant populating the information as you wish. -!["Create Variant"](/images/getting_started/create_variant.png) +-- TODO add screenshot Click `Flags` in the navigation menu and you should now see your newly created flag in the list. @@ -102,7 +96,7 @@ To create a segment: 3. Populate the details of the segment as shown. 4. Click `Create`. -!["Create Segment"](/images/getting_started/create_segment.png) +-- TODO add screenshot ### Create a Constraint @@ -120,7 +114,7 @@ To create a constraint: 2. Populate the details of the constraint as shown. 3. Click `Create`. -!["Create Constraint"](/images/getting_started/create_constraint.png) +-- TODO add screenshot Click `Segments` in the navigation menu and you should now see your newly created segment in the list. @@ -144,7 +138,7 @@ To create a rule: of `50%` each. 7. Click `Create`. -!["Create"](/images/getting_started/create_rule.png) +-- TODO add screenshot A distribution is a way of assigning a percentage for which entities evaluated get a specific variant. The higher the percentage assigned, the more likely it @@ -180,7 +174,7 @@ To test evaluation: segment that you created earlier, and return one of the variants defined. 6. Experiment with different values for the `Request Context` and `Entity ID` fields. -!["Evaluation Console"](/images/getting_started/evaluation_console.png) +-- TODO add screenshot That's it! You're now ready to integrate Flipt into your applications and start defining your flags and segments that will enable you to seamlessly rollout From df59abe037f2b169b364a3ccbdb7a670a538205b Mon Sep 17 00:00:00 2001 From: Mark Phelps <209477+markphelps@users.noreply.github.com> Date: Thu, 24 Apr 2025 21:01:31 -0400 Subject: [PATCH 5/5] chore: turn off no-unused-vars because it gives false positives with mdx Signed-off-by: Mark Phelps <209477+markphelps@users.noreply.github.com> --- .eslintrc.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.json b/.eslintrc.json index 050fcd04..e419209c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -10,6 +10,7 @@ }, "rules": { "no-undef": "off", + "no-unused-vars": "off", "no-unused-expressions": "off" } }