installruntime

package
v1.45.12 Latest Latest
Warning

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

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

Documentation

Overview

Package installruntime owns the shared installation transaction primitives. Lock order is component, then config paths in canonical sorted order. Config-only migration must never acquire the component lock.

Index

Constants

View Source
const CoordinatorLockName = ".setup-coordinator.lock"

CoordinatorLockName is the single ControlRoot process lock that serializes setup coordinators. The kernel lock inode is separate; death releases this lease, but a persisted reservation remains.

View Source
const ReservationWriterFloor = 2

ReservationWriterFloor is published with guarded start/change/cleanup of a PendingMutation. Ordinary installs keep WriterFloor. The floor never decreases.

View Source
const WriterFloor = 1
View Source
const WriterProtocolMarker = "agent-notifications-managed-writer-protocol-v1"

WriterProtocolMarker is an offline compatibility declaration in the trusted package bytes, not publisher authentication. No historical writer is run to discover its capabilities. Increment the floor for destructive protocol changes.

Variables

View Source
var ErrPolicyRecovery = errors.New("pending installation transaction requires installer recovery")

ErrPolicyRecovery leaves pending installer work untouched for its owner.

View Source
var ErrReservationConflict = errors.New("pending mutation reservation blocks this operation")

ErrReservationConflict is a pending mutation blocking an unmatched writer.

Functions

func AcquireCoordinatorLease

func AcquireCoordinatorLease(ctx context.Context, root string) (func(), error)

AcquireCoordinatorLease serializes confirmed cross-system mutation/resume. Read-only operations must not take it. The OS releases the lease on process death; file age is not ownership.

func CanonicalPath

func CanonicalPath(path string) (string, error)

CanonicalPath resolves directory roots, including a not-yet-created suffix. File CAS leaves must not use it: a final symlink is itself the owned identity.

func CheckPrivateControlRoot

func CheckPrivateControlRoot(root string) error

CheckPrivateControlRoot is read-only and shared by installed-state consumers. Missing roots are errors; it never creates or migrates state.

func ControlRoot

func ControlRoot() (string, error)

ControlRoot is independent of any client's installation or cache directory.

func DiscardNative

func DiscardNative(ctx context.Context, control string, change *NativeChange) error

DiscardNative removes only this invocation's unused, unchanged candidate. The component lock and recovery references prevent deleting either an interrupted transaction's input or the previous callback retained by a swap. This is best-effort staging cleanup, never the transaction's rollback path.

func IdentityMode

func IdentityMode(mode uint32) uint32

IdentityMode returns the permission bits retained by the host fingerprint. Windows has no Unix execute bit and normalizes its file modes accordingly.

func Lock

func Lock(ctx context.Context, path string) (func(), error)

Lock holds a permanent inode. Closing releases the kernel lock; the path is never unlinked, including after crashes. Callers must supply a deadline.

func LockExisting

func LockExisting(ctx context.Context, path string) (func(), error)

LockExisting acquires the permanent inode without creating any filesystem state.

func OwnedNotificationCommand

func OwnedNotificationCommand(l Ledger, root string) (string, error)

OwnedNotificationCommand selects the installed entry, including native Windows architecture names. Never infer an executable from an unowned filesystem file.

func PhysicalPath

func PhysicalPath(path string) (string, error)

PhysicalPath rewrites only Darwin root-owned /var, /tmp, and /etc aliases. Arbitrary user-directory symlinks are not canonicalized.

func WindowsLauncherScript

func WindowsLauncherScript(launcher, entry string) []byte

WindowsLauncherScript is the transaction-owned BAT wrapper. The shell installer must emit the same bytes and must not rewrite a committed launcher.

func WithInstalledLease

func WithInstalledLease(ctx context.Context, root string, expected InstalledSnapshot, handoff func(InstalledSnapshot) error) error

WithInstalledLease fences generation, owner, fingerprints and recovery until the bounded handoff returns. It never changes policy. Missing state is rejected without creating a control directory or lock.

func WriterCompatible

func WriterCompatible(data []byte) bool

WriterCompatible is available to package adapters before any candidate exec. Source authentication remains the adapter's prerequisite.

Types

type Consumer

type Consumer struct {
	RuntimeRoot  string
	Registration string
	Commands     []string
}

type File

type File struct {
	// WindowsReplacementID binds the evacuated preimage used by Windows redo.
	WindowsReplacementID string
	Parents              []PathAnchor
	BeforeData           []byte
	Link                 string
	Path                 string
	Before               Identity
	Data                 []byte
	Mode                 uint32
	Remove               bool
	DataSHA256           string `json:",omitempty"`
	BeforeDataSHA256     string `json:",omitempty"`
}

func NativeAlias

func NativeAlias(change *NativeChange, bin string) ([]File, error)

