supportupload

package
v1.0.144 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package supportupload is the appliance-side client for M6 "Optional secure upload" (docs/support/SECURE-UPLOAD-ARCHITECTURE.md §4): a resumable, SSRF-guarded, chunked, outbound-only HTTPS uploader to a TAC upload gateway.

It is a PURE ENGINE — it opens no connections on its own and is wired to no trigger. The caller supplies the (already E2E-encrypted) bundle bytes and the per-bundle identity; the client performs init → offset-idempotent chunk PUTs → complete, and returns the gateway's signed receipt. The queue/state machine and the per-bundle consent gate that decide WHETHER and WHEN to call it live in later slices; nothing here can cause egress until something invokes it.

Every outbound dial is SSRF-guarded at the network layer (ssrf.SafeDialContext checks the post-resolution address, closing the DNS-rebind window) and on every redirect hop (ssrf.PrivateHost) — a compromised or misconfigured origin cannot be pointed at internal infrastructure.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

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

Client is a resumable, SSRF-guarded upload client. Safe for sequential use by one uploader; the queue serializes per-bundle transfers.

func NewClient

func NewClient(cfg Config) (*Client, error)

NewClient validates the origin (https + host) and builds an SSRF-guarded client: the transport dials only public resolved addresses (ssrf.SafeDialContext) and every redirect hop is re-checked. Inline url.Parse + scheme + host so the guard is visible at the construction boundary.

func (*Client) Complete

func (c *Client) Complete(ctx context.Context, uploadID, bundleSHA256 string) (Receipt, error)

Complete finalizes the upload. The gateway re-verifies bundleSHA256 against the bytes it received and returns the signed receipt; Complete ALSO re-checks the receipt's hash equals the expected bundleSHA256 so EVERY completion path — the Upload convenience wrapper and the queue's direct Init/Status/PutChunk/Complete resume path — rejects a corrupted or mis-issued receipt identically.

func (*Client) Init

func (c *Client) Init(ctx context.Context, m Meta) (uploadID string, chunkSize int64, err error)

Init opens an upload session and returns its id + the gateway-chosen chunk size.

func (*Client) PutChunk

func (c *Client) PutChunk(ctx context.Context, uploadID string, offset int64, chunk []byte) (receivedOffset int64, err error)

PutChunk uploads one chunk at the given offset. Idempotent per offset (a re-sent offset is a no-op on the gateway), so a retry after a drop is safe. Returns the gateway's new received offset.

func (*Client) Status

func (c *Client) Status(ctx context.Context, uploadID string) (receivedOffset int64, err error)

Status returns the gateway's current received offset — the resume point after a dropped connection or a process restart.

func (*Client) Upload

func (c *Client) Upload(ctx context.Context, m Meta, ra io.ReaderAt, size int64) (Receipt, error)

Upload runs the full resumable transfer of ra[0:size] and returns the signed receipt. It consults the gateway's received offset first, so re-invoking it on the same freshly-init'd session only sends missing chunks; cross-restart resume is driven by the queue via the exposed Init/Status/PutChunk/Complete methods. The receipt hash is re-checked against meta.BundleSHA256 (defense in depth over the gateway's own complete-time check).

type Config

type Config struct {
	Origin     string        // TAC upload base URL (https)
	Credential string        // per-appliance bearer credential (tenant-scoped)
	Timeout    time.Duration // per-request timeout (default 60s)
}

Config constructs a Client.

type GatewayError

type GatewayError struct {
	Status int
	Body   string
}

GatewayError is returned for a non-2xx gateway response, preserving the status so the caller (queue) can classify entitlement/format/hash rejections vs transient 5xx for retry decisions.

func (*GatewayError) Error

func (e *GatewayError) Error() string

type Meta

type Meta struct {
	CaseID       string `json:"case_id"`
	BundleID     string `json:"bundle_id"`
	BundleSHA256 string `json:"bundle_sha256"`
	Size         int64  `json:"size"`
	KeyID        string `json:"key_id,omitempty"`
}

Meta is the per-bundle identity sent at init (SECURE-UPLOAD-ARCHITECTURE.md §4). BundleSHA256 is the hash of the bytes being uploaded (the encrypted bundle); the gateway re-verifies it at complete and echoes it in the receipt.

type Receipt

type Receipt struct {
	CaseID       string `json:"case_id"`
	BundleID     string `json:"bundle_id"`
	BundleSHA256 string `json:"bundle_sha256"`
	ReceivedAt   string `json:"received_at"`
	Sig          string `json:"sig"`
}

Receipt is the signed proof the gateway returns from :complete.

Jump to

Keyboard shortcuts

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