distribution

package
v1.260819.0 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: MIT Imports: 48 Imported by: 0

Documentation

Overview

Package distribution inspects and prepares local iOS release-testing artifacts. It deliberately contains no account, keychain, network, or storage-provider operations.

Index

Constants

View Source
const (
	ContentTypeIPA      = "application/octet-stream"
	ContentTypeManifest = "application/xml"
	ContentTypeHTML     = "text/html; charset=utf-8"
)
View Source
const (

	// CodeSignatureScopeCompleteMainApp is the exact verification scope required
	// before a prepared bundle may be published.
	CodeSignatureScopeCompleteMainApp = "complete-main-app-code-resources-entitlements-and-profile-certificate-binding"
)
View Source
const (

	// MaxIPABytes bounds synchronous inspection, hashing, and preparation work.
	MaxIPABytes int64 = 8 << 30
)

Variables

View Source
var (
	ErrNotEligible         = errors.New("IPA metadata is not eligible for release-testing preparation")
	ErrBundleConflict      = errors.New("distribution bundle conflicts with existing output")
	ErrIPAIdentityMismatch = errors.New("IPA snapshot does not match expected identity")
)
View Source
var (
	// ErrPrivatePublishLinkExpired means an immutable private install lease can
	// no longer be verified and must be replaced by a newly authorized run.
	ErrPrivatePublishLinkExpired = errors.New("private publication link expired")
	// ErrPrivatePublishProfileExpired means the signed payload is no longer
	// usable for publication and must be rebuilt under a new plan.
	ErrPrivatePublishProfileExpired = errors.New("private publication profile expired")
	// ErrPrivatePublishConflict means exact immutable local or remote evidence
	// conflicts with the saved publication intent. Retrying cannot repair it.
	ErrPrivatePublishConflict = errors.New("private publication intent conflict")
	// ErrImmutableObjectConflict means an existing object at an exact key does
	// not match the expected immutable content identity.
	ErrImmutableObjectConflict = errors.New("immutable object conflict")
	// ErrVerificationContentConflict means a successful fetch returned bytes or
	// representation metadata that conflict with the immutable expected object.
	// Retrying cannot make that exact destination safe to reuse.
	ErrVerificationContentConflict = errors.New("published object content conflict")
)
View Source
var ErrObjectVerificationMismatch = errors.New("published object verification mismatch")

Functions

func ExecutePrivatePublishIntent

func ExecutePrivatePublishIntent(ctx context.Context, ipa io.ReadSeeker, descriptor PreparedDescriptor, options PublishOptions, intent PrivatePublishIntent) (PublishReceipt, SensitiveLinks, error)

ExecutePrivatePublishIntent converges exactly the saved destinations in IPA, manifest, page order. It never generates an identifier or presigned URL.

func NormalizePrefix

func NormalizePrefix(raw string) (string, error)

func PublicObjectURL

func PublicObjectURL(base, key string) (string, error)

func RedactedDirectInstallURL

func RedactedDirectInstallURL(links SensitiveLinks) string

RedactedDirectInstallURL returns the exact non-secret itms-services URL form used in a public receipt.

func RedactedInstallURL

func RedactedInstallURL(links SensitiveLinks) string

RedactedInstallURL returns the exact non-secret install-page URL form used in a public receipt. It is safe for logs and structured output.

func Reverify

func Reverify(ctx context.Context, verifier Verifier, receipt PublishReceipt, links SensitiveLinks, now time.Time) error

func ValidateBucket

func ValidateBucket(raw string) error

func ValidateDescriptorForPublish

func ValidateDescriptorForPublish(descriptor Descriptor) error

ValidateDescriptorForPublish is the canonical preparation-evidence gate for in-process consumers. It deliberately centralizes the exact verification scope so workflow and publisher code do not duplicate a security string.

func ValidateEndpoint

func ValidateEndpoint(raw string) (*url.URL, error)

func ValidatePrepareOptions

func ValidatePrepareOptions(options PrepareOptions) error

ValidatePrepareOptions validates optional metadata before preparation opens or writes any filesystem path.

func ValidatePublicBaseURL

func ValidatePublicBaseURL(raw string) (*url.URL, error)

Types

type Access

type Access string
const (
	AccessPrivate Access = "private"
	AccessPublic  Access = "public"
)

type App

