features

package module
v1.13.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README

Forge Features, a feature flag extension for Go with user targeting and percentage rollouts

Forge Features: feature flags for Go services

Forge Features is the feature flag extension for Forge, the Go backend framework. You define boolean, string, number and JSON flags in Go, target them at users by ID, email, country, group or any custom attribute, and roll a feature out to a fixed percentage of users with stable hashing, so the same user gets the same answer on every request. Flags are evaluated in process by the local provider. Settings for LaunchDarkly, Unleash, Flagsmith and PostHog exist in the config, but those providers aren't wired up yet: see Providers.

Go CI Go Reference Apache 2.0

Documentation · Quick start · Features · Evaluating flags · Targeting and rollouts · Providers · Configuration · FAQ

Quick start

You need Go 1.26 or later. Add Forge and the extension:

go get github.com/xraph/forge@latest
go get github.com/xraph/forge/extensions/features@latest

Save this as main.go. It defines two flags: a checkout switch that beta users always get and a quarter of everyone else gets, and a theme string that changes for one country.

package main

import (
	"log"
	"net/http"

	"github.com/xraph/forge"
	"github.com/xraph/forge/extensions/features"
)

func main() {
	app := forge.NewApp(forge.AppConfig{
		Name:        "flags-demo",
		HTTPAddress: ":8080",
		Extensions: []forge.Extension{
			features.NewExtension(
				features.WithLocalFlags(map[string]features.FlagConfig{
					"new-checkout": {
						Key:     "new-checkout",
						Type:    "boolean",
						Enabled: true,
						Targeting: []features.TargetingRule{
							{Attribute: "group", Operator: "in", Values: []string{"beta"}, Value: true},
						},
						Rollout: &features.RolloutConfig{Percentage: 25},
					},
					"checkout-theme": {
						Key:   "checkout-theme",
						Type:  "string",
						Value: "classic",
						Targeting: []features.TargetingRule{
							{Attribute: "country", Operator: "equals", Values: []string{"DE"}, Value: "compact"},
						},
					},
				}),
			),
		},
	})

	err := app.Router().GET("/checkout", func(ctx forge.Context) error {
		flags, err := features.Get(app.Container())
		if err != nil {
			return err
		}

		user := features.NewUserContext(ctx.QueryDefault("user", "anonymous")).
			WithCountry(ctx.Query("country"))
		if ctx.Query("beta") == "true" {
			user = user.WithGroups([]string{"beta"})
		}

		return ctx.JSON(http.StatusOK, map[string]any{
			"user":         user.UserID,
			"new_checkout": flags.IsEnabled(ctx.Context(), "new-checkout", user),
			"theme":        flags.GetString(ctx.Context(), "checkout-theme", user, "classic"),
		})
	})
	if err != nil {
		log.Fatal(err)
	}

	if err := app.Run(); err != nil {
		log.Fatal(err)
	}
}

Run it and ask as a few different users:

go mod tidy
go run .

curl "http://localhost:8080/checkout?user=alice"
# {"new_checkout":false,"theme":"classic","user":"alice"}
curl "http://localhost:8080/checkout?user=bob&beta=true&country=DE"
# {"new_checkout":true,"theme":"compact","user":"bob"}

Bob is in the beta group, so the targeting rule turns the checkout on for him, and his country picks the compact theme. Alice falls through to the 25% rollout, and her user ID hashes outside it. Try a dozen user IDs and roughly a quarter of them come back true. Ask again as Alice and you'll get the same answer every time.

Features

You need Forge Features gives you
On/off switches in code Boolean flags read with IsEnabled and IsEnabledWithDefault
Config values that change per user String, number and JSON flags through GetString, GetInt, GetFloat and GetJSON
A feature for specific people first Targeting rules on user_id, email, name, ip, country, group or any custom attribute, with equals, contains, in and not_in
A gradual rollout RolloutConfig with a percentage and a hashing attribute, stable per user
Safe behaviour when something is missing Every getter takes a default, and an evaluation error logs a warning and returns that default
Fallbacks without defining a full flag WithDefaultFlags for plain key-value defaults
One service your code can inject A *features.Service in the Vessel container, also registered as "features" and "features.Service"

