setupwizard

package
v1.48.1 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: GPL-2.0 Imports: 42 Imported by: 0

Documentation

Overview

Package setupwizard is the P6 application service for setup-notifications wizard. Run does not prompt. FillInteractive is a thin TTY adapter that only fills Request.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrPromptCanceled    = errors.New("prompt canceled")
	ErrPromptUnavailable = errors.New("prompt unavailable; pass --agents and --yes")
	ErrPromptInputClosed = errors.New("prompt input closed before a complete answer")
)
View Source
var ErrAmbiguousBinding = errors.New("ambiguous_binding")
View Source
var ErrAmbiguousInstallation = errors.New("ambiguous_installation")
View Source
var ErrLiveProfileConflict = errors.New("live_profile_conflict")
View Source
var ErrRefused = errors.New("setup wizard refused")

Functions

func BootstrapAutoTargets added in v1.46.1

func BootstrapAutoTargets(ctx context.Context, req Request, before Result) (selected, skipped []string, err error)

BootstrapAutoTargets preserves absent MCP units when an installation or owned direct registration already exists. Historical state has no durable per-client opt-out bit, so an absent sibling requires an explicit Add. A read error or ambiguous state must never be interpreted as a fresh install.

func BootstrapPolicyRows added in v1.47.0

func BootstrapPolicyRows(fields map[string]json.RawMessage) ([]string, error)

BootstrapPolicyRows exposes the effective enabled/route decisions for host summary without leaking raw policy into the immutable MCP projection.

func CheckBootstrapMCP added in v1.47.0

func CheckBootstrapMCP(expected BootstrapMCPSelection, current BootstrapMCPProjection) error

func ConfirmationRows added in v1.47.0

func ConfirmationRows(plan SetupPlan) ([]string, error)

ConfirmationRows derives the final scope from the ready plan and structured decisions populated by preflight, never from parsing the legacy prose.

func EscapeConfirmationRows added in v1.47.0

func EscapeConfirmationRows(raw []string) ([]string, error)

EscapeConfirmationRows quotes authority reversibly, including non-UTF8 Unix path bytes. No path suffix or warning is elided. Continuations split only between escaped tokens; an oversized plan refuses before reading consent.

func LiveNotifyClients

func LiveNotifyClients(controlRoot string, agents []string) []string

LiveNotifyClients returns selected agents that already have a non-absent portable binding. Missing state is "none"; the TTY adapter does not invent an installation from the running master's version.

func LiveSetupClients

func LiveSetupClients(req Request, agents []string) []string

LiveSetupClients returns selected agents that already have a portable binding or managed Codex hooks. Missing state is "none".

func RetryCommand

func RetryCommand(req Request) []string

RetryCommand is the structured argv that repeats this wizard request.

Types

type Action

type Action string
const (
	ActionInstall   Action = "install"
	ActionUninstall Action = "uninstall"
	ActionInspect   Action = "inspect"
	ActionUpdate    Action = "update"
	ActionRepair    Action = "repair"
)

type AgentCapability

type AgentCapability struct {
	ID      string
	Present bool
	Path    string
	Bound   bool
	Profile string
}

AgentCapability is the Claude/Codex surface shown by the TTY picker. Presence and bindings come from Engine.Discover; the renderer does not search PATH.

func DiscoverAgents

func DiscoverAgents(req Request) []AgentCapability

DiscoverAgents reports Claude/Codex user-scope metadata and executable presence without creating UAP state or executing found files.

type BootstrapDirectMCP added in v1.47.0

type BootstrapDirectMCP struct {
	ID, OwnerID         string
	Registered          bool
	Config, RuntimeRoot []byte
	Commands            [][]byte
}

type BootstrapMCPBinding added in v1.47.0

type BootstrapMCPBinding struct {
	Client, ID, Scope         string
	Target, DataRoot, Profile []byte
}

type BootstrapMCPProjection added in v1.47.0

type BootstrapMCPProjection struct {
	InstallationID string                `json:"installationID"`
	Bindings       []BootstrapMCPBinding `json:"bindings"`
	Direct         []BootstrapDirectMCP  `json:"direct"`
	Profiles       map[string][]byte     `json:"profiles"`
	PolicyPresent  bool                  `json:"policyPresent"`
	Enabled        bool                  `json:"enabled"`
}

func ObserveBootstrapMCP added in v1.47.0

func ObserveBootstrapMCP(ctx context.Context, r Request) (BootstrapMCPProjection, uint64, error)

ObserveBootstrapMCP returns the generation from the same verified ownership window as the relevant projection. Read-only observers never create state or run agents. Caller uses a deadline context for existing lock-based readers.

func ObserveBootstrapMCPWithPolicy added in v1.47.0

