Photo normalization architecture¶
Scope¶
Photo normalization is shared product knowledge. It is not merchant-specific unless a future rule explicitly depends on a concrete source_feed.
The historical runtime entry points remain:
ccx_norm_apply_photo_family_routing_v1()innorm/30-photo-family.php;ccx_norm_apply_photo_enrichment_v1()innorm/40-photo-enrichment.php.
Both files are compatibility facades. 90-offers-norm.php keeps calling them at the historical positions, so extraction does not change pipeline ordering.
Module layout¶
norm/products/photo/
├── routing/
│ ├── 10-v1.php
│ ├── 20-v2.php
│ ├── 30-v3.php
│ └── 40-accessory-types-v4.php
├── enrichment/
│ ├── 10-v1.php
│ ├── 20-v2.php
│ ├── 30-v3.php
│ └── 40-final-polish.php
└── 90-compose.php
The first extraction is deliberately stage-oriented rather than product-oriented. The historical V1/V2/V3/V4 and final-polish order is contractual because later passes repair or enrich results produced by earlier passes.
Current ownership¶
The routing stages currently own generic classification for camera, camera_accessory, optics, drone, drone_accessory, battery, and memory_card where those rules historically lived in the photo pipeline.
The enrichment stages currently own camera_body_type, lens_mount_norm, lens_family_norm, focal_length_norm, aperture_norm, drone_family_norm, and optics_family_norm enrichment.
battery and memory_card remain in the historical photo routing sequence for this structural extraction. Moving them to independent product domains is a separate behavioral/ownership refactor and must have its own contract and validation.
Ordering contract¶
Routing order is:
CCX_PHOTO_FAMILY_ROUTING_V1;CCX_PHOTO_FAMILY_ROUTING_V2;CCX_PHOTO_FAMILY_ROUTING_V3;CCX_PHOTO_ACCESSORY_TYPES_V4.
Enrichment order is:
CCX_PHOTO_ENRICHMENT_V1;CCX_PHOTO_ENRICHMENT_V2;CCX_PHOTO_ENRICHMENT_V3;CCX_PHOTO_ENRICHMENT_FINAL_POLISH_V1.
Do not reorder these passes while performing structural extraction. SQL predicates and update semantics must remain unchanged unless a separate behavior change is explicitly reviewed.
Merchant boundary¶
Brand/product names such as Canon, Nikon, Sony, Fujifilm, DJI, GoPro, Leica, Panasonic, Olympus, or Pentax are product knowledge and do not make a rule merchant-specific.
A rule belongs under norm/feed-rules/<feed>/ only when correctness depends on that source feed itself.
Validation¶
The structural boundary is characterized by tests/Runtime/PhotoProductBoundaryContractTest.php. Any future split by product family must preserve the legacy entry points and stage order until a dedicated migration intentionally changes them.