Evaluating flags

Get the service from the container with features.Get(container), features.GetFromApp(app) or their Must versions, or take it as a constructor parameter:

type Checkout struct {
	flags *features.Service
}

func NewCheckout(flags *features.Service) *Checkout {
	return &Checkout{flags: flags}
}

// After forge.NewApp:
err := forge.Provide(app.Container(), NewCheckout)

Every evaluation takes a *features.UserContext. Build one with NewUserContext and chain whatever you know about the caller:

user := features.NewUserContext("user-42").
	WithEmail("ada@example.com").
	WithGroups([]string{"beta", "staff"}).
	WithAttribute("plan", "pro")

limit := flags.GetInt(ctx, "upload-limit-mb", user, 10)
ratio := flags.GetFloat(ctx, "sample-rate", user, 0.1)
layout := flags.GetJSON(ctx, "dashboard-layout", user, map[string]any{"columns": 2})

all, err := flags.GetAllFlags(ctx, user)

WithName, WithIP and WithCountry fill the other built-in fields. You can pass nil as the user context too, and then targeting and rollouts are skipped and you get the flag's base value.

Method Returns
IsEnabled(ctx, key, user) bool, false when the flag is unknown
IsEnabledWithDefault(ctx, key, user, def) bool, def when the flag is unknown
GetString(ctx, key, user, def) string
GetInt(ctx, key, user, def) int
GetFloat(ctx, key, user, def) float64
GetJSON(ctx, key, user, def) any
GetAllFlags(ctx, user) map[string]any of every defined flag, evaluated for that user
Refresh(ctx) re-reads flags from the provider (a no-op for the local provider)

Types are matched exactly. GetInt only returns a value you stored as a Go int and GetFloat only one you stored as a float64, so if you store 50 in a flag and then read it with GetFloat, the type assertion fails quietly and you get your default back with no warning in the logs.

Targeting and rollouts

For a defined flag, the local provider goes through these steps in order and stops at the first one that gives an answer:

  1. Each targeting rule, in the order you listed them. If a rule matches the user and its Value has the type you asked for, that value wins.
  2. For boolean flags with a Rollout, the user's bucket. A user inside the percentage gets Enabled, a user outside it gets the opposite.
  3. The flag's own value: Enabled for booleans, Value for everything else.

A flag you never defined falls back to WithDefaultFlags, then to the default you passed to the getter.

Rule attribute Matches against
user_id, email, name, ip, country The matching UserContext field
group Groups, and only with the in operator
anything else Attributes[name], when it holds a string
Operator True when
equals, in The attribute equals one of Values
not_in The attribute equals none of Values
contains The attribute contains one of Values as a substring (case-sensitive)

Rollouts hash the attribute named in RolloutConfig.Attribute (user_id when empty, or email, or a custom string attribute) with MD5 into one of 100 buckets. A user with an empty value for that attribute is always outside the rollout. Percentage of 0 or less puts nobody in, and 100 or more puts everybody in.

So a boolean flag with Enabled: true and Percentage: 25 is on for about a quarter of your users. Flip it to Enabled: false and the same quarter now gets false while everyone else gets true, which is rarely what you meant.

Providers

Provider Status
local Works. Flags come from WithLocalFlags and live in memory for the life of the process
launchdarkly Config and option exist (WithLaunchDarkly). Registration fails with "launchdarkly provider not yet available"
unleash Same: WithUnleash exists, registration fails
flagsmith Same: WithFlagsmith exists, registration fails
posthog Same: WithPostHog exists, registration fails

The providers package has client code for the four remote services, but the extension doesn't call it yet. Pick one today and registration fails, so your app won't start.

Configuration

Configure the extension with options on features.NewExtension, or under extensions.features (falling back to features) in your config file. Your options win over the file and the file wins over the defaults. Flags can live in YAML under local.flags, value included. Write a number the way your getter expects it: 50 decodes as int and 50.0 as float64. WithRequireConfig(true) turns a missing section into a startup error.

