// Package forge defines the backend-neutral operations used by hosted delivery. package forge import ( "context" "io" ) // Backend provides the hosted operations needed by the shared delivery // workflow. Implementations own destination-specific rules and protocol // details; the shared workflow uses only the logical values and evidence in // this package. type Backend interface { // Preflight verifies credentials and access to the configured destination // using read-only operations. It does not depend on a source tag or release. Preflight(ctx context.Context) error // TagCommit returns the commit observed for the complete tag. TagCommit(ctx context.Context, tag string) (string, error) // FindRelease returns the release for the complete tag. A missing release // is reported with FailureNotFound. FindRelease(ctx context.Context, tag string) (Release, error) // CreateRelease creates the requested release and returns the protocol // evidence even when an error occurs. CreateRelease(ctx context.Context, request CreateReleaseRequest) (Release, WriteEvidence, error) // ListAssets returns the assets attached to the release identified by handle. ListAssets(ctx context.Context, releaseHandle any) ([]Asset, error) // OpenAsset opens the remote asset identified by handle. The caller owns and // must close the returned stream, including when reading it fails. OpenAsset(ctx context.Context, assetHandle any) (io.ReadCloser, error) // UploadAsset uploads content to the release identified by handle. The // backend borrows content for the duration of this call and must finish any // request or multipart work before returning; it must not close content. UploadAsset(ctx context.Context, releaseHandle any, filename string, content io.Reader) (WriteEvidence, error) } // Release contains the logical release properties used by shared delivery. // Handle is opaque to shared code and is interpreted only by the backend that // produced it. type Release struct { URL string Tag string Title string Body string Draft bool Prerelease bool Handle any } // CreateReleaseRequest contains the release properties requested by shared // delivery. type CreateReleaseRequest struct { Tag string Commit string Title string Body string Draft bool Prerelease bool } // Asset contains the remote properties needed to compare an attachment with a // declared local asset. Handle is opaque to shared code and is interpreted only // by the backend that produced it. type Asset struct { Filename string Size int64 Handle any } // PreflightFailureKind classifies a failure to verify destination settings, // credentials, or repository access. type PreflightFailureKind string const ( PreflightInvalidDestination PreflightFailureKind = "invalid_destination" PreflightMissingCredential PreflightFailureKind = "missing_credential" PreflightInvalidCredential PreflightFailureKind = "invalid_credential" PreflightInsufficientPermissions PreflightFailureKind = "insufficient_permissions" PreflightInaccessibleDestination PreflightFailureKind = "inaccessible_destination" PreflightUnavailable PreflightFailureKind = "unavailable" ) // PreflightFailure reports a classified credential or destination access // failure. Err retains the underlying cause for diagnostics and cancellation // identity. type PreflightFailure struct { Kind PreflightFailureKind Err error } func (f *PreflightFailure) Error() string { if f.Err != nil { return string(f.Kind) + ": " + f.Err.Error() } return string(f.Kind) } // Unwrap returns the cause of the preflight failure, if any. func (f *PreflightFailure) Unwrap() error { return f.Err } // FailureKind classifies a backend-neutral delivery operation failure. type FailureKind string const ( FailureInvalid FailureKind = "invalid_request" FailureNotFound FailureKind = "not_found" FailureUnauthorized FailureKind = "unauthorized" FailureConflict FailureKind = "conflict" FailureMalformed FailureKind = "malformed_response" FailureUnverifiable FailureKind = "unverifiable" FailureTransport FailureKind = "transport" FailureRejected FailureKind = "rejected" FailureUnknown FailureKind = "unknown" ) // Failure reports a backend-neutral operation failure. Backend-specific // status and operation details belong in Err. Err is retained for errors.Is // and errors.As inspection. type Failure struct { Kind FailureKind Err error } func (f *Failure) Error() string { if f.Err != nil { return string(f.Kind) + ": " + f.Err.Error() } return string(f.Kind) } // Unwrap returns the cause of the operation failure, if any. func (f *Failure) Unwrap() error { return f.Err } // WriteDisposition describes the backend's evidence about a write operation. type WriteDisposition string const ( WriteNotAttempted WriteDisposition = "not_attempted" WriteAccepted WriteDisposition = "accepted" WriteRejected WriteDisposition = "rejected" WriteConflict WriteDisposition = "conflict" WriteUncertain WriteDisposition = "uncertain" ) // WriteEvidence records whether a write was handed to the transport and what // its acknowledgment establishes. Accepted means the backend received and // decoded the required protocol acknowledgment; shared content checks still // apply. Uncertain means the outcome could not be established. Attempted marks // handoff to the transport and does not claim the server received the request. // Evidence remains meaningful when the operation also returns an error. type WriteEvidence struct { Attempted bool Disposition WriteDisposition }