DEV Community

QuentinBarrett5281
QuentinBarrett5281

Posted on

Buyer Image Delivery After Purchase — Preserve Originals, Serve Moderated Crops

Short answer: serve a processed rendition to the buyer by default, preserve the original as an immutable private source, and release that original only when the purchase entitlement explicitly includes it. For a creator portfolio that turns customer-support images into square, landscape, and portrait placements, every delivered object must be traceable to the exact source revision, crop specification, and moderation decision that approved it.

The page that matters is not "image processing is slow." It is paid buyer received an unreviewed image rendition. The on-call needs the order ID, asset revision, moderation decision ID, rendition specification, and delivery result in one event. Anything less turns a customer-support incident into a dashboard scavenger hunt while fulfillment continues.

What should page the on-call?

Page on a confirmed policy bypass, not on every failed crop. A failed crop can leave fulfillment pending, retry safely, or enter review. Serving bytes whose moderation relationship cannot be proved crosses the delivery boundary and needs immediate action.

The earlier warning is a sustained rise in paid orders blocked because no approved rendition exists for the requested ratio. Group that signal by ratio and transform version. A global success percentage can remain green while a new 9:16 path fails every time; a dashboard that cannot say which page fired is mostly decoration.

Moderation coverage is a relationship, not a label. The decision covers an immutable source digest, while the served object is derived from that digest by a versioned transform. Replacing the source invalidates the decision. Silently changing the crop algorithm while retaining the same rendition key makes incident reconstruction guesswork.

Should an API serve buyers the original or a processed image?

Keep source preservation, transformation, and entitlement separate. The source is write-once and addressed by a digest or immutable version. A rendition record names its dimensions, fit mode, focus data, encoder settings, transform version, and source digest. An order grants access to a delivery class such as display_rendition or licensed_original; it should not grant broad access to a storage prefix.

A small decision function is easier to test than fallback behavior scattered through handlers:

package delivery

import "errors"

type Request struct {
    OrderPaid       bool
    OriginalAllowed bool
    WantOriginal    bool
    SourceDigest    string
    ReviewedDigest  string
    RenditionReady  bool
}

func ObjectClass(r Request) (string, error) {
    if !r.OrderPaid {
        return "", errors.New("order is not paid")
    }
    if r.SourceDigest == "" || r.SourceDigest != r.ReviewedDigest {
        return "", errors.New("source revision lacks moderation coverage")
    }
    if r.WantOriginal {
        if !r.OriginalAllowed {
            return "", errors.New("order does not license the original")
        }
        return "original", nil
    }
    if !r.RenditionReady {
        return "", errors.New("approved rendition is not ready")
    }
    return "rendition", nil
}
Enter fullscreen mode Exit fullscreen mode

No silent fallback. Stop there.

Issue a short-lived, order-scoped download capability only after this decision. Send the correct media type, use Content-Disposition to reflect viewing versus an authorized source download, and enforce access before handling byte ranges. A valid range response uses HTTP 206 Partial Content, as defined by RFC 9110, but status-code correctness cannot compensate for a missing authorization decision; the range handler must receive the already authorized immutable object identifier rather than resolve an object from buyer-controlled path data.

This approach has a real limitation: preserving originals increases retained data and expands the deletion surface. Teams unable to enforce private storage, lifecycle deletion, and narrow authorization should not expose original downloads at all. Processed-only storage reduces that burden, but it permanently removes the pixels needed for future aspect ratios and makes later licensing of the source impossible. The trade-off is explicit: operational control and future recropping justify retention only when the team can also prove deletion and access control. The delivery API should make that choice visible.

Treat each crop as a reviewable artifact

Smart cropping changes what the buyer sees. A source may pass review while a narrow crop removes context, centers sensitive material, or excludes the support agent's intended subject. Independently reviewing only a crop leaves an uncovered original if that original is later sold. The policy therefore needs explicit coverage for the source and for each deliverable representation it governs.

Define the supported ratio set before fulfillment. For example, exactly three specifications might cover the portfolio: 1:1 square, 16:9 landscape, and 9:16 portrait. Those are examples, not universal defaults. Arbitrary client dimensions create unbounded transform and moderation work, while an allowlist makes the coverage denominator knowable and prevents cache-cardinality surprises. Three requested outputs should produce three traceable review outcomes; two approvals and one missing record means the asset is not ready for all placements, even when a global dashboard rounds the completion rate into something reassuring.

Change Source review Rendition review Delivery action
Buyer retries the same order Valid Valid Reuse the authorized object
Crop specification changes Valid Stale Generate and review a new rendition
Source bytes change Stale Stale Review, regenerate, then review the crop
Original license is added Valid Unrelated Allow the source under the new entitlement

Retain the original because a later crop cannot recover discarded pixels. Retention is not exposure: keep the source private, detach public delivery names from storage paths, and apply the product's retention and deletion policy to source and derivatives together.

Instrument the evidence chain

The first useful metric sits at the final authorization branch. Count outcomes with low-cardinality reasons such as source_review_missing, rendition_review_missing, entitlement_denied, and rendition_not_ready. Put order IDs, asset IDs, and decision IDs in structured logs or traces, not metric labels. Otherwise monitoring becomes the next incident.

Measure moderation completion, rendition generation, fulfillment authorization, and byte delivery as separate boundaries. Correlate them with a trace ID and retain the decision IDs used at authorization time. A successful response is not sufficient evidence; the audit event needs to state which immutable object was authorized and why.

Test the signals by injecting a stale review and a mismatched digest outside production. Then verify that the alert identifies affected orders without exposing buyer data and links to an action that can stop delivery. This is also where the processed-default design earns its complexity: the response team can pause one rendition class without destroying the source or blocking an explicitly licensed original that remains covered.

Deploy crop changes as migrations. Generate a new rendition version, send it through the applicable review path, inspect crop-quality samples, and switch new fulfillment after coverage completes. Existing paid links should stay pinned to their authorized immutable rendition or be reauthorized explicitly. Mutating bytes behind a stable link weakens both audit evidence and buyer expectations.

The threshold can create its own incident

A zero-tolerance page for a proven moderation bypass is defensible because the event is customer-visible and policy-relevant. Zero tolerance for any missing rendition is noisy: asynchronous work, retries, and deliberate review holds are normal states. Use a warning for backlog growth while fulfillment remains blocked, then page when its age or rate threatens the service objective. Set that threshold from the fulfillment objective and observed baseline, not a round number borrowed from another service.

False positives cost more than interrupted sleep. Repeated pages teach responders to treat the moderation alarm as pipeline noise, which is how the one delivery violation that matters gets acknowledged late. Every page should name the violated invariant, point to the evidence chain, and offer a safe action such as pausing the affected rendition class.

Noise wins otherwise.

"Errors increased" is not enough.

The durable rule is preserve the original, serve an approved rendition by default, and expose the source only under an explicit purchase entitlement. Binding review decisions to immutable revisions keeps recropping possible and delivery reproducible. It also gives the person carrying the pager a fact they can act on at 3 a.m., rather than one more graph to interpret.

Further reading

The image-format guide helps select a delivery encoding; the HTTP specification defines media types, ranges, and content disposition semantics. The file-upload guidance covers storage and validation boundaries, while the metrics specification explains aggregation and attributes.

References

Top comments (0)