Option Effect
WithLocalFlags(map[string]FlagConfig) Sets the flag definitions and selects the local provider
WithDefaultFlags(map[string]any) Fallback values for keys with no flag definition
WithEnabled(bool) false skips registration entirely, and features.Get then returns an error
WithProvider(string) Picks a provider by name
WithRefreshInterval(time.Duration) How often the service calls the provider's Refresh. 0 turns the loop off
WithCache(bool, time.Duration) Sets EnableCache and CacheTTL, which nothing reads yet
WithLaunchDarkly, WithUnleash, WithFlagsmith, WithPostHog Fill provider settings and select that provider
WithRequireConfig(bool) true makes Register fail when the config file has no features section
WithConfig(features.Config) Replaces the whole config. NewExtensionWithConfig(cfg) does the same

DefaultConfig() gives you Enabled: true, Provider: "local", a 30-second refresh interval, and empty flag and default maps.

A FlagConfig has Key, Name, Description, Type (boolean, string, number or json), Enabled, Value, Targeting and Rollout. Type matters for GetAllFlags: it decides which getter is used for each flag, and anything other than the first three returns the raw Value.

Documentation

Topic Where
Features and usage Features extension guide
Configuration reference Features configuration
Function reference Features functions
Go API pkg.go.dev
Writing and loading extensions Forge extension system

Where the docs pages and this README disagree about providers or YAML config, this README follows the code.

FAQ

How do I add feature flags to a Go API?

Add features.NewExtension(features.WithLocalFlags(...)) to your Forge app's Extensions, then call IsEnabled or one of the typed getters with a UserContext. The quick start is a complete program.

How do percentage rollouts stay consistent per user in Go?

The provider hashes the user's ID (or the attribute you name) with MD5 and takes the result modulo 100. The same ID always lands in the same bucket, so a user doesn't flicker between on and off as you call the flag again, and raising the percentage only adds users.

Can I use LaunchDarkly, Unleash, Flagsmith or PostHog with Forge?

Not through this extension yet. The options exist, but choosing any of those providers makes startup fail until they're wired in. Use the local provider for now.

Can I change flags without restarting?

Not through the public API. Local flags are fixed when you build the extension, and the service doesn't expose a way to edit them, so you restart with new definitions or keep values you need to change at runtime somewhere else.

What happens if a flag is missing?

You get a default, never an error. A missing flag falls back to WithDefaultFlags, and then to the default you pass to the getter. IsEnabled uses false.

Contributing

Features is its own Go module in the Forge repository. Test it from its directory the way CI does:

cd extensions/features
GOWORK=off go build ./...
GOWORK=off go vet ./...
GOWORK=off go test -short -count=1 ./...
golangci-lint run ./...

AGENTS.md has the pinned lint version and the repository conventions. Commits follow Conventional Commits, for example feat(features): ....

License

Forge Features is part of Forge and is available under the Apache License 2.0.

Documentation

Index

Constants

View Source
const (
	// ServiceKey is the DI key for the features service.
	ServiceKey = "features"
	// ServiceKeyLegacy is the legacy DI key for the features service.
	ServiceKeyLegacy = "features.Service"
)

DI container keys for features extension services.

Variables

This section is empty.

Functions

func NewExtension

func NewExtension(opts ...ConfigOption) forge.Extension

NewExtension creates a new feature flags extension.

func NewExtensionWithConfig

func NewExtensionWithConfig(config Config) forge.Extension

NewExtensionWithConfig creates a new extension with complete config.

Types

type Config

