features

package
v0.11.0-beta.1 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: Apache-2.0, MIT Imports: 6 Imported by: 0

Documentation

Overview

Package features is a small runtime feature-flag layer for Overkill (Phase 1.5 #4). Lighter than LaunchDarkly — no network, no dependencies — but richer than static config because flags can gate on USER, CHANNEL, or a PERCENTAGE rollout per request.

Three layers (highest precedence first):

  1. Per-user override (Flag.UserOverrides[userID])
  2. Per-channel override (Flag.ChannelOverrides[channelID])
  3. Percentage rollout (Flag.Percent, deterministic hash of context)
  4. Default (Flag.Default)

All flags are evaluated against an EvalContext. A missing flag is treated as disabled (safe default — code paths gated behind a flag shouldn't activate just because the flag name was typo'd).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type EvalContext

type EvalContext struct {
	UserID  string
	Channel string
	// Subject is the optional unit-of-rollout key. When set, percent
	// rollout hashes against this string so a given subject (e.g.
	// session ID, project name) gets a STABLE bucket. When empty,
	// UserID is used as the subject. When both empty, percent rollout
	// is treated as disabled (no stable bucket = unsafe to flip).
	Subject string
}

EvalContext supplies the inputs the layered rules evaluate against. All fields optional — an empty context evaluates only the Default.

type Flag

type Flag struct {
	Name             string            `toml:"-" json:"name"`
	Default          bool              `toml:"default" json:"default"`
	Percent          int               `toml:"percent" json:"percent"`       // 0..100; 0 = disabled rollout
	UserOverrides    map[string]bool   `toml:"users" json:"users,omitempty"` // userID → enabled
	ChannelOverrides map[string]bool   `toml:"channels" json:"channels,omitempty"`
	Tags             map[string]string `toml:"tags" json:"tags,omitempty"` // free-form metadata for UI
}

Flag is a single named gate.

type Manager

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

Manager holds a set of flags and evaluates them concurrently.

func NewManager

func NewManager() *Manager

NewManager returns an empty manager. Use Register / LoadDefaults / LoadFromTOML to populate.

func (*Manager) Enabled

func (m *Manager) Enabled(name string, ctx EvalContext) bool

Enabled evaluates the named flag against ctx and returns the decision. Unknown flag → false (safe default).

Layering (highest precedence first):

  1. UserOverrides[ctx.UserID] if entry present
  2. ChannelOverrides[ctx.Channel] if entry present
  3. Percent rollout if Percent > 0 AND subject available. Subject is the primary roll-out key (e.g. a user ID). When Subject is empty, UserID is used as a fallback. When both are empty the percent check is silently skipped — no one gets the flag via percent rollout. This is intentional: a flag with Percent > 0 but no identifiable user simply won't roll out to that context. Set a ChannelOverride or Default=true if you need anonymous contexts to receive the flag.
  4. Default

func (*Manager) Get

func (m *Manager) Get(name string) *Flag

Get returns a copy of the named flag, or nil when not registered.

func (*Manager) List

func (m *Manager) List() []*Flag

List returns all registered flags. Order is undefined.

func (*Manager) LoadFromTOML

func (m *Manager) LoadFromTOML(path string) error

LoadFromTOML reads a features.toml and registers every flag it contains. Missing file is OK. Malformed file returns the parse error so the caller can surface it to the user.

func (*Manager) Register

func (m *Manager) Register(f *Flag)

Register adds or replaces a flag. Pass a copy if the caller might mutate the original — Manager stores the pointer.

Jump to

Keyboard shortcuts

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