type App struct {
	BundleID         string `json:"bundleId"`
	Title            string `json:"title"`
	Version          string `json:"version"`
	BuildNumber      string `json:"buildNumber"`
	MinimumOSVersion string `json:"minimumOSVersion,omitempty"`
}

type Artifact

type Artifact struct {
	RelativePath string `json:"relativePath,omitempty"`
	SizeBytes    int64  `json:"sizeBytes"`
	SHA256       string `json:"sha256"`
}

type CodeSignatureVerification

type CodeSignatureVerification struct {
	Status                              CodeSignatureVerificationStatus `json:"status"`
	Scope                               string                          `json:"scope,omitempty"`
	Reason                              string                          `json:"reason,omitempty"`
	SignerCertificateSHA256Fingerprints []string                        `json:"signerCertificateSha256Fingerprints,omitempty"`
}

type CodeSignatureVerificationStatus

type CodeSignatureVerificationStatus string
const (
	CodeSignatureVerified    CodeSignatureVerificationStatus = "verified"
	CodeSignatureInvalid     CodeSignatureVerificationStatus = "invalid"
	CodeSignatureNotVerified CodeSignatureVerificationStatus = "not-verified"
)

type CorruptObjectReplacer

type CorruptObjectReplacer interface {
	ReplaceCorrupt(context.Context, PutObject) (StoredObject, error)
}

type Descriptor

type Descriptor struct {
	SchemaVersion      string   `json:"schemaVersion"`
	Platform           string   `json:"platform"`
	DistributionMethod string   `json:"distributionMethod"`
	App                App      `json:"app"`
	Artifact           Artifact `json:"artifact"`
	Signing            Signing  `json:"signing"`
	Source             *Source  `json:"source,omitempty"`
}

type ExpectedIPA

type ExpectedIPA struct {
	SHA256    string
	SizeBytes int64
}

ExpectedIPA binds agent-driven preparation to an exact upstream artifact. SHA256 must be the lowercase hexadecimal digest of exactly SizeBytes bytes.

type HTTPVerifier

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

func NewHTTPVerifier

func NewHTTPVerifier(client *http.Client, timeout time.Duration) *HTTPVerifier

func NewHTTPVerifierWithEnvironmentTrust

func NewHTTPVerifierWithEnvironmentTrust(timeout time.Duration) (*HTTPVerifier, error)

NewHTTPVerifierWithEnvironmentTrust builds a verifier that honors the same AWS_CA_BUNDLE trust override used by the S3 SDK for private endpoints.

func (*HTTPVerifier) Verify

func (v *HTTPVerifier) Verify(ctx context.Context, verification VerifyRequest) error

type InspectOptions

type InspectOptions struct {
	IncludeDevices bool
	Now            time.Time
}

type Inspection

type Inspection struct {
	SchemaVersion      string      `json:"schemaVersion"`
	Platform           string      `json:"platform"`
	DistributionMethod string      `json:"distributionMethod"`
	App                App         `json:"app"`
	Artifact           Artifact    `json:"artifact"`
	Signing            Signing     `json:"signing"`
	Preparation        Preparation `json:"preparation"`
	EmbeddedTargets    []string    `json:"embeddedTargets,omitempty"`
}

func InspectIPA

func InspectIPA(file *os.File, size int64, options InspectOptions) (Inspection, error)

InspectIPA validates and reads deterministic metadata from an already-open regular IPA file. The file must remain open for the duration of the call.

func InspectIPAContext

func InspectIPAContext(ctx context.Context, file *os.File, size int64, options InspectOptions) (Inspection, error)

type ObjectStore

type ObjectStore interface {
	Ensure(context.Context, PutObject) (StoredObject, error)
	PresignGet(context.Context, string, time.Duration) (string, error)
}

type Preparation

type Preparation struct {
	MetadataEligible bool     `json:"metadataEligible"`
	Issues           []string `json:"issues"`
}

type PrepareOptions

type PrepareOptions struct {
	Root           string
	OutputDir      string
	Title          string
	Channel        string
	SourceRevision string
	SourceURL      string
}

type PrepareResult

type PrepareResult struct {
	BundlePath string     `json:"bundlePath"`
	Reused     bool       `json:"reused"`
	Descriptor Descriptor `json:"descriptor"`
}

func PrepareIPA