type Config struct {
	// Enabled determines if feature flags extension is enabled
	Enabled bool `json:"enabled" yaml:"enabled"`

	// Provider specifies the backend provider
	// Options: "local", "launchdarkly", "unleash", "flagsmith", "posthog"
	Provider string `json:"provider" yaml:"provider"`

	// RefreshInterval is how often to refresh flags from remote provider
	RefreshInterval time.Duration `json:"refresh_interval" yaml:"refresh_interval"`

	// EnableCache enables local caching of flag values
	EnableCache bool `json:"enable_cache" yaml:"enable_cache"`

	// CacheTTL is the cache TTL for flag values
	CacheTTL time.Duration `json:"cache_ttl" yaml:"cache_ttl"`

	// Local provider settings
	Local LocalProviderConfig `json:"local" yaml:"local"`

	// LaunchDarkly provider settings
	LaunchDarkly LaunchDarklyConfig `json:"launchdarkly" yaml:"launchdarkly"`

	// Unleash provider settings
	Unleash UnleashConfig `json:"unleash" yaml:"unleash"`

	// Flagsmith provider settings
	Flagsmith FlagsmithConfig `json:"flagsmith" yaml:"flagsmith"`

	// PostHog provider settings
	PostHog PostHogConfig `json:"posthog" yaml:"posthog"`

	// DefaultFlags are default flag values (used as fallback)
	DefaultFlags map[string]any `json:"default_flags" yaml:"default_flags"`

	// RequireConfig requires config from ConfigManager
	RequireConfig bool `json:"-" yaml:"-"`
}

Config holds feature flags extension configuration.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns the default feature flags configuration.

type ConfigOption

type ConfigOption func(*Config)

ConfigOption configures the feature flags extension.

func WithCache

func WithCache(enabled bool, ttl time.Duration) ConfigOption

WithCache enables caching with TTL.

func WithConfig

func WithConfig(config Config) ConfigOption

WithConfig sets the complete config.

func WithDefaultFlags

func WithDefaultFlags(flags map[string]any) ConfigOption

WithDefaultFlags sets default flag values.

func WithEnabled

func WithEnabled(enabled bool) ConfigOption

WithEnabled sets whether feature flags is enabled.

func WithFlagsmith

func WithFlagsmith(apiURL, environmentKey string) ConfigOption

WithFlagsmith configures Flagsmith provider.

func WithLaunchDarkly

func WithLaunchDarkly(sdkKey string) ConfigOption

WithLaunchDarkly configures LaunchDarkly provider.

func WithLocalFlags

func WithLocalFlags(flags map[string]FlagConfig) ConfigOption

WithLocalFlags sets local provider flags.

func WithPostHog

func WithPostHog(apiKey, host string) ConfigOption

WithPostHog configures PostHog provider.

func WithProvider

func WithProvider(provider string) ConfigOption

WithProvider sets the feature flags provider.

func WithRefreshInterval

func WithRefreshInterval(interval time.Duration) ConfigOption

WithRefreshInterval sets the refresh interval.

func WithRequireConfig added in v1.12.9

func WithRequireConfig(require bool) ConfigOption

WithRequireConfig requires config from ConfigManager.

func WithUnleash

func WithUnleash(url, apiToken, appName string) ConfigOption

WithUnleash configures Unleash provider.

type EvaluationResult

type EvaluationResult struct {
	// FlagKey is the flag key
	FlagKey string `json:"flag_key"`

	// Value is the evaluated value
	Value any `json:"value"`

	// VariationIndex is the variation index (if applicable)
	VariationIndex int `json:"variation_index,omitempty"`

	// Reason is the evaluation reason
	Reason string `json:"reason"`

	// RuleID is the ID of the rule that matched (if applicable)
	RuleID string `json:"rule_id,omitempty"`
}

EvaluationResult holds the result of a flag evaluation.

type Extension

type Extension struct {
	*forge.BaseExtension
	// contains filtered or unexported fields
}

Extension implements forge.Extension for feature flags. The extension is now a lightweight facade that loads config and registers services.

func (*Extension) Dependencies

func (e *Extension) Dependencies() []string

Dependencies returns extension dependencies.

func (*Extension) Health

func (e *Extension) Health(ctx context.Context) error

Health checks the extension health.

func (*Extension) Register

func (e *Extension) Register(app forge.App) error

Register registers the extension with the app. This method now only loads configuration and registers service constructors.

