flags

package
v1.801.299 Latest Latest
Warning

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

Go to latest
Published: Jul 28, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package flags is cloud's NATIVE feature-flag engine: definitions live in per-(org, project) SQLite (cloud.OrgDB — {DataDir}/orgs/{org}/projects/{project}/ flags.db, encrypted at rest via cek) and evaluation runs in-process through the embedded hanzo-flags Rust evaluator (native/flags, FFI) with PostHog-compatible semantics: rollout hash, full property-operator set, variants, payloads. Stateless and scalable by construction — no KV, no network hop, every pod evaluates from its own hot in-memory copy of the definitions.

TWO surfaces, ONE engine:

  • /v1/flags — the product API (org-scoped via the gateway principal): evaluate flags for a distinct_id + properties, manage definitions, read the activity log. PostHog-shaped responses so existing SDK consumers port 1:1.

  • the PLATFORM switches — the launch/ops knobs the SuperAdmin flips from admin.hanzo.ai (registry below). They evaluate from the reserved platform/platform store through the same engine. A switch with no stored definition falls back env -> literal default — exactly the pre-engine behavior, zero regression; the first cockpit write creates the definition and takes effect within one cache TTL (default 15s), no redeploy.

FAIL-SAFE. When the native engine is absent (!cgo) or a store read fails, evaluation degrades to env fallback -> literal default and the HTTP surface says so honestly — never fail-wrong.

── THE POLICY PRIMITIVE ─────────────────────────────────────────────────────────

This engine IS Hanzo's runtime decision primitive: (Principal, context) -> verdict, evaluated in-process, stateless, hot. It knows ONLY flags — definitions, evaluation, and the platform-switch registry. It has ZERO knowledge of any specific policy that rides on it: no host→service map, no waitlist, no service registry. Those COMPOSE this engine from the OUTSIDE, one-way (they import flags; flags imports none of them):

  • the launch waitlist gate (clients/admission) — a service's mode IS the switch waitlist.<svc>; admission owns the host→service registry + Enforce and reads the mode through flags.Bool. It USED to live in this package; extracting it is the PROOF the engine composes its tenants rather than absorbing them.
  • authz (access policy) — (Principal, resource+action) -> allow/deny
  • entitlements (product-access policy) — (Principal, feature/plan) -> granted/denied

Every one is (Principal, context) -> verdict. Folding them onto this evaluator makes Policy ONE composable primitive with one audit log and one hot-apply path. authz and entitlements are NOT built on it yet — this note only names the target so the seam stays visible; the launch waitlist (now external) is the first, proven composition.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Bool

func Bool(key string) bool

Bool returns the live boolean value of a registered switch (flags -> env -> default).

func GetDef added in v1.801.186

func GetDef(org, project, key string) (definition json.RawMessage, ok bool, err error)

GetDef reads a flag definition for (org, project). ok is false when no such flag exists. The experiments primitive composes it on decide to read the current assignment flag before rewriting its variant weights.

func Int

func Int(key string) int

Int returns the live integer value of a registered switch.

func Mount

func Mount(app cloud.Router, deps cloud.Deps) error

Mount opens the per-org definition stores, installs the process-wide evaluation seam, and registers the /v1/flags surface. The native engine being absent (!cgo) degrades every switch to env/default and the HTTP surface reports it — never an error at boot.

func PutDef added in v1.801.186

func PutDef(org, project, key string, definition json.RawMessage, actor string) error

PutDef writes (creates or overwrites) a flag definition for (org, project) and records the change in the flag's activity log. The experiments primitive composes it to register an experiment's multivariate assignment flag on create, and to rewrite the variant weights on decide (promote a winner to 100%). One definition store, one evaluator — no duplication.

func Register

func Register(d Def)

Register adds a switch to the platform-flag registry. Any subsystem may call it (in its init) to surface its own flag in the cockpit — the registry is open, not hardcoded. A duplicate key REPLACES the prior def (last registration wins).

func SetPlatformSwitch

func SetPlatformSwitch(key string, definition json.RawMessage, actor string) error

SetPlatformSwitch stores/overwrites a platform switch's definition (the admin cockpit's ONE write path) and applies it immediately in this pod.

func Shutdown

func Shutdown(_ context.Context) error

Shutdown closes every open per-org definitions store.

func String

func String(key string) string

String returns the live string value of a registered switch.

Types

type ActivityRow

