admin

package
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Apr 16, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ActionAcquireSyncLock            = "ACQUIRE_SYNC_LOCK"
	ActionReleaseSyncLock            = "RELEASE_SYNC_LOCK"
	ActionSetConditionOverride       = "SET_CONDITION_OVERRIDE"
	ActionClearConditionOverride     = "CLEAR_CONDITION_OVERRIDE"
	ActionClearAllConditionOverrides = "CLEAR_ALL_CONDITION_OVERRIDES"
	ActionConditionOverrideAutoClear = "CONDITION_OVERRIDE_AUTO_CLEARED"
)

Audit-log action constants for the lock + condition-override epic. Defined here (rather than as bare strings) so they're greppable and callers can't typo them.

Variables

View Source
var (
	ErrFlagNotFound     = errors.New("flag not found")
	ErrOverrideNotFound = errors.New("override not found")
	ErrInvalidArgument  = errors.New("invalid argument")
)

Sentinel errors used by the override / sync-lock store layer. mapStoreErr in service.go uses errors.Is to translate these into the right Connect codes — replacing the prior brittle substring matcher.

View Source
var ErrSyncNotLocked = errors.New("sync is not locked")

ErrSyncNotLocked is returned when ReleaseSyncLock is called while the lock is not held.

Functions

func SourceProtoToString added in v0.20.0

func SourceProtoToString(s pbflagsv1.OverrideSource) string

SourceProtoToString is the inverse: proto enum → DB column value. Unspecified defaults to "cli" (the most common entry point).

Types

type AdminService

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

AdminService implements the FlagAdminService Connect handler.

func NewAdminService

func NewAdminService(store *Store, logger *slog.Logger, opts ...AdminServiceOption) *AdminService

NewAdminService creates a FlagAdminService handler.

func (*AdminService) AcquireSyncLock added in v0.20.0

func (*AdminService) GetLaunch added in v0.18.0

func (*AdminService) GetSyncLock added in v0.20.0

GetSyncLock is gated by --allow-runtime-overrides for symmetry with Acquire/Release: if the feature isn't on, no part of the lock surface is addressable.

func (*AdminService) KillLaunch added in v0.18.0

func (*AdminService) ListLaunches added in v0.18.0

func (*AdminService) ReleaseSyncLock added in v0.20.0

func (*AdminService) UnkillLaunch added in v0.18.0

func (*AdminService) UpdateLaunchRamp added in v0.18.0

type AdminServiceOption added in v0.20.0

type AdminServiceOption func(*AdminService)

AdminServiceOption configures optional AdminService behavior.

func WithAllowRuntimeOverrides added in v0.20.0

func WithAllowRuntimeOverrides() AdminServiceOption

WithAllowRuntimeOverrides enables every state-changing RPC: condition overrides, sync lock acquire/release, flag state updates (kill/unkill), and launch ramp/status/kill/unkill. Default is disabled — operators opt in via the --allow-runtime-overrides server flag (default true at the binary level; off only on locked-down read-only deployments).

type AuditLogFilter added in v0.4.1

type AuditLogFilter struct {
	FlagID string
	Action string
	Actor  string
	Limit  int32
}

AuditLogFilter specifies optional filters for audit log queries.

type ConditionOverride added in v0.20.0

type ConditionOverride struct {
	FlagID         string
	ConditionIndex *int32 // nil = static/compiled-default override
	Value          *pbflagsv1.FlagValue
	Source         string // "cli" or "ui"
	Actor          string
	Reason         string
	CreatedAt      time.Time
}

ConditionOverride is one row from feature_flags.condition_overrides.

type FlagCondition added in v0.16.0

type FlagCondition struct {
	CEL         string // CEL expression; empty string means "otherwise" (default fallback)
	Value       string // formatted display value
	Comment     string // annotation from YAML comment
	LaunchID    string // launch override ID (empty if none)
	LaunchValue string // formatted launch override value
}

FlagCondition represents a single condition in a flag's condition chain.

type FlagExtra added in v0.16.0

type FlagExtra struct {
	Conditions      []FlagCondition
	ConditionsError string
	SyncSHA         string
}

FlagExtra holds non-proto data loaded alongside a FlagDetail.

type Launch added in v0.17.0

type Launch struct {
	LaunchID         string
	ScopeFeatureID   *string // nil for cross-feature launches
	Dimension        string
	RampPct          int
	RampSource       string // "unspecified", "config", "cli", "ui"
	Status           string
	KilledAt         *time.Time
	AffectedFeatures []string
	Description      *string
	CreatedAt        time.Time
	UpdatedAt        time.Time
	RampSteps        []int32
}

Launch represents a launch (gradual rollout) in the new schema.

type OverrideListFilter added in v0.20.0