func (*Extension) Start

func (e *Extension) Start(ctx context.Context) error

Start marks the extension as started. The actual service is started by Vessel calling Service.Start().

func (*Extension) Stop

func (e *Extension) Stop(ctx context.Context) error

Stop marks the extension as stopped. The actual service is stopped by Vessel calling Service.Stop().

type FlagConfig

type FlagConfig struct {
	// Key is the unique flag identifier
	Key string `json:"key" yaml:"key"`

	// Name is the human-readable name
	Name string `json:"name" yaml:"name"`

	// Description describes what this flag controls
	Description string `json:"description" yaml:"description"`

	// Type is the flag value type: "boolean", "string", "number", "json"
	Type string `json:"type" yaml:"type"`

	// Enabled is the default enabled state for boolean flags
	Enabled bool `json:"enabled" yaml:"enabled"`

	// Value is the default value for non-boolean flags
	Value any `json:"value" yaml:"value"`

	// Targeting defines user/group targeting rules
	Targeting []TargetingRule `json:"targeting" yaml:"targeting"`

	// Rollout defines percentage-based rollout
	Rollout *RolloutConfig `json:"rollout" yaml:"rollout"`
}

FlagConfig defines a single feature flag.

type FlagEvaluationEvent

type FlagEvaluationEvent struct {
	// FlagKey is the flag key
	FlagKey string `json:"flag_key"`

	// UserContext is the user context
	UserContext *UserContext `json:"user_context"`

	// Value is the evaluated value
	Value any `json:"value"`

	// Default indicates if the default value was used
	Default bool `json:"default"`

	// Reason is the evaluation reason
	Reason string `json:"reason"`

	// Timestamp is when the evaluation occurred
	Timestamp int64 `json:"timestamp"`
}

FlagEvaluationEvent represents a flag evaluation event for analytics.

type FlagValue

type FlagValue struct {
	// Key is the flag key
	Key string `json:"key"`

	// Value is the flag value
	Value any `json:"value"`

	// Enabled indicates if the flag is enabled (for boolean flags)
	Enabled bool `json:"enabled"`

	// Variation is the variation key/name
	Variation string `json:"variation,omitempty"`

	// Reason is the evaluation reason
	Reason string `json:"reason,omitempty"`
}

FlagValue represents a feature flag value with metadata.

type FlagsmithConfig

type FlagsmithConfig struct {
	// APIURL is the Flagsmith API URL
	APIURL string `json:"api_url" yaml:"api_url"`

	// EnvironmentKey is the Flagsmith environment key
	EnvironmentKey string `json:"environment_key" yaml:"environment_key"`
}

FlagsmithConfig for Flagsmith provider.

type LaunchDarklyConfig

type LaunchDarklyConfig struct {
	// SDKKey is the LaunchDarkly SDK key
	SDKKey string `json:"sdk_key" yaml:"sdk_key"`

	// Timeout for API requests
	Timeout time.Duration `json:"timeout" yaml:"timeout"`
}

LaunchDarklyConfig for LaunchDarkly provider.

type LocalProviderConfig

type LocalProviderConfig struct {
	// Flags are the static flag definitions
	Flags map[string]FlagConfig `json:"flags" yaml:"flags"`
}

LocalProviderConfig for local in-memory provider.

type PostHogConfig

type PostHogConfig struct {
	// APIKey is the PostHog project API key
	APIKey string `json:"api_key" yaml:"api_key"`

	// Host is the PostHog host (default: https://app.posthog.com)
	Host string `json:"host" yaml:"host"`

	// PersonalAPIKey for admin operations (optional)
	PersonalAPIKey string `json:"personal_api_key" yaml:"personal_api_key"`

	// EnableLocalEvaluation enables local flag evaluation (faster)
	EnableLocalEvaluation bool `json:"enable_local_evaluation" yaml:"enable_local_evaluation"`

	// PollingInterval for flag refresh (default: 30s)
	PollingInterval time.Duration `json:"polling_interval" yaml:"polling_interval"`
}

PostHogConfig for PostHog provider.

