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
- Variables
- func AcquireCoordinatorLease(ctx context.Context, root string) (func(), error)
- func CanonicalPath(path string) (string, error)
- func CheckPrivateControlRoot(root string) error
- func ControlRoot() (string, error)
- func DiscardNative(ctx context.Context, control string, change *NativeChange) error
- func IdentityMode(mode uint32) uint32
- func Lock(ctx context.Context, path string) (func(), error)
- func LockExisting(ctx context.Context, path string) (func(), error)
- func MatchPersistedDirectory(stored, current, parentDev string) bool
- func OwnedNotificationCommand(l Ledger, root string) (string, error)
- func PhysicalPath(path string) (string, error)
- func ReconcileNativeRegistration(ctx context.Context, control string) error
- func WindowsLauncherScript(launcher, entry string) []byte
- func WithInstalledLease(ctx context.Context, root string, expected InstalledSnapshot, ...) error
- func WriterCompatible(data []byte) bool
- type Consumer
- type File
- type Identity
- type InstalledSnapshot
- func AcquireInstalledLease(ctx context.Context, root string, expected InstalledSnapshot) (InstalledSnapshot, func(), error)
- func AcquireSetupLease(ctx context.Context, root string, expected InstalledSnapshot) (InstalledSnapshot, func(), error)
- func ReadInstalledSnapshot(root string) (InstalledSnapshot, error)
- type Ledger
- type NativeChange
- type NativeGeneration
- type NativeRecord
- type PathAnchor
- type PendingMutation
- type PolicySnapshot
- type PurgeEntry
- type PurgeTree
- type Request
- type RevocationSnapshot
- type UserPolicy
Constants ¶
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.
const ReservationWriterFloor = 2
ReservationWriterFloor is published with guarded start/change/cleanup of a PendingMutation. Ordinary installs keep WriterFloor. The floor never decreases.
const WriterFloor = 1
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 ¶
var ErrPolicyConflict = errors.New("stale explicit policy bytes")
ErrPolicyConflict refuses a stale ExpectedPolicy under the commit locks, before publishing any transaction or product mutation.
var ErrPolicyRecovery = errors.New("pending installation transaction requires installer recovery")
ErrPolicyRecovery leaves pending installer work untouched for its owner.
var ErrReservationConflict = errors.New("pending mutation reservation blocks this operation")
ErrReservationConflict is a pending mutation blocking an unmatched writer.
Functions ¶
func AcquireCoordinatorLease ¶
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 ¶
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 ¶
CheckPrivateControlRoot is read-only and shared by installed-state consumers. Missing roots are errors; it never creates or migrates state.
func ControlRoot ¶
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 ¶
IdentityMode returns the permission bits retained by the host fingerprint. Windows has no Unix execute bit and normalizes its file modes accordingly.
func Lock ¶
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 ¶
LockExisting acquires the permanent inode without creating any filesystem state.
func MatchPersistedDirectory ¶ added in v1.47.0
MatchPersistedDirectory compares a durable identity with a freshly observed physical directory. Callers must reject symlinks/non-directories first and supply the device of its held or no-follow observed parent. Only Darwin may renumber devices, and only away from a current volume boundary.
func OwnedNotificationCommand ¶
OwnedNotificationCommand selects the installed entry, including native Windows architecture names. Never infer an executable from an unowned filesystem file.
func PhysicalPath ¶
PhysicalPath rewrites only Darwin root-owned /var, /tmp, and /etc aliases. Arbitrary user-directory symlinks are not canonicalized.
func ReconcileNativeRegistration ¶ added in v1.47.0
ReconcileNativeRegistration is a post-success adapter, never transaction redo. It leaves bundle bytes and published callback identities intact. Callers must report failure as a warning: the committed installation remains successful.
func WindowsLauncherScript ¶
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 ¶
WriterCompatible is available to package adapters before any candidate exec. Source authentication remains the adapter's prerequisite.
Types ¶
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 publishes a required product-owned discovery alias while retaining pre-existing concrete conventional bundles and every queued callback inode.
func StageFiles ¶
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 ¶
Identity includes existence: an empty file is not an absent file.
func Fingerprint ¶
type InstalledSnapshot ¶
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 ¶
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 ¶
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.
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 ¶
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 AcquirePolicyLease ¶ added in v1.46.0
func AcquirePolicyLease(ctx context.Context, root string, expected PolicySnapshot) (PolicySnapshot, func(), error)
AcquirePolicyLease pins the exact observed policy and installation through a consumer's bounded handoff. Unlike AcquireInstalledLease, portable enablement is not an admission condition: the consumer must check its own registration and consent against the returned snapshot before using the retained native bundle. Both existing locks are retained until release.
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 ¶
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 {
// RevokeOpenCode permits only the exact desktop/webhook false policy patch
// when delivery assets are damaged. It still requires a registered consumer,
// generation and policy CAS; no asset, native or other policy mutation is allowed.
RevokeOpenCode bool
// RevokeGemini permits only Gemini's exact desktop/webhook false patch.
// Damaged assets do not prevent revocation; ownership and CAS still apply.
RevokeGemini bool
// 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 RevocationSnapshot ¶ added in v1.46.0
RevocationSnapshot is only a CAS preimage for turning a consumer's channels off. It deliberately does not assert that native or owned assets are usable.
func ReadRevocationSnapshot ¶ added in v1.46.0
func ReadRevocationSnapshot(ctx context.Context, root string) (RevocationSnapshot, error)
ReadRevocationSnapshot keeps the same component/config lock order as policy reads while allowing a damaged delivery asset to be revoked. Commit performs the final generation, ownership and exact policy preimage checks again.
type UserPolicy ¶
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.
Source Files
¶
- identity.go
- identity_other.go
- identity_refresh.go
- lock.go
- lock_unix.go
- native.go
- native_other.go
- native_path_unix.go
- native_registration.go
- native_rename_linux.go
- native_tree.go
- notification_command.go
- path.go
- path_alias_other.go
- path_unix.go
- policy.go
- purge.go
- recovery.go
- reservation.go
- retire.go
- retire_other.go
- snapshot.go
- stage.go
- swap_other.go
- sync_unix.go
- transaction.go
- writer.go