type ActivityRow struct {
	ID     int64  `json:"id"`
	Key    string `json:"key"`
	Action string `json:"action"`
	Actor  string `json:"actor"`
	At     string `json:"at"`
	Detail string `json:"detail,omitempty"`
}

type Assignment added in v1.801.186

type Assignment struct {
	Variant string          `json:"variant"`
	On      bool            `json:"on"`
	Payload json.RawMessage `json:"payload,omitempty"`
}

Assignment is one subject's deterministic evaluation of a single flag: the multivariate Variant key (empty when the subject is not enrolled — the flag evaluated to boolean false), whether the flag is On (a variant, or boolean true), and the matched Payload (featureFlagPayloads[key], may be nil). It is the value the experiments primitive composes for assignment.

func Assign added in v1.801.186

func Assign(org, project, key, subject string, personProps json.RawMessage) (Assignment, error)

Assign evaluates one (org, project) flag for one subject and returns its deterministic assignment. This is THE assignment seam: subject -> variant is a pure function of (key, subject, definition) via the same engineEvaluate the /v1/flags surface runs — no second bucketing engine, no assignment store. personProps is the optional PostHog person_properties bag the flag's targeting groups read (nil when the experiment targets everyone). Fails CLOSED: an unconfigured engine returns an error, never a fabricated variant.

type BoardView

type BoardView struct {
	Engine     string       `json:"engine"`
	Configured bool         `json:"configured"`
	ManageURL  string       `json:"manageUrl"`
	AuditURL   string       `json:"auditUrl"`
	Switches   []SwitchView `json:"switches"`
}

BoardView is the full control-plane read board: the engine status plus every switch's live value. Definitions are edited in place over /v1/flags (the cockpit writes through SetPlatformSwitch); the activity log is the native change audit.

func Board

func Board() BoardView

Board evaluates every registered switch live and returns the cockpit read board.

type Client

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

Client is the in-process evaluation seam: per-(org, project) SQLite definition stores + the embedded native evaluator, with the platform project's evaluation cached for one TTL (the hot-apply bound).

type Def

type Def struct {
	Key      string // the flag key (snake_case)
	Category string // Launch | Signup | Subsystems | Gateway | Network
	Label    string
	Desc     string
	Type     Type
	Env      string // env var supplying the fallback default (may be "")
	Default  string // literal fallback when neither the store nor env has a value
	ReadOnly bool   // surfaced read-only (boot-time activation, network ids)
}

Def is ONE platform switch: a flag key qualified by the metadata the cockpit shows and the env var that provides the fallback default. This table is the ONE place the platform switches are named; the embedded engine evaluates them.

func Defs

func Defs() []Def

Defs returns a snapshot of the registered switches in registration order.

type DefRow

type DefRow struct {
	Key        string          `json:"key"`
	Definition json.RawMessage `json:"definition"`
	Version    int             `json:"version"`
	UpdatedAt  string          `json:"updated_at"`
	UpdatedBy  string          `json:"updated_by"`
}

type Store

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

func (*Store) Activity

func (s *Store) Activity(limit int) ([]ActivityRow, error)

func (*Store) Close

func (s *Store) Close() error

func (*Store) DefsJSON

func (s *Store) DefsJSON() ([]byte, int, error)

DefsJSON assembles every definition into the JSON array the evaluator takes. The stored definition's "key" wins; a row whose JSON is corrupt is skipped rather than poisoning the whole project.

func (*Store) Delete

func (s *Store) Delete(key, actor string) (bool, error)

func (*Store) Get

func (s *Store) Get(key string) (DefRow, bool, error)

func (*Store) List

func (s *Store) List() ([]DefRow, error)

func (*Store) Upsert

func (s *Store) Upsert(key string, definition json.RawMessage, actor string) error

Upsert stores a definition under key (the definition's own "key" field is forced to match) and logs the change.

type SwitchView

type SwitchView struct {
	Key         string `json:"key"`
	Category    string `json:"category"`
	Label       string `json:"label"`
	Description string `json:"description"`
	Type        string `json:"type"`
	Value       string `json:"value"`
	Source      string `json:"source"`
	Env         string `json:"env,omitempty"`
	ReadOnly    bool   `json:"readOnly"`
}

SwitchView is one platform switch as the admin cockpit renders it: the live value + where it came from (flags | env | default).

type Type

type Type string

Type is the switch kind the cockpit renders (and how the value is decoded).

const (
	TypeBool   Type = "bool"
	TypeInt    Type = "int"
	TypeString Type = "string"
)

Jump to

Keyboard shortcuts

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