---
id: WF-COM-CAT-003
title: Save a record with managed pictures or files
trigger: >-
  A record save prepares files before opening its transaction and commits their attachments with the record.
  Cleanup handles unused copies and released references later.
product_area: commerce
module: catalog
revision: 1
status: draft
design_intent: confirmed
implementation_evidence: observed
inference: []
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-COM-CAT-003
  - CAP-COM-CAT-005
  - CAP-COM-CAT-006
moves:
  - STATE-COM-CAT-004
  - STATE-COM-CAT-003
crosses:
  - SVC-COM-CAT-catalog
  - SVC-COM-CAT-configuration
idempotency: >-
  Optional creation keys and read-version replacements govern record writes. Unchanged file references are
  reused rather than copied again.
concurrency: >-
  Asset preparation precedes the versioned parent transaction. A losing save rolls back and leaves its private
  prepared copies for discard.
hops:
  - 'n': 1
    actor_or_service: Catalog or configuration service
    action: Determine the record key and identify changed asset fields.
    anchor: 'services-commerce:modules/catalog/services/assets/catalog-assets.ts'
    seam: sync
    on_failure: Stop before copying if preparation inputs cannot be established.
    left_inconsistent: No prepared asset remains from this step.
    observer: The requesting person or service receives the result and any returned refusal.
    provenance: documented
    source: 'services-commerce:modules/catalog/services/persistence/product-categories.ts'
  - 'n': 2
    actor_or_service: Shared asset pipeline
    action: >-
      Prepare the primary image, gallery and private files through nested asset saves before the parent
      transaction begins.
    anchor: 'services-commerce:modules/catalog/services/persistence/product-listings.ts:prepareProductListingSave'
    seam: sync
    on_failure: Reject unreadable sources and leave any completed copies eligible for cleanup.
    left_inconsistent: Prepared copies may remain without an attached record.
    observer: The requesting person or service receives the result and any returned refusal.
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/e2e/product-categories.e2e.spec.js#answers 400 to a picture the
      pipeline cannot read as a file, creating nothing
  - 'n': 3
    actor_or_service: Catalog or configuration service
    action: >-
      Validate prepared references, write parent and child records, attach new files and detach replaced
      references in one transaction.
    anchor: 'services-commerce:modules/catalog/services/persistence/product-listings.ts:requireRowAssets'
    seam: sync
    on_failure: Roll back the save; preparation marks unused copies for eventual discard.
    left_inconsistent: Uncommitted copies await the scheduled cleanup.
    observer: The requesting person or service receives the result and any returned refusal.
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/integration/services/persistence/product-listings.integration.spec.js#refuses
      a gallery picture written past the pipeline (a reference the save never prepared)
  - 'n': 4
    actor_or_service: Catalog or configuration service
    action: 'Delete an eligible record and its owned children, releasing every retained asset reference.'
    anchor: 'services-commerce:modules/catalog/services/persistence/product-categories.ts:deleteProductCategory'
    seam: sync
    on_failure: Reject protected or referenced deletion without releasing assets.
    left_inconsistent: The original record and its asset attachments remain.
    observer: The requesting person or service receives the result and any returned refusal.
    provenance: test
    source: >-
      services-commerce:modules/catalog/tests/integration/services/persistence/product-categories.integration.spec.js#deletes
      the category with its memberships and detaches its picture; a second delete is 404
branches:
  - The current console accepts image web addresses; shared upload interaction remains deferred.
waits:
  - Released assets await a scheduled sweep running every fifteen minutes.
evidence:
  - >-
    services-commerce at c8b66a98: modules/catalog/services/assets/catalog-assets.ts;
    services/persistence/product-categories.ts, product-listings.ts;
    modules/configuration/services/persistence/stores.ts; docs/milestones/COMM-M1-set-up-what-you-sell.md
    (D11).
  - 'react-console at baf6dae3: components/commerce/catalog/image-field.tsx.'
controls: [TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-CRY-001, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-LOG-004, TC-LOG-005, TC-PI-001, TC-PI-003, TC-PI-005, TC-PRV-001, TC-PRV-002]
---

# Save a record with managed pictures or files

## What It Does

A record save prepares files before opening its transaction and commits their attachments with the record. Cleanup handles unused copies and released references later.

## The Flow

```mermaid
sequenceDiagram
  participant S as Staff
  participant M as Catalog or configuration service
  participant P as Asset pipeline
  participant D as Commerce database
  S->>M: save record with picture or file references
  M->>P: copy each new file
  P-->>M: permanent references (ready)
  M->>D: transaction: guard references, write record, attach new, detach old
  alt refused
    D-->>M: rolled back
    M-->>S: refusal (copies abandoned)
  else committed
    D-->>M: committed
    M-->>S: saved record
  end
```

## When Something Fails

Stop before copying if preparation inputs cannot be established. No prepared asset remains from this step. Reject unreadable sources and leave any completed copies eligible for cleanup. Prepared copies may remain without an attached record. Roll back the save; preparation marks unused copies for eventual discard. Uncommitted copies await the scheduled cleanup. Reject protected or referenced deletion without releasing assets. The original record and its asset attachments remain.

## Open Design Questions

The implemented recovery and concurrency behaviour above defines the current boundary. Any change to transaction scope or product authority requires a recorded decision.