func ObserveBootstrapMCPWithPolicy(ctx context.Context, r Request) (BootstrapMCPProjection, uint64, installruntime.Identity, error)

ObserveBootstrapMCPWithPolicy carries the policy bytes verified with this projection into protected admission. It never reuses the confirmation preimage.

type BootstrapMCPSelection added in v1.47.0

type BootstrapMCPSelection struct {
	Selected   []string               `json:"selected"`
	Skipped    []string               `json:"skipped"`
	Projection BootstrapMCPProjection `json:"projection"`
	// A fresh absent policy may become the exact seed shown at confirmation.
	AllowPolicySeed bool `json:"allowPolicySeed"`
	SeedEnabled     bool `json:"seedEnabled"`
}

BootstrapMCPSelection freezes only portable identity, profile and keep/off decisions. Hooks/native runtime generations are intentionally not identity.

type ClientUnits

type ClientUnits struct {
	Client string
	Hooks  bool
	Notify bool
}

ClientUnits is the live hooks/notify fact for one selected client. The TTY shows these when Claude and Codex differ so omission is not one bool.

func LiveClientUnits

func LiveClientUnits(req Request, agents []string) []ClientUnits

LiveClientUnits reports currently managed hooks/notify for each selected client. A missing binding is off, not a collapsed global default.

type LinePrompt

type LinePrompt struct {
	In  io.Reader
	Out io.Writer
	// contains filtered or unexported fields
}

LinePrompt is a local adapter until UAP publishes the reusable P5 terminal UI.

func (*LinePrompt) Confirm

func (p *LinePrompt) Confirm(ctx context.Context, summary string) (bool, error)

func (*LinePrompt) SelectAgents

func (p *LinePrompt) SelectAgents(ctx context.Context, clients []AgentCapability) ([]string, error)

func (*LinePrompt) SelectExistingAction

func (p *LinePrompt) SelectExistingAction(ctx context.Context) (Action, error)

func (*LinePrompt) SelectLiveUnits

func (p *LinePrompt) SelectLiveUnits(ctx context.Context, live []ClientUnits) (bool, bool, bool, error)

func (*LinePrompt) SelectUnits

func (p *LinePrompt) SelectUnits(ctx context.Context) (bool, bool, error)

type MigrationBinding added in v1.45.3

type MigrationBinding struct {
	Old, New                       portable.Binding
	OldConsumerKey, NewConsumerKey string
}

MigrationBinding is the exact, versioned intent payload for replacing one historical portable consumer. A retry uses these bindings even if the UAP target or the process environment changed after confirmation.

type NextAction

type NextAction struct {
	Kind    string   `json:"kind"`
	Agents  []string `json:"agents,omitempty"`
	Command []string `json:"command,omitempty"`
	Reason  string   `json:"reason,omitempty"`
}

type Prompter

type Prompter interface {
	SelectAgents(context.Context, []AgentCapability) ([]string, error)
	SelectExistingAction(context.Context) (Action, error)
	SelectUnits(context.Context) (hooks, notify bool, err error)
	SelectLiveUnits(context.Context, []ClientUnits) (keep, hooks, notify bool, err error)
	Confirm(context.Context, string) (bool, error)
}

Prompter is the thin TTY port. It only fills Request fields; Run owns rules.

type PublicPrompt

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

PublicPrompt is the Notifications adapter for the neutral UAP terminal UI. It maps product choices to opaque IDs and keeps all wizard policy in this package; installerui never knows about hooks, MCP, or agent-notify.

func NewPublicPrompt

func NewPublicPrompt(in io.Reader, out io.Writer) (*PublicPrompt, error)

func NewTerminalPublicPrompt added in v1.47.0

func NewTerminalPublicPrompt(in, out *os.File, mode installerui.TerminalMode, noColor bool) (*PublicPrompt, error)

NewTerminalPublicPrompt borrows actual prompt descriptors. Menus use the shared cancellable line reader; effects consent always uses Terminal.Confirm.

func (*PublicPrompt) Confirm

func (p *PublicPrompt) Confirm(ctx context.Context, summary string) (bool, error)

func (*PublicPrompt) ConfirmPlan added in v1.47.0

func (p *PublicPrompt) ConfirmPlan(ctx context.Context, plan SetupPlan) (bool, error)

ConfirmPlan is called exactly once by the command, after Plan.Ready.

func (*PublicPrompt) SelectAgents

func (p *PublicPrompt) SelectAgents(ctx context.Context, clients []AgentCapability) ([]string, error)

func (*PublicPrompt) SelectExistingAction

func (p *PublicPrompt) SelectExistingAction(ctx context.Context) (Action, error)

func (*PublicPrompt) SelectLiveUnits

func (p *PublicPrompt) SelectLiveUnits(ctx context.Context, live []ClientUnits) (bool, bool, bool, error)

func (*PublicPrompt) SelectUnits