func PrepareIPA(file *os.File, size int64, options PrepareOptions) (result PrepareResult, resultErr error)

PrepareIPA validates an already-open IPA and publishes an immutable local bundle without replacing an existing destination.

func PrepareIPAContext

func PrepareIPAContext(ctx context.Context, file *os.File, size int64, options PrepareOptions) (result PrepareResult, resultErr error)

func PrepareIPAPath

func PrepareIPAPath(ctx context.Context, inputRoot rootfs.Root, ipaPath string, options PrepareOptions) (PrepareResult, error)

PrepareIPAPath opens a relative IPA path beneath inputRoot without following symlinks and prepares it with cancellation propagated through snapshotting and code-signature verification.

func PrepareIPAPathExact

func PrepareIPAPathExact(ctx context.Context, inputRoot rootfs.Root, ipaPath string, expected ExpectedIPA, options PrepareOptions) (PrepareResult, error)

PrepareIPAPathExact is the agent-facing preparation seam. It snapshots a relative, no-follow input and rejects it before inspection or output writes unless the private snapshot exactly matches expected.

type PreparedApp

type PreparedApp struct {
	BundleID         string `json:"bundleId"`
	Title            string `json:"title"`
	Version          string `json:"version"`
	BuildNumber      string `json:"buildNumber"`
	MinimumOSVersion string `json:"minimumOSVersion,omitempty"`
}

type PreparedArtifact

type PreparedArtifact struct {
	RelativePath string `json:"relativePath"`
	SHA256       string `json:"sha256"`
	SizeBytes    int64  `json:"sizeBytes"`
}

type PreparedBundle

type PreparedBundle struct {
	Descriptor       PreparedDescriptor
	DescriptorSHA256 string
	DescriptorSize   int64
	IPA              *os.File
	IPASHA256        string
	IPASize          int64
}

func LoadPreparedBundle

func LoadPreparedBundle(bundleDir string) (*PreparedBundle, error)

func LoadPreparedBundleContext

func LoadPreparedBundleContext(ctx context.Context, root rootfs.Root) (*PreparedBundle, error)

LoadPreparedBundleContext reads a prepared bundle through an already-pinned root. The caller owns root and must retain it for the complete publication workflow so a lexical path replacement cannot select a different bundle.

type PreparedCodeSignatureVerification

type PreparedCodeSignatureVerification struct {
	Status                              string   `json:"status"`
	Reason                              string   `json:"reason,omitempty"`
	Scope                               string   `json:"scope,omitempty"`
	SignerCertificateSHA256Fingerprints []string `json:"signerCertificateSha256Fingerprints,omitempty"`
}

type PreparedDescriptor

type PreparedDescriptor struct {
	SchemaVersion      string           `json:"schemaVersion"`
	Platform           string           `json:"platform"`
	DistributionMethod string           `json:"distributionMethod"`
	App                PreparedApp      `json:"app"`
	Artifact           PreparedArtifact `json:"artifact"`
	Signing            PreparedSigning  `json:"signing"`
	EmbeddedTargets    []string         `json:"embeddedTargets,omitempty"`
}

type PreparedSigning

type PreparedSigning struct {
	ProfileClass                         string                            `json:"profileClass"`
	ProfileUUID                          string                            `json:"profileUuid"`
	EmbeddedProfileSHA256                string                            `json:"embeddedProfileSha256"`
	TeamID                               string                            `json:"teamId"`
	ExpiresAt                            string                            `json:"expiresAt"`
	DeviceCount                          int                               `json:"deviceCount"`
	DeviceSetSHA256                      string                            `json:"deviceSetSha256"`
	ProfileCertificateSHA256Fingerprints []string                          `json:"profileCertificateSha256Fingerprints"`
	CodeSignatureVerification            PreparedCodeSignatureVerification `json:"codeSignatureVerification"`
	ProfileIntegrityVerification         PreparedCodeSignatureVerification `json:"profileIntegrityVerification"`
	ProfileTrustVerification             PreparedCodeSignatureVerification `json:"profileTrustVerification"`
}

func (*PreparedSigning) UnmarshalJSON

func (signing *PreparedSigning) UnmarshalJSON(data []byte) error

type PrivatePublishDocument

type PrivatePublishDocument struct {
	StoredObject
	Body []byte `json:"body"`
}