NativeAlias retains every pre-existing concrete bundle path. Hook discovery uses the stable ClaudeNotifier.app name, plus terminal-notifier.app when that optional legacy alias is free. A foreign legacy symlink is left untouched so an available modern alias can still be published. Retargeting those aliases does not swap the queued callback inode.

func StageFiles

func StageFiles(source, destination string, allow func(string) bool) ([]File, error)

StageFiles snapshots bytes and target identities before taking the component lock. The caller supplies its existing runtime allowlist. Callback bundles require the separate native promotion path and are never flattened here.

type Identity

type Identity struct {
	Link   string
	Exists bool
	SHA256 string
	Mode   uint32
}

Identity includes existence: an empty file is not an absent file.

func Fingerprint

func Fingerprint(path string) (Identity, error)

func OwnedFile

func OwnedFile(l Ledger, path string) (Identity, bool)

OwnedFile looks up a ledger identity by the published path or its canonical form.

type InstalledSnapshot

type InstalledSnapshot struct {
	Ledger   Ledger
	Recovery bool
	Enabled  bool
}

InstalledSnapshot is a read-only observation, not an admission lease. Missing, corrupt or interrupted state never creates files or performs recovery. Delivery must revalidate with WithInstalledLease immediately before handoff, without holding a journal lock. The callback must be bounded by ctx.

func AcquireInstalledLease

func AcquireInstalledLease(ctx context.Context, root string, expected InstalledSnapshot) (InstalledSnapshot, func(), error)

AcquireInstalledLease revalidates the snapshot under the existing component lock. The caller must release it after bounded handoff (or readiness probing), and must not hold a journal lock. Errors release the lease automatically. Missing state never creates a directory or a replacement lock inode.

func AcquireSetupLease

func AcquireSetupLease(ctx context.Context, root string, expected InstalledSnapshot) (InstalledSnapshot, func(), error)

AcquireSetupLease pins an existing, unchanged installation for explicit setup probes. It does not authorize notification delivery or enable policy. The caller must qualify native protocol support before executing the retained helper.

func ReadInstalledSnapshot

func ReadInstalledSnapshot(root string) (InstalledSnapshot, error)

type Ledger

type Ledger struct {
	WriterFloor      int
	Enabled          bool
	Native           *NativeRecord
	Schema           int
	ID               string
	Owner            string
	RuntimeRoot      string
	Generation       uint64
	PolicyGeneration uint64
	Consumers        map[string]Consumer
	Files            map[string]Identity
	DecoderFloor     int
	PendingMutation  *PendingMutation `json:",omitempty"`
}

func Commit

func Commit(ctx context.Context, r Request) (Ledger, error)

Commit serializes all component decisions, then config locks in canonical order. The durable redo record precedes every live mutation. Recovery checks every identity before changing anything and refuses ambiguous foreign edits.

func ReadOwnership

func ReadOwnership(root string) (Ledger, bool, error)

ReadOwnership returns the durable ledger and whether a recovery marker is present. Unlike ReadInstalledSnapshot it does not fingerprint unrelated published files, so a single-path Prepare callback can still repair a missing sibling under the component lock.

func Recover

func Recover(ctx context.Context, controlRoot string) (Ledger, error)

Recover replays a pending journal for this control root and returns. It does not refresh, install, add a consumer, or require a package.

type NativeChange

type NativeChange struct {
	Parents       []PathAnchor
	PurgeTrees    []PurgeTree
	Staged        string
	StagedID      string
	Before, After NativeRecord
	Purge         bool
	Retire        bool
}

func StageNative

func StageNative(ctx context.Context, control, source string) (*NativeChange, error)

StageNative accepts executable-code trust from the adapter's explicitly selected installation source (the same package authority as the Go sender). A self-signed manifest does not establish that authority. Shell uses its fixed upstream HTTPS release source; setup uses the user-selected plugin package. Missing manifests are legacy and never probed. Existing bin fallbacks must use StageRetainedNative instead: their presence does not authorize execution.

func StageRetainedNative

func StageRetainedNative(ctx context.Context, control, source string) (*NativeChange, error)

StageRetainedNative preserves existing unknown callbacks without probing them. Only a previously recorded exact managed fingerprint can retain a known floor.

type NativeGeneration

type NativeGeneration struct {
	DirectoryID, Path, SHA256 string
	DecoderFloor              int
	Attestation               []byte
	InstalledTreeSHA256       string
}

NativeGeneration is one published callback identity. Paths and inodes stay durable after later promotions; the ledger only selects the active artifact.

type NativeRecord

type NativeRecord struct {
	DirectoryID, PreviousDirectoryID string
	// Attestation stores the external post-signing package evidence durably,
	// outside the signed bundle. InstalledTreeSHA256 binds it to bundle bytes.
	Attestation                                []byte
	InstalledTreeSHA256                        string
	Path, SHA256, PreviousPath, PreviousSHA256 string
	DecoderFloor                               int
	Published                                  []NativeGeneration
}