type Provider

type Provider interface {
	// Name returns the provider name
	Name() string

	// Initialize initializes the provider
	Initialize(ctx context.Context) error

	// IsEnabled checks if a boolean flag is enabled for a user/context
	IsEnabled(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue bool) (bool, error)

	// GetString gets a string flag value
	GetString(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue string) (string, error)

	// GetInt gets an integer flag value
	GetInt(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue int) (int, error)

	// GetFloat gets a float flag value
	GetFloat(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue float64) (float64, error)

	// GetJSON gets a JSON flag value
	GetJSON(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue any) (any, error)

	// GetAllFlags gets all flags for a user/context
	GetAllFlags(ctx context.Context, userCtx *UserContext) (map[string]any, error)

	// Refresh refreshes flags from remote source
	Refresh(ctx context.Context) error

	// Close closes the provider
	Close() error

	// Health checks provider health
	Health(ctx context.Context) error
}

Provider defines the interface for feature flag providers.

func NewFlagsmithProvider

func NewFlagsmithProvider(config FlagsmithConfig, defaults map[string]any) (Provider, error)

NewFlagsmithProvider creates a new Flagsmith provider NOTE: Temporarily disabled until dependencies are resolved.

func NewLaunchDarklyProvider

func NewLaunchDarklyProvider(config LaunchDarklyConfig, defaults map[string]any) (Provider, error)

NewLaunchDarklyProvider creates a new LaunchDarkly provider NOTE: Temporarily disabled until dependencies are resolved.

func NewLocalProvider

func NewLocalProvider(config LocalProviderConfig, defaults map[string]any) Provider

NewLocalProvider creates a new local in-memory provider.

func NewPostHogProvider

func NewPostHogProvider(config PostHogConfig, defaults map[string]any) (Provider, error)

NewPostHogProvider creates a new PostHog provider NOTE: Temporarily disabled until dependencies are resolved.

func NewUnleashProvider

func NewUnleashProvider(config UnleashConfig, defaults map[string]any) (Provider, error)

NewUnleashProvider creates a new Unleash provider NOTE: Temporarily disabled until dependencies are resolved.

type RolloutConfig

type RolloutConfig struct {
	// Percentage of users to enable (0-100)
	Percentage int `json:"percentage" yaml:"percentage"`

	// Attribute to use for consistent hashing (default: "user_id")
	Attribute string `json:"attribute" yaml:"attribute"`
}

RolloutConfig defines percentage-based rollout.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service provides high-level feature flag operations. It implements di.Service for lifecycle management.

func Get

func Get(container forge.Container) (*Service, error)

Get retrieves the features service from the container. Returns error if features service is not registered.

func GetFromApp

func GetFromApp(app forge.App) (*Service, error)

GetFromApp is a convenience helper to get features service from an App.

func MustGet

func MustGet(container forge.Container) *Service

MustGet retrieves the features service from the container. Panics if features service is not registered. Use this during application startup where failure should halt execution.

func MustGetFromApp

func MustGetFromApp(app forge.App) *Service

MustGetFromApp is a convenience helper to get features service from an App. Panics if features service is not registered. Use this during application startup where failure should halt execution.

func NewService

func NewService(config Config, provider Provider, logger forge.Logger) *Service

NewService creates a new feature flags service.

func (*Service) GetAllFlags

func (s *Service) GetAllFlags(ctx context.Context, userCtx *UserContext) (map[string]any, error)

GetAllFlags gets all feature flags for a user/context.

func (*Service) GetFloat

func (s *Service) GetFloat(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue float64) float64

GetFloat gets a float feature flag value.

func (*Service) GetInt

func (s *Service) GetInt(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue int) int

GetInt gets an integer feature flag value.

func (*Service) GetJSON

func (s *Service) GetJSON(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue any) any

GetJSON gets a JSON feature flag value.

func (*Service) GetString

func (s *Service) GetString(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue string) string

GetString gets a string feature flag value.

func (*Service) Health

func (s *Service) Health(ctx context.Context) error