func (p *PublicPrompt) SelectUnits(ctx context.Context) (bool, bool, error)

type ReadinessFact

type ReadinessFact struct {
	Client     string `json:"client"`
	Runtime    string `json:"runtime"`
	Hooks      string `json:"hooks"`
	MCP        string `json:"mcp"`
	Permission string `json:"permission"`
	Restart    string `json:"restart"`
	Delivery   string `json:"delivery"`
}

ReadinessFact is independent of binary download. Inspect and mutation both report these fields; not_checked/not_verified are not installation failure.

type RemovalBinding added in v1.45.3

type RemovalBinding struct {
	Old            portable.Binding
	OldConsumerKey string
}

type Request

type Request struct {
	Action                                            Action
	Agents                                            []string
	Hooks, AgentNotify                                *bool
	Yes                                               bool
	PackageRoot, PluginRoot, ControlRoot, RuntimeRoot string
	// PackageRoots are per-agent local packages for mixed-revision Repair.
	// Run fills them from the offered root and still-usable recorded sources;
	// they are not CLI flags.
	PackageRoots map[string]string
	// CodexHome and ClaudeConfig are explicit UAP client profile roots.
	// EnvCodexHome and EnvClaudeConfig are a one-shot CLI snapshot of
	// CODEX_HOME / CLAUDE_CONFIG_DIR, not flags. Resume restores intent
	// profiles first; remaining empty roots take this snapshot. Run and
	// Plan do not reread the process environment.
	GlobalConfig, CodexHome, ClaudeConfig string
	// Cursor selection is explicit, never filled from discovery or environment.
	// Fixed authority is provided by the qualified composition owner; it does
	// not replace physical capture, installed receipts, or channel consent.
	CursorConfig                        string
	CursorAuthority                     *cursorinstall.Authority
	CursorAgentNotify                   *bool
	EnvCodexHome, EnvClaudeConfig       string
	ClientExecutable, ScopeRoot, Helper string
	ClientExecutables                   map[string]string
	PackageSHA256                       string
	// TreeDigest is the canonical package-tree digest from Prepare. It is
	// distinct from PackageSHA256 (archive bytes).
	TreeDigest, HelperDigest, HelperVersion string
	InstallationID, Primary                 string
	// BindingIDs are reserved per client during Plan/identity without
	// staging. Run and the durable intent reuse them.
	BindingIDs map[string]string
	// MigrationBindings freezes the exact historical and replacement consumer
	// identities before the confirmed intent is published. It is restored from
	// that intent on retry, never reconstructed from a changed host environment.
	MigrationBindings map[string]MigrationBinding
	// RemovalBindings freezes the exact portable consumer that uninstall will
	// revoke. A retry restores it from the confirmed intent after kernel revoke.
	RemovalBindings map[string]RemovalBinding
	// DataReceiptIDs are known UAP PLUGIN_DATA receipts. Uninstall/publish
	// copies live receipts onto the durable intent; resume rejects a different ID.
	DataReceiptIDs                      map[string]string
	MCPConfig                           map[string]string
	ClaudeHooks, CodexHooks             *bool
	ClaudeAgentNotify, CodexAgentNotify *bool
	// ExternalUninstalled is host attestation that Codex already removed the
	// native plugin, or never activated it. --yes does not set this.
	ExternalUninstalled bool
	// BootstrapExpectedGeneration fences an automatic client selection made
	// before release acquisition. It is internal to the bootstrap orchestrator:
	// an intervening opt-out must not become an implicit Add.
	BootstrapExpectedGeneration *uint64
	// BootstrapExpectedPolicy is captured after the last relevant projection check.
	BootstrapExpectedPolicy *installruntime.Identity
	// BootstrapMCP is consumed by the command admission boundary. Plan/Run use
	// the verified generation, then existing reservation/config CAS protects apply.
	BootstrapMCP *BootstrapMCPSelection
	// ClaudeRunner overrides Claude activation probing. Production leaves it
	// nil so the OS process runner is used. Isolated tests inject a listing
	// fixture; the field is never parsed from CLI flags.
	ClaudeRunner ports.CommandRunner
	// ReleaseVersion is the accepted master revision without a leading v.
	// DefaultReleaseVersion is a one-shot CLI snapshot of this binary's
	// compiled consumer version, not an explicit flag. Resume restores
	// intent.SourceRevision first; remaining empty values take this snapshot.
	ReleaseVersion, DefaultReleaseVersion string
	// ReleaseDownloadRoot is the directory that contains v{version}/ assets.
	// Empty disables host fetch so tests that omit --package stay offline.
	ReleaseDownloadRoot string
	// PackageFetcher downloads one URL. Production uses HTTPS; tests inject
	// a local server. Never parsed from CLI flags.
	PackageFetcher func(context.Context, string) ([]byte, error)
	// Progress reports large confirmed phases to the host. JSON stdout stays
	// one result; the CLI writes these lines to stderr. Nil is silent.
	Progress func(string)
	// DiscoverAgents supplies Claude/Codex executable presence for the TTY
	// picker. Production sets this from Engine.Discover. Nil skips presence
	// labels. The function must not execute found files.
	DiscoverAgents func() []AgentCapability
	// LiveUnits reports managed hooks/notify for the TTY mixed-opt-out
	// display. Nil uses LiveClientUnits from control-root state.
	LiveUnits func([]string) []ClientUnits
}