type OverrideListFilter struct {
	FlagID string
	MinAge time.Duration
	Actor  string
	// Limit caps the result count. Zero / negative defaults to
	// defaultOverrideListLimit. Values above maxOverrideListLimit are
	// clamped to that ceiling.
	Limit int32
}

OverrideListFilter narrows the global override listing.

type Store

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

Store provides PostgreSQL persistence for flag state.

func NewStore

func NewStore(pool *pgxpool.Pool, logger *slog.Logger) *Store

NewStore creates a Store backed by the given connection pool.

func (*Store) AcquireSyncLock added in v0.20.0

func (s *Store) AcquireSyncLock(ctx context.Context, actor, reason string) (*SyncLockInfo, error)

AcquireSyncLock takes the global sync lock. If the lock is already held, returns *SyncLockHeldError carrying the current holder's metadata.

Race safety: uses INSERT ... ON CONFLICT DO NOTHING so concurrent acquires both attempt the insert; only one succeeds, the other re-reads the holder and returns SyncLockHeldError.

func (*Store) ClearAllConditionOverrides added in v0.20.0

func (s *Store) ClearAllConditionOverrides(ctx context.Context, flagID, actor, reason string) (int, error)

ClearAllConditionOverrides deletes every override on a flag, returning the number cleared. Reason is captured in the audit row.

func (*Store) ClearConditionOverride added in v0.20.0

func (s *Store) ClearConditionOverride(
	ctx context.Context,
	flagID string,
	conditionIndex *int32,
	actor, reason string,
) error

ClearConditionOverride deletes a single override row. Returns ErrOverrideNotFound when no row exists at this position.

func (*Store) ClearOverridesForFlagsTx added in v0.20.0

func (s *Store) ClearOverridesForFlagsTx(ctx context.Context, tx pgx.Tx, flagIDs []string, actor string) (int, error)

ClearOverridesForFlagsTx is invoked by sync inside its own transaction to auto-clear overrides for synced flags after a successful condition write. Each cleared override is audit-logged as CONDITION_OVERRIDE_AUTO_CLEARED.

Caller passes the tx so the override clear commits atomically with the new conditions, eliminating the race where new conditions are visible but old overrides still match.

func (*Store) ConfigManagedFeatures added in v0.20.0

func (s *Store) ConfigManagedFeatures(ctx context.Context) (map[string]bool, error)

ConfigManagedFeatures returns a set of feature IDs that are currently config-as-code managed (sync_sha is set). Used by the dashboard to surface a per-feature badge without an N+1 lookup.

func (*Store) FlagsByLaunch added in v0.20.0

func (s *Store) FlagsByLaunch(ctx context.Context, launches []Launch) (map[string][]string, error)

FlagsByLaunch returns a map from launch_id to the sorted list of flag_ids whose condition chain references that launch (pb-6fi). The scan is restricted to the union of features the supplied launches affect — typically a small set — to keep the cost bounded for the admin UI's per-launch "impacted flags" panel. Conditions live in a proto-encoded BYTEA column, so we decode in Go rather than push the filter into SQL.

Returns an empty map (never nil) when launches is empty so callers can index without nil-checks. Failures to decode an individual flag's chain are logged and skipped — one bad row shouldn't blank out the whole UI panel.

func (*Store) GetAuditLog

func (s *Store) GetAuditLog(ctx context.Context, filter AuditLogFilter) ([]*pbflagsv1.AuditLogEntry, error)

GetAuditLog returns audit log entries, optionally filtered by flag ID, action, and actor.

func (*Store) GetFlag

func (s *Store) GetFlag(ctx context.Context, flagID string) (*pbflagsv1.FlagDetail, *FlagExtra, error)

GetFlag returns details for a single flag.

func (*Store) GetFlagState

func (s *Store) GetFlagState(ctx context.Context, flagID string) (*pbflagsv1.GetFlagStateResponse, error)

GetFlagState returns the state and value for a single flag.

func (*Store) GetKilledFlags

func (s *Store) GetKilledFlags(ctx context.Context) (*pbflagsv1.GetKilledFlagsResponse, error)

GetKilledFlags returns globally killed flag IDs.

func (*Store) GetLaunch added in v0.17.0

func (s *Store) GetLaunch(ctx context.Context, launchID string) (*Launch, error)

GetLaunch returns a single launch by ID.

func (*Store) GetSyncLock added in v0.20.0

func (s *Store) GetSyncLock(ctx context.Context) (*SyncLockInfo, error)

GetSyncLock returns the current lock state, or (nil, nil) if unlocked.

func (*Store) IsConfigManaged added in v0.20.0

func (s *Store) IsConfigManaged(ctx context.Context, flagID string) (bool, error)

