approval

package
v0.0.21 Latest Latest
Warning

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

Go to latest
Published: Sep 14, 2026 License: MPL-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ComputeApprovalHash

func ComputeApprovalHash(res profile.Resolved) string

ComputeApprovalHash returns a 12-hex-char hash of the non-user gated fields of res, pre-template-expansion. The hash fingerprints the granted values only — contributor identity is excluded — so a grant moving between contributors (e.g. a tpd catalog refactor) does not re-prompt, while any value or key change does.

func DefaultPrompt

func DefaultPrompt(req PromptRequest, stdin io.Reader, stdout io.Writer) (map[string]map[string]bool, error)

DefaultPrompt is the bubbletea implementation: a scrollable flat list of every gated item, with previously approved items pre-checked and newly introduced ones unchecked. Enter submits the visible state as the choices map; esc/Ctrl+C aborts and surfaces as "approval declined".

func WithLock added in v0.0.8

func WithLock(store Store, fullName string, fn func() error) error

WithLock runs fn while holding an exclusive advisory lock on the profile's approval state file, so concurrent tpd processes cannot lose each other's approvals. The lock file is a stable sibling of the state file — never the state file itself — so locking the renamed path could not serialize writers. A store that does not implement Lockable (an in-memory overlay, or a decorator that fails to forward LockPath) is rejected rather than run unlocked.

Types

type ApprovedField

type ApprovedField struct {
	Keys    []string
	Network *bool
}

ApprovedField represents one field's approved set. Map fields use Keys; the scalar network uses Network (nil = never decided, true = approved, false = denied).

type EphemeralStore

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

EphemeralStore wraps a base Store with an in-memory overlay. Load returns the overlay (ignoring the base); Save is a no-op. Used by the --dry-run --yes/--no path so the re-filter sees the choice without persisting.

func NewEphemeralStore

func NewEphemeralStore(base Store, overlay State) *EphemeralStore

func (*EphemeralStore) Load

func (e *EphemeralStore) Load(string) (State, error)

func (*EphemeralStore) Save

func (e *EphemeralStore) Save(string, State) error

type FSStore

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

FSStore writes state files under <root>/approvals/<FullName>.yaml.

func NewFSStore

func NewFSStore(root string) *FSStore

func (*FSStore) Load

func (s *FSStore) Load(fullName string) (State, error)

func (*FSStore) LockPath added in v0.0.8

func (s *FSStore) LockPath(fullName string) (string, error)

LockPath returns the advisory lock file path for fullName's state file.

func (*FSStore) Save

func (s *FSStore) Save(fullName string, st State) error

type GatedItem added in v0.0.10

type GatedItem struct {
	Field  string
	Key    string
	Value  string
	Source profile.Contributor
	// PriorApproved reports whether the stored state already approved this
	// key. The UI pre-selects such items and leaves newly introduced ones
	// unselected, so a profile change cannot silently re-approve old grants.
	PriorApproved bool
	// Detail is a concise one-line descriptor for the list view ("read/write",
	// "host value", "talk", a host→container port binding, ...). Value is the
	// full pre-expansion label, shown for the highlighted item in the detail
	// pane.
	Detail string
	// Body is an optional multi-line rendering of the item's full value for
	// the detail pane (services format their definition across lines). When
	// empty, the pane shows Value wrapped.
	Body string
	// Benign marks permissions that are almost always harmless — common
	// dotfiles, cache dirs, display/runtime env vars, loopback ports,
	// D-Bus talk. Benign items are de-emphasized (grey, listed at the
	// bottom); everything else — including anything new from a remote import
	// — stays prominent, so the emphasis is fail-safe.
	Benign bool
	// Warning marks grants that deserve a highlighted color and the very top
	// of the list. Services are the biggest grant — a whole companion
	// container — so they carry it.
	Warning bool
}

GatedItem is one gated key the user must decide on.

type Lockable added in v0.0.8

type Lockable interface {
	// LockPath returns the advisory lock file path for fullName's state
	// file: a stable sibling of the state file, which Save replaces via
	// rename.
	LockPath(fullName string) (string, error)
}

Lockable is implemented by stores that back onto a filesystem state file and can name its advisory lock file. WithLock requires it, so a store or decorator that cannot lock never silently runs a transaction unlocked.

type Prompt

type Prompt func(req PromptRequest, stdin io.Reader, stdout io.Writer) (map[string]map[string]bool, error)

Prompt renders the interactive approval dialog and returns the user's choices as a map[field]set[key]bool. If stdin is not a TTY, returns an error.

type PromptRequest

type PromptRequest struct {
	ProfileName string
	FullName    string
	Hash        string
	Items       []GatedItem
}

PromptRequest is what the dialog renders. Empty Items = no prompt.

func Filter

func Filter(res profile.Resolved, store Store) (profile.Profile, PromptRequest, error)

Filter returns the profile with denied/dropped fields removed and a PromptRequest describing any still-unapproved gated fields.

type ReadOnlyStore

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

ReadOnlyStore wraps a base Store: Load delegates to the base; Save is a no-op. Used for the whole --dry-run flow so the initial Filter can read stored approvals (an approved profile must not prompt) but a reconciliation write-back never touches disk.

func NewReadOnlyStore

func NewReadOnlyStore(base Store) *ReadOnlyStore

func (*ReadOnlyStore) Load

func (r *ReadOnlyStore) Load(name string) (State, error)

func (*ReadOnlyStore) Save

func (r *ReadOnlyStore) Save(string, State) error

type State

type State struct {
	Hash     string
	Approved map[string]ApprovedField
}

func (State) MarshalYAML

func (s State) MarshalYAML() (interface{}, error)

func (*State) UnmarshalYAML

func (s *State) UnmarshalYAML(unmarshal func(interface{}) error) error

type Store

type Store interface {
	Load(profileName string) (State, error)
	Save(profileName string, s State) error
}

Store persists per-profile approval choices.

Jump to

Keyboard shortcuts

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