PrivatePublishDocument is an exact, persistable document publication. Body is encoded as base64 by encoding/json and belongs only in protected intent state because it may contain bearer URLs.

type PrivatePublishIntent

type PrivatePublishIntent struct {
	SchemaVersion     string                 `json:"schemaVersion"`
	CreatedAt         time.Time              `json:"createdAt"`
	PageExpiresAt     time.Time              `json:"pageExpiresAt"`
	DownloadExpiresAt time.Time              `json:"downloadExpiresAt"`
	CredentialLimit   *time.Time             `json:"credentialLimit,omitempty"`
	Bucket            string                 `json:"bucket"`
	Prefix            string                 `json:"prefix"`
	URLTTL            string                 `json:"urlTtl"`
	DownloadGrace     string                 `json:"downloadGrace"`
	LinkID            string                 `json:"linkId"`
	Artifact          StoredObject           `json:"artifact"`
	Manifest          PrivatePublishDocument `json:"manifest"`
	Page              PrivatePublishDocument `json:"page"`
	Links             SensitiveLinks         `json:"links"`
	App               PreparedApp            `json:"app"`
	Signing           ReceiptSigning         `json:"signing"`
}

PrivatePublishIntent contains every nondeterministic choice and generated byte required to converge a private publication after a crash. It must be persisted before ExecutePrivatePublishIntent is called.

func PreparePrivatePublishIntent

func PreparePrivatePublishIntent(ctx context.Context, descriptor PreparedDescriptor, options PublishOptions) (PrivatePublishIntent, error)

PreparePrivatePublishIntent performs every private-publication choice and presign before any remote object write. Callers must durably persist the returned intent before execution.

func (PrivatePublishIntent) Clone

Clone returns an independent intent suitable for validation tests and callers that must retain an immutable in-memory copy.

type ProfileClass

type ProfileClass string
const (
	ProfileClassUnknown     ProfileClass = "unknown"
	ProfileClassDevelopment ProfileClass = "development"
	ProfileClassAdHoc       ProfileClass = "ad-hoc"
	ProfileClassEnterprise  ProfileClass = "enterprise"
	ProfileClassAppStore    ProfileClass = "app-store"
)

type PublishOptions

type PublishOptions struct {
	Store           ObjectStore
	Verifier        Verifier
	Bucket          string
	Prefix          string
	Access          Access
	PublicBaseURL   string
	URLTTL          time.Duration
	DownloadGrace   time.Duration
	CredentialLimit time.Time
	Now             func() time.Time
	RandomID        func() (string, error)
}

type PublishReceipt

type PublishReceipt struct {
	SchemaVersion    string         `json:"schemaVersion"`
	Endpoint         string         `json:"endpoint"`
	DownloadEndpoint string         `json:"downloadEndpoint,omitempty"`
	PublicBaseURL    string         `json:"publicBaseUrl,omitempty"`
	Region           string         `json:"region"`
	AddressingStyle  string         `json:"addressingStyle"`
	Access           Access         `json:"access"`
	Bucket           string         `json:"bucket"`
	Prefix           string         `json:"prefix"`
	URLTTL           string         `json:"urlTtl,omitempty"`
	DownloadGrace    string         `json:"downloadGrace,omitempty"`
	Artifact         StoredObject   `json:"artifact"`
	Manifest         StoredObject   `json:"manifest"`
	Page             StoredObject   `json:"page"`
	InstallURL       string         `json:"installUrl"`
	DirectInstallURL string         `json:"directInstallUrl"`
	ExpiresAt        *time.Time     `json:"expiresAt,omitempty"`
	Verified         bool           `json:"verified"`
	App              PreparedApp    `json:"app"`
	Signing          ReceiptSigning `json:"signing"`
	ReceiptPath      string         `json:"receiptPath,omitempty"`
	LinkPath         string         `json:"linkPath,omitempty"`
}

type PutObject

type PutObject struct {
	Key         string
	Body        io.Reader
	SHA256      string
	SizeBytes   int64
	ContentType string
}

type ReceiptSigning