Health checks the service health.

func (*Service) IsEnabled

func (s *Service) IsEnabled(ctx context.Context, flagKey string, userCtx *UserContext) bool

IsEnabled checks if a boolean feature flag is enabled.

func (*Service) IsEnabledWithDefault

func (s *Service) IsEnabledWithDefault(ctx context.Context, flagKey string, userCtx *UserContext, defaultValue bool) bool

IsEnabledWithDefault checks if a boolean feature flag is enabled with a custom default.

func (*Service) Name

func (s *Service) Name() string

Name returns the service name for Vessel's lifecycle management.

func (*Service) Refresh

func (s *Service) Refresh(ctx context.Context) error

Refresh refreshes flags from remote source.

func (*Service) Start

func (s *Service) Start(ctx context.Context) error

Start initializes the provider and starts the refresh loop.

func (*Service) Stop

func (s *Service) Stop(ctx context.Context) error

Stop stops the service gracefully.

type TargetingRule

type TargetingRule struct {
	// Attribute is the user attribute to match (e.g., "user_id", "email", "group")
	Attribute string `json:"attribute" yaml:"attribute"`

	// Operator is the comparison operator: "equals", "contains", "in", "not_in"
	Operator string `json:"operator" yaml:"operator"`

	// Values are the values to match against
	Values []string `json:"values" yaml:"values"`

	// Value is the flag value for matching users
	Value any `json:"value" yaml:"value"`
}

TargetingRule defines targeting rules for a flag.

type UnleashConfig

type UnleashConfig struct {
	// URL is the Unleash API URL
	URL string `json:"url" yaml:"url"`

	// APIToken is the Unleash API token
	APIToken string `json:"api_token" yaml:"api_token"`

	// AppName is the application name
	AppName string `json:"app_name" yaml:"app_name"`

	// Environment is the environment name
	Environment string `json:"environment" yaml:"environment"`

	// InstanceID is a unique instance identifier
	InstanceID string `json:"instance_id" yaml:"instance_id"`
}

UnleashConfig for Unleash provider.

type UserContext

type UserContext struct {
	// UserID is the unique user identifier
	UserID string `json:"user_id"`

	// Email is the user email
	Email string `json:"email,omitempty"`

	// Name is the user name
	Name string `json:"name,omitempty"`

	// Groups are user group memberships
	Groups []string `json:"groups,omitempty"`

	// Attributes are custom attributes for targeting
	Attributes map[string]any `json:"attributes,omitempty"`

	// IP is the user IP address
	IP string `json:"ip,omitempty"`

	// Country is the user country code
	Country string `json:"country,omitempty"`
}

UserContext holds user/context information for flag evaluation.

func NewUserContext

func NewUserContext(userID string) *UserContext

NewUserContext creates a new user context for flag evaluation.

func (*UserContext) GetAttribute

func (uc *UserContext) GetAttribute(key string) (any, bool)

GetAttribute gets a custom attribute.

func (*UserContext) GetAttributeString

func (uc *UserContext) GetAttributeString(key string) (string, error)

GetAttributeString gets a string attribute.

func (*UserContext) HasGroup

func (uc *UserContext) HasGroup(group string) bool

HasGroup checks if user is in a group.

func (*UserContext) WithAttribute

func (uc *UserContext) WithAttribute(key string, value any) *UserContext

WithAttribute sets a custom attribute.

func (*UserContext) WithCountry

func (uc *UserContext) WithCountry(country string) *UserContext

WithCountry sets the user country.

func (*UserContext) WithEmail

func (uc *UserContext) WithEmail(email string) *UserContext

WithEmail sets the user email.

func (*UserContext) WithGroups

func (uc *UserContext) WithGroups(groups []string) *UserContext

WithGroups sets the user groups.

func (*UserContext) WithIP

func (uc *UserContext) WithIP(ip string) *UserContext

WithIP sets the user IP address.

func (*UserContext) WithName

func (uc *UserContext) WithName(name string) *UserContext

WithName sets the user name.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL