Documentation
¶
Overview ¶
Package updates verifies publisher-authenticated agent-update manifests, authenticated machine inventory reports and the write-ahead upgrade journal, plus bounded payload streams. It grants no permission to install, downloads nothing and does not implement the updater, management transport or job lifecycle.
Index ¶
- Constants
- Variables
- func Digest(raw []byte) string
- func KeyID(key ed25519.PublicKey) string
- type ActionReceipt
- type Artifact
- type Compatibility
- type Driver
- type Inventory
- type InventoryAttempt
- type InventoryDriver
- type InventoryMSI
- type Journal
- type JournalAck
- type JournalAction
- type JournalBinding
- type JournalContext
- type JournalEvent
- type JournalPlan
- type JournalSnapshot
- type JournalStore
- type JournalTransition
- type MSI
- type Manifest
- type Predecessor
- type Updater
- type VerifiedInventory
- type VerifiedManifest
Constants ¶
const ( InventoryDomain = "kw-management-inventory/v1\x00" MaxInventoryBytes = 32 * 1024 InventoryFreshSeconds = 60 MaxInventoryMSIEntries = 8 )
InventoryDomain frames authenticated management.inventory.v1 reports. The signature covers the domain plus the exact payload bytes; freshness and the server-minted nonce binding are checked after authenticity.
const ( MaxJournalBytes = 16 * 1024 MaxJournalSequence = 1_000_000 AttemptSeconds int64 = 15 * 60 RebootWaitSeconds int64 = 24 * 60 * 60 )
const ( Domain = "kw-agent-update-manifest/v1\x00" MaxManifestBytes = 64 * 1024 MaxArtifactBytes uint64 = 2 * 1024 * 1024 * 1024 AgentUpgradeCode = "f72bb43e-dba8-4dbb-a963-b201e6c0d885" )
Variables ¶
var ( ErrInventory = errors.New("invalid machine inventory") ErrInventoryFresh = errors.New("machine inventory is stale, future-dated or bound to a different nonce") )
var ( ErrJournal = errors.New("invalid update journal") ErrFence = errors.New("update journal binding or owner fence changed") ErrTransition = errors.New("update journal transition denied") ErrClock = errors.New("update journal clock is stale or out of bounds") ErrRecording = errors.New("update journal recording acknowledgment required") ErrPersistence = errors.New("update journal persistence outcome unavailable; reload before continuing") ErrConflict = errors.New("update journal compare-and-swap conflict") )
var ( ErrInvalid = errors.New("invalid agent update manifest") ErrUntrusted = errors.New("agent update publisher is not trusted") ErrDigest = errors.New("agent update manifest digest mismatch") ErrSignature = errors.New("agent update manifest signature mismatch") ErrPayload = errors.New("agent update payload is incomplete, oversized or corrupt") )
Functions ¶
Types ¶
type ActionReceipt ¶
type ActionReceipt struct {
Sequence uint64 `json:"sequence"`
Kind string `json:"kind"`
Outcome string `json:"outcome"`
MSICode *int64 `json:"msi_code"`
ServiceState string `json:"service_state"`
ProductCode string `json:"product_code"`
TargetAbsent bool `json:"target_absent"`
DriverSHA256 string `json:"driver_sha256"`
IdentityVerified bool `json:"identity_verified"`
HealthVerified bool `json:"health_verified"`
}
type Compatibility ¶
type Compatibility struct {
MinimumAgentVersion string `json:"minimum_agent_version"`
MaximumAgentVersion string `json:"maximum_agent_version"`
ManagementMin uint16 `json:"management_min"`
ManagementMax uint16 `json:"management_max"`
DesktopMin uint16 `json:"desktop_min"`
DesktopMax uint16 `json:"desktop_max"`
}
type Inventory ¶
type Inventory struct {
Version uint32 `json:"version"`
Nonce string `json:"nonce"`
Timestamp int64 `json:"timestamp"`
Namespace string `json:"namespace"`
Name string `json:"name"`
WorkspaceUID string `json:"workspace_uid"`
VMUID string `json:"vm_uid"`
RevocationEpoch uint64 `json:"revocation_epoch"`
OS string `json:"os"`
Architecture string `json:"architecture"`
AgentVersion string `json:"agent_version"`
BuildSHA256 string `json:"build_sha256"`
ManagementMin uint16 `json:"management_min"`
ManagementMax uint16 `json:"management_max"`
UpdaterMin uint16 `json:"updater_min"`
UpdaterMax uint16 `json:"updater_max"`
MSI []InventoryMSI `json:"msi"`
Driver *InventoryDriver `json:"driver"`
PendingReboot bool `json:"pending_reboot"`
Attempt *InventoryAttempt `json:"attempt"`
}
Inventory is the authenticated machine report. The exact bytes are digested into expected_installed_inventory_sha256 at start; a report is evidence, not upgrade authority.
type InventoryAttempt ¶
type InventoryDriver ¶
type InventoryMSI ¶
type Journal ¶
type Journal struct {
// contains filtered or unexported fields
}
Journal is immutable between successfully persisted transitions.
func DecodeJournal ¶
func DecodeJournal(raw []byte, planDigest, checkpointDigest string, minimumSequence uint64) (*Journal, error)
DecodeJournal needs the admitted plan digest and a trusted checkpoint digest/ sequence floor. A self-reported hash is corruption detection, not authority.
func NewJournal ¶
func NewJournal(plan JournalPlan, owner uint64, now int64) (*Journal, error)
func (*Journal) Prepare ¶
func (j *Journal) Prepare(event JournalEvent, c JournalContext) (*JournalTransition, error)
func (*Journal) Recovery ¶
func (j *Journal) Recovery(c JournalContext) string
Recovery is advisory only. Active actions are observed/reconciled, never replayed; callers still need fresh native inventory and authenticated permits.
func (*Journal) Snapshot ¶
func (j *Journal) Snapshot() JournalSnapshot
type JournalAck ¶
type JournalAction ¶
type JournalBinding ¶
type JournalBinding struct {
AttemptID string `json:"attempt_id"`
Namespace string `json:"namespace"`
WorkspaceName string `json:"workspace_name"`
WorkspaceUID string `json:"workspace_uid"`
VMUID string `json:"vm_uid"`
RevocationEpoch uint64 `json:"revocation_epoch"`
ActorUID string `json:"actor_uid"`
RecordingID string `json:"recording_id"`
TargetSHA256 string `json:"target_sha256"`
PreviousSHA256 string `json:"previous_sha256"`
InventorySHA256 string `json:"inventory_sha256"`
}
JournalBinding must be supplied by authenticated admission/current identity, never reconstructed as authority from a guest journal or client annotation.
type JournalContext ¶
type JournalEvent ¶
type JournalEvent struct {
Kind string // begin, complete, cancel, rollback, observe_boot, claim, manual, recording_lost, finalize
Receipt *ActionReceipt
}
type JournalPlan ¶
type JournalPlan struct {
Binding JournalBinding `json:"binding"`
TargetProductCode string `json:"target_product_code"`
PreviousProductCode string `json:"previous_product_code"`
TargetDriverSHA256 string `json:"target_driver_sha256"`
PreviousDriverSHA256 string `json:"previous_driver_sha256"`
AllowReboot bool `json:"allow_reboot"`
}
JournalPlan is a projection of verified manifests and authenticated inventory. Its validation is structural, not publisher trust or installation permission.
func (JournalPlan) SHA256 ¶
func (p JournalPlan) SHA256() string
type JournalSnapshot ¶
type JournalSnapshot struct {
Version uint32 `json:"version"`
Plan JournalPlan `json:"plan"`
Sequence uint64 `json:"sequence"`
OwnerFence uint64 `json:"owner_fence"`
Phase string `json:"phase"`
Flow string `json:"flow"`
Step uint32 `json:"step"`
Active *JournalAction `json:"active"`
LastReceipt *ActionReceipt `json:"last_receipt"`
Mutated bool `json:"mutated"`
ServiceNeedsRestore bool `json:"service_needs_restore"`
CancelRequested bool `json:"cancel_requested"`
RebootCount uint32 `json:"reboot_count"`
WaitBootID string `json:"wait_boot_id"`
WaitingSince int64 `json:"waiting_since"`
StartedAt int64 `json:"started_at"`
UpdatedAt int64 `json:"updated_at"`
ExpiresAt int64 `json:"expires_at"`
CleanupResult string `json:"cleanup_result"`
Result string `json:"result"`
}
type JournalStore ¶
JournalStore must durably and atomically replace the checkpoint only if its current digest matches expected. Uncertain writes return an error, even if they might have committed. A native ACL/flush/lock adapter is still required.
type JournalTransition ¶
type JournalTransition struct {
// contains filtered or unexported fields
}
func (*JournalTransition) Bytes ¶
func (t *JournalTransition) Bytes() []byte
func (*JournalTransition) Commit ¶
func (t *JournalTransition) Commit(store JournalStore, c JournalContext, ack *JournalAck) (*Journal, *JournalAction, error)
Commit returns an action descriptor only after durable CAS and matching off-guest intent acknowledgment. Descriptors are not signed execution grants. Any lost/uncertain persistence reply returns no action: reload/reconcile.
func (*JournalTransition) SHA256 ¶
func (t *JournalTransition) SHA256() string
func (*JournalTransition) Sequence ¶
func (t *JournalTransition) Sequence() uint64
type Manifest ¶
type Manifest struct {
Version uint32 `json:"version"`
TargetID string `json:"target_id"`
OS string `json:"os"`
Architecture string `json:"architecture"`
AgentVersion string `json:"agent_version"`
BuildSHA256 string `json:"build_sha256"`
MSI MSI `json:"msi"`
Updater Updater `json:"updater"`
Driver *Driver `json:"driver,omitempty"`
Compatibility Compatibility `json:"compatibility"`
RollbackPredecessors []Predecessor `json:"rollback_predecessors"`
RebootPolicy string `json:"reboot_policy"`
}
type Predecessor ¶
type VerifiedInventory ¶
type VerifiedInventory struct {
// contains filtered or unexported fields
}
func VerifyInventory ¶
func VerifyInventory(raw, signature []byte, keyID, expectedNonce string, now int64, keys map[string]ed25519.PublicKey) (*VerifiedInventory, error)
VerifyInventory requires the independently minted nonce and current time in addition to a pinned agent identity keyring. Every string field is ASCII-bounded so the canonical re-encode matches serde_json byte for byte.
func (*VerifiedInventory) Metadata ¶
func (v *VerifiedInventory) Metadata() Inventory
Metadata returns a deep copy so availability callers cannot mutate the verified report behind the digest.
func (*VerifiedInventory) SHA256 ¶
func (v *VerifiedInventory) SHA256() string
type VerifiedManifest ¶
type VerifiedManifest struct {
// contains filtered or unexported fields
}
VerifiedManifest keeps its verified payload identities private. Metadata() returns a deep copy so display/availability callers cannot replace the hashes used by VerifyArtifact after publisher verification.
func Verify ¶
func Verify(raw, signature []byte, keyID, expectedDigest string, keys map[string]ed25519.PublicKey) (*VerifiedManifest, error)
Verify requires an operator-pinned manifest digest and independently supplied publisher keyring. No trust key or download URL comes from the signed body. Signatures cover the domain plus the exact raw bytes, including whitespace.
func (*VerifiedManifest) Metadata ¶
func (v *VerifiedManifest) Metadata() Manifest
func (*VerifiedManifest) SHA256 ¶
func (v *VerifiedManifest) SHA256() string
func (*VerifiedManifest) VerifyArtifact ¶
func (v *VerifiedManifest) VerifyArtifact(name string, reader io.Reader) error
VerifyArtifact reads at most the signed size plus one byte. It never buffers an entire installer, accepts trailing content, or trusts a caller's size/hash.