IsConfigManaged returns true when the owning feature has a non-empty sync_sha (i.e., config-as-code is currently the source of truth for this flag's conditions). Callers use this to surface a warning when overriding.

func (*Store) KillLaunch added in v0.17.0

func (s *Store) KillLaunch(ctx context.Context, launchID string, actor string) error

KillLaunch sets killed_at on a launch (reversible emergency disable).

func (*Store) ListAllLaunches added in v0.17.0

func (s *Store) ListAllLaunches(ctx context.Context) ([]Launch, error)

ListAllLaunches returns all launches.

func (*Store) ListAllOverrides added in v0.20.0

func (s *Store) ListAllOverrides(ctx context.Context, f OverrideListFilter) ([]ConditionOverride, error)

ListAllOverrides returns active condition overrides across all flags, newest first. Backs both the `pb overrides` CLI and the dashboard listing. The result is bounded — see OverrideListFilter.Limit.

func (*Store) ListFeatures

func (s *Store) ListFeatures(ctx context.Context) ([]*pbflagsv1.FeatureDetail, map[string]int, error)

ListFeatures returns all features with their non-archived flags. The second return value maps flag_id → condition count (0 = static/default).

func (*Store) ListLaunches added in v0.17.0

func (s *Store) ListLaunches(ctx context.Context, featureID string) ([]Launch, error)

ListLaunches returns launches scoped to a feature (defined in the feature config).

func (*Store) ListLaunchesAffecting added in v0.17.0

func (s *Store) ListLaunchesAffecting(ctx context.Context, featureID string) ([]Launch, error)

ListLaunchesAffecting returns all launches that affect a feature (including cross-feature).

func (*Store) ListOverridesForFlag added in v0.20.0

func (s *Store) ListOverridesForFlag(ctx context.Context, flagID string) ([]ConditionOverride, error)

ListOverridesForFlag returns all overrides on a single flag, ordered with the static-default (NULL) row first, then by condition_index ascending.

func (*Store) ReleaseSyncLock added in v0.20.0

func (s *Store) ReleaseSyncLock(ctx context.Context, actor, unlockReason string) error

ReleaseSyncLock releases the global sync lock. Returns ErrSyncNotLocked if no lock is currently held. unlockReason is captured in the audit row so retros can see why the lock was released.

func (*Store) SetConditionOverride added in v0.20.0

func (s *Store) SetConditionOverride(
	ctx context.Context,
	flagID string,
	conditionIndex *int32,
	value *pbflagsv1.FlagValue,
	source, actor, reason string,
) (*pbflagsv1.FlagValue, error)

SetConditionOverride upserts an override row for (flagID, conditionIndex). Returns the previous override value at this position, if any (for confirmation UX). conditionIndex == nil means override the static/compiled default. source must be "cli", "ui", or "automation".

Race safety: uses INSERT ... ON CONFLICT DO UPDATE keyed off the partial unique indexes, so concurrent set calls on the same (flag, index) can't both INSERT and trip the unique constraint.

func (*Store) UnkillLaunch added in v0.17.0

func (s *Store) UnkillLaunch(ctx context.Context, launchID string, actor string) error

UnkillLaunch clears killed_at on a launch (resume where it left off).

func (*Store) UpdateFlagState

func (s *Store) UpdateFlagState(ctx context.Context, flagID string, state pbflagsv1.State, actor string) error

UpdateFlagState sets the killed state for a flag (kill or unkill).

func (*Store) UpdateLaunchRamp added in v0.17.0

func (s *Store) UpdateLaunchRamp(ctx context.Context, launchID string, pct int, source, actor string) (prevSource string, err error)

UpdateLaunchRamp changes the ramp percentage for a launch and records an audit log entry. Returns the previous ramp_source so callers can warn when overriding config-managed ramp.

func (*Store) UpdateLaunchStatus added in v0.17.0

func (s *Store) UpdateLaunchStatus(ctx context.Context, launchID string, status string, actor string) error

UpdateLaunchStatus changes the lifecycle status of a launch.

type SyncLockHeldError added in v0.20.0

type SyncLockHeldError struct {
	Info SyncLockInfo
}

SyncLockHeldError is returned when AcquireSyncLock is called while the lock is already held by someone else. It carries the current holder so the caller can include it in user-facing error messages.

func (*SyncLockHeldError) Error added in v0.20.0

func (e *SyncLockHeldError) Error() string

type SyncLockInfo added in v0.20.0

type SyncLockInfo struct {
	Actor     string
	Reason    string
	CreatedAt time.Time
}

SyncLockInfo describes the held state of the global config-sync lock.

Directories

Path Synopsis
Package web provides an embedded admin dashboard for the pbflags feature flag system.
Package web provides an embedded admin dashboard for the pbflags feature flag system.

Jump to

Keyboard shortcuts

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