NativeRecord is separate from ordinary runtime files: final consumer removal retains the callback reader and its previously published artifacts by default.

type PathAnchor

type PathAnchor struct{ Path, Identity string }

PathAnchor binds a staged destination's existing parents to their opened filesystem identities. Recovery must not reinterpret a substituted directory.

type PendingMutation

type PendingMutation struct {
	ID        string
	Owner     string
	IntentRef string
}

PendingMutation is the kernel-owned reservation. The intent payload lives in a host-owned file; this package does not parse it.

type PolicySnapshot

type PolicySnapshot struct {
	// Preimage identifies exactly the bytes parsed into Fields, not a later
	// fingerprint. Setup may pass it unchanged as Request.ExpectedPolicy.
	Preimage     Identity
	Installation InstalledSnapshot
	Policy       UserPolicy
	Fields       map[string]json.RawMessage
}

PolicySnapshot belongs to one request, never to a service lifetime. Fields contains the authoritative policy (including adapter-owned route settings), without a second on-disk configuration. Callers must treat it as immutable. Pass Installation unchanged to AcquireInstalledLease for readiness/handoff.

func ReadPolicySnapshot

func ReadPolicySnapshot(ctx context.Context, root string) (PolicySnapshot, error)

ReadPolicySnapshot reads policy and installation generation under component, then policy config locking. It never creates state or recovers transactions. Call once per request without a journal lock; release precedes journal work. Managed mutations use the same lock order. Manual edits have snapshot semantics.

type PurgeEntry

type PurgeEntry struct {
	ObjectID  string
	Directory string
	File      Identity
}

PurgeEntry persists individual ownership before the first deletion. Directory identities survive renames and reject replacement even by an identical tree.

type PurgeTree

type PurgeTree struct {
	Path    string
	Entries map[string]PurgeEntry
}

type Request

type Request struct {
	// PolicyOnly requires an already-managed runtime and existing kernel locks.
	// It refuses recovery and asset/consumer mutations; setup cannot accidentally
	// promote native or rewrite hooks from an unrelated pending transaction.
	PolicyOnly bool
	// PolicyEnabled changes explicit intent; nil preserves it. Mutations require
	// an expected generation and share component/config locking and recovery.
	PolicyEnabled *bool
	// PolicyFields merges installer-owned route/rates and setupState ownership
	// members into the same
	// policy CAS transaction. Nil preserves all existing fields.
	PolicyFields map[string]json.RawMessage
	// ExpectedPolicy optionally fences the exact setup policy preimage, including
	// manual config edits that do not increment the installation generation.
	ExpectedPolicy *Identity
	// RefreshOnly updates an already registered runtime without adding a consumer.
	RefreshOnly bool
	// RelocateVersionedCache explicitly moves only the existing Claude hooks
	// consumer between sibling, versioned Claude plugin cache directories.
	// Other consumers and their runtime roots are never moved implicitly.
	RelocateVersionedCache bool
	// RollbackPending explicitly reverses a pending transaction using per-file CAS.
	RollbackPending bool
	Native          *NativeChange
	PurgeNative     bool
	// RetireNative removes only the drained predecessor, retaining the stable reader.
	// Requires ExpectedGeneration; may not be combined with native promotion/removal.
	RetireNative                                bool
	ControlRoot, Owner, RuntimeRoot, ConsumerID string
	Consumer                                    Consumer
	RemoveConsumer                              bool
	ExpectedGeneration                          *uint64
	Files                                       []File
	ConfigPaths                                 []string
	Prepare                                     func() ([]File, error)
	// RecoverOnly replays a pending journal and returns without refresh, install,
	// or consumer registration. It does not require owner/runtime/package.
	RecoverOnly bool
	// Reservation publishes or continues a kernel-owned pending mutation.
	Reservation *PendingMutation
	// ClearReservation removes a matching pending mutation. Floor/schema stay.
	ClearReservation bool
	// Fault is a test seam; returning an error intentionally leaves recovery data.
	Fault func(string) error
}

Request stages ordinary file bytes before Commit. Prepare runs under the component and config locks, and may only compute adapter-owned JSON changes.

type UserPolicy

type UserPolicy struct {
	SchemaVersion int  `json:"schemaVersion"`
	Enabled       bool `json:"enabled"`
}

UserPolicy is durable user intent. Runtime eligibility and its generation fence remain in the ledger; routes belong only in this authoritative file.

func ReadUserPolicy

func ReadUserPolicy(root string) (UserPolicy, error)

ReadUserPolicy never creates or migrates configuration. Missing means disabled. Unknown fields are retained by managed enable/disable for future route adapters.

Jump to

Keyboard shortcuts

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