Request is copied by Run. Omitted unit flags are nil; install defaults both units on, uninstall omitted units selects every managed unit of the agents.

func ApplyEnvDefaults

func ApplyEnvDefaults(req Request) Request

ApplyEnvDefaults fills omitted Codex/Claude profile roots from the process environment once. Explicit Request fields win. HOME is not a fallback. The CLI snapshots these values onto EnvCodexHome/EnvClaudeConfig; Run and Plan apply that snapshot after resume instead of rereading the environment.

func FillInteractive

func FillInteractive(ctx context.Context, req Request, p Prompter, existing func([]string) []string) (Request, error)

FillInteractive copies req and asks only for omitted mutation choices. existing reports live portable bindings for the selected agents; nil means treat the machine as new. Detection stays outside this adapter.

func PinCurrentReleasePackage added in v1.46.1

func PinCurrentReleasePackage(ctx context.Context, req Request) (Request, error)

PinCurrentReleasePackage is used by the public bootstrap mode when its caller did not provide a verified ZIP. It deliberately ignores the old recorded package, so updating the runtime also updates the portable skill. Pending intents are checked before this function is called and keep their recorded source revision for resume.

func ResolvePendingPackage added in v1.48.0

func ResolvePendingPackage(ctx context.Context, req Request, intent portablesetup.Intent) (Request, error)

ResolvePendingPackage checks the admitted intent's exact candidate without fetching, consulting the predecessor, or removing any source.

func RetainCurrentReleasePackage added in v1.48.0

func RetainCurrentReleasePackage(ctx context.Context, req Request) (Request, error)

RetainCurrentReleasePackage publishes only an exclusive composition stage after caller admission, before Plan/Run. Its existing identity fields become the intent's address. Published sources are shared and never cleanup-owned.

func StageCurrentReleasePackage added in v1.48.0

func StageCurrentReleasePackage(ctx context.Context, req Request) (Request, func(), error)

StageCurrentReleasePackage lends only a newly owned acquisition to read-only caller composition. On success the caller retains it for Plan/Run and pending resume; cleanup is permitted only before either can begin an effect. Existing explicit/cached sources are shared and never belong to this cleanup.

type Result

type Result struct {
	Action         string          `json:"action"`
	Outcome        string          `json:"outcome"`
	Reason         string          `json:"reason,omitempty"`
	InstallationID string          `json:"installationID,omitempty"`
	Generation     uint64          `json:"generation,omitempty"`
	Command        []string        `json:"command,omitempty"`
	Targets        []TargetResult  `json:"targets,omitempty"`
	Readiness      []ReadinessFact `json:"readiness,omitempty"`
	NextActions    []NextAction    `json:"nextActions,omitempty"`
	// DataRetained is true after the last live binding is removed while
	// PLUGIN_DATA remains. Absent inspect rows are not a license to run.
	DataRetained bool `json:"dataRetained,omitempty"`
	// contains filtered or unexported fields
}

func Run

func Run(ctx context.Context, req Request) (Result, error)

func (Result) ExitCode

func (r Result) ExitCode() int

type SetupPlan

type SetupPlan struct {
	Text    string
	Ready   bool
	Request Request
	Result  Result
	// contains filtered or unexported fields
}

SetupPlan is the read-only preflight shown before TTY confirmation. Ready means the application service can mutate after --yes; it is not a committed installation result.

func Plan

func Plan(ctx context.Context, req Request) (SetupPlan, error)

Plan preflights without publishing intent or applying hooks/MCP.

type TargetResult

type TargetResult struct {
	Client     string `json:"client"`
	Unit       string `json:"unit"`
	Outcome    string `json:"outcome"`
	Reason     string `json:"reason,omitempty"`
	Profile    string `json:"profile,omitempty"`
	TreeDigest string `json:"treeDigest,omitempty"`
	// ConfigPath is the owned MCP file inspect used for a direct-mcp
	// target. Empty on hooks/notify rows so JSON omits it.
	ConfigPath string `json:"configPath,omitempty"`
	// Warnings are post-commit maintenance diagnostics, not installation failure.
	Warnings []string `json:"warnings,omitempty"`
}

Jump to

Keyboard shortcuts

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