type ReceiptSigning struct {
	ProfileClass                   string                            `json:"profileClass"`
	ProfileUUID                    string                            `json:"profileUuid"`
	EmbeddedProfileSHA256          string                            `json:"embeddedProfileSha256"`
	TeamID                         string                            `json:"teamId"`
	ProfileExpiresAt               string                            `json:"profileExpiresAt"`
	DeviceCount                    int                               `json:"deviceCount"`
	DeviceSetSHA256                string                            `json:"deviceSetSha256"`
	ProfileCertificateFingerprints []string                          `json:"profileCertificateSha256Fingerprints"`
	ProfileIntegrityVerification   PreparedCodeSignatureVerification `json:"profileIntegrityVerification"`
	ProfileTrustVerification       PreparedCodeSignatureVerification `json:"profileTrustVerification"`
	CodeSignatureVerification      PreparedCodeSignatureVerification `json:"codeSignatureVerification"`
}

func (ReceiptSigning) MatchesPrepared

func (signing ReceiptSigning) MatchesPrepared(prepared PreparedSigning) bool

MatchesPrepared reports whether receipt signing facts exactly bind to a prepared descriptor without consuming raw device identifiers.

type S3Store

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

func NewS3Store

func NewS3Store(ctx context.Context, options S3StoreConfig) (*S3Store, time.Time, error)

func (*S3Store) CredentialSource

func (store *S3Store) CredentialSource() string

func (*S3Store) Ensure

func (store *S3Store) Ensure(ctx context.Context, input PutObject) (StoredObject, error)

func (*S3Store) PresignGet

func (store *S3Store) PresignGet(ctx context.Context, key string, ttl time.Duration) (string, error)

func (*S3Store) ReplaceCorrupt

func (store *S3Store) ReplaceCorrupt(ctx context.Context, input PutObject) (StoredObject, error)

ReplaceCorrupt conditionally replaces the exact object generation observed by a fresh HEAD. Matching metadata alone is insufficient after a full GET proved the body corrupt, while If-Match prevents overwriting a concurrent legitimate replacement.

type S3StoreConfig

type S3StoreConfig struct {
	Endpoint         string
	DownloadEndpoint string
	Region           string
	Bucket           string
	AddressingStyle  string
	HTTPClient       *http.Client
	RequestTimeout   time.Duration
}
type SensitiveLinks struct {
	SchemaVersion    string     `json:"schemaVersion"`
	InstallURL       string     `json:"installUrl"`
	DirectInstallURL string     `json:"directInstallUrl"`
	ArtifactURL      string     `json:"artifactUrl"`
	ManifestURL      string     `json:"manifestUrl"`
	ExpiresAt        *time.Time `json:"expiresAt,omitempty"`
}

type Signing

type Signing struct {
	ProfileClass                         ProfileClass              `json:"profileClass"`
	ProfileUUID                          string                    `json:"profileUuid,omitempty"`
	TeamID                               string                    `json:"teamId,omitempty"`
	ExpiresAt                            string                    `json:"expiresAt,omitempty"`
	DeviceCount                          int                       `json:"deviceCount"`
	DeviceSetSHA256                      string                    `json:"deviceSetSha256,omitempty"`
	EmbeddedProfileSHA256                string                    `json:"embeddedProfileSha256,omitempty"`
	ProfileCertificateSHA256Fingerprints []string                  `json:"profileCertificateSha256Fingerprints,omitempty"`
	Devices                              []string                  `json:"devices,omitempty"`
	ProfileIntegrityVerification         CodeSignatureVerification `json:"profileIntegrityVerification"`
	ProfileTrustVerification             CodeSignatureVerification `json:"profileTrustVerification"`
	CodeSignatureVerification            CodeSignatureVerification `json:"codeSignatureVerification"`
}

type Source

type Source struct {
	Channel  string `json:"channel,omitempty"`
	Revision string `json:"revision,omitempty"`
	URL      string `json:"url,omitempty"`
}

type StoredObject

type StoredObject struct {
	Key         string `json:"key"`
	SHA256      string `json:"sha256"`
	SizeBytes   int64  `json:"sizeBytes"`
	ContentType string `json:"contentType"`
	Status      string `json:"status"`
	// contains filtered or unexported fields
}

type Verifier

type Verifier interface {
	Verify(context.Context, VerifyRequest) error
}

type VerifyKind

type VerifyKind int
const (
	VerifyDocument VerifyKind = iota
	VerifyIPA
)

type VerifyRequest

type VerifyRequest struct {
	URL         string
	Kind        VerifyKind
	SHA256      string
	SizeBytes   int64
	ContentType string
}

Jump to

Keyboard shortcuts

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