(type=CUSTOMER, customer_id=X) — customer's own overlay
A cross-route rule (route_id NULL) is scoped by product_category,
vendor_id, product_id and customer_id, at least one set. ADMIN-only
by CHECK; DENY-only by the admin service and the resolver view's
value = 'DENY'.
Mutable on currentVersionId, matcherHash, and deletedAt only. Every
change to the matcher, status, priority, value, or label/description
inserts a new product_activation_rule_version row and re-points
currentVersionId (and re-stamps matcherHash from the new version) in
the same transaction.
product_activation_rule_unique_tuple (scope columns + matcher_hash,
NULLS NOT DISTINCT, live rows) refuses a duplicate matcher; matcherHash is
denormalized here for it, and services surface it as DUPLICATE_MATCHER.
Activation rules — identity row. A route rule (
route_idset) has three valid tier shapes (CHECK-enforced):A cross-route rule (
route_idNULL) is scoped byproduct_category,vendor_id,product_idandcustomer_id, at least one set. ADMIN-only by CHECK; DENY-only by the admin service and the resolver view'svalue = 'DENY'.Mutable on
currentVersionId,matcherHash, anddeletedAtonly. Every change to the matcher, status, priority, value, or label/description inserts a newproduct_activation_rule_versionrow and re-pointscurrentVersionId(and re-stampsmatcherHashfrom the new version) in the same transaction.product_activation_rule_unique_tuple(scope columns +matcher_hash, NULLS NOT DISTINCT, live rows) refuses a duplicate matcher;matcherHashis denormalized here for it, and services surface it asDUPLICATE_MATCHER.