Validation Rules CatalogΒΆ
36 validation rules governing behavioural correctness in UC-BoK processes.
Validation Rules are process-level guards: they define what must be true before, during, or after an operation. Unlike Semantic Constraints (which express domain invariants), Validation Rules are contextual and process-scoped.
SummaryΒΆ
| Type | Count | Purpose |
|---|---|---|
| β¬οΈ Pre-Condition | 22 | What must be true before an operation can begin. |
| π§ Transition Guard | 9 | What must be true for a lifecycle state transition to be permitted. |
| β¬οΈ Post-Condition | 5 | What must be true after an operation has completed. |
| Severity | Count |
|---|---|
| π΄ Invariant | 32 |
| π‘ Constraint | 4 |
| π’ Guideline | 0 |
β¬οΈ Pre-ConditionΒΆ
What must be true before an operation can begin.
| Rule | Applies To | Context | Subject | Severity |
|---|---|---|---|---|
bopis-requires-channel |
bopis |
process | channel |
π΄ Invariant |
bopis-requires-store-inventory |
bopis |
process | inventory |
π΄ Invariant |
boris-requires-order-with-items |
boris |
process | order |
π΄ Invariant |
capture-payment-requires-authorization |
capture-payment |
service | payment |
π΄ Invariant |
checkout-requires-active-basket |
checkout |
process | basket |
π΄ Invariant |
checkout-requires-active-product |
checkout |
process | product |
π΄ Invariant |
close-order-requires-fulfillment-complete |
close-order |
service | fulfillment-order |
π΄ Invariant |
confirm-reservation-requires-reserved |
confirm-reservation |
service | reservation |
π΄ Invariant |
customer-registration-requires-no-duplicate |
customer-registration |
process | customer |
π΄ Invariant |
endless-aisle-requires-active-channel |
endless-aisle |
process | channel |
π΄ Invariant |
exchange-anywhere-requires-closed-order |
exchange-anywhere |
process | order |
π΄ Invariant |
issue-points-requires-closed-order |
issue-points |
service | order |
π‘ Constraint |
loss-prevention-intervention-requires-policy |
loss-prevention-case-handling |
process | loss-prevention-case |
π΄ Invariant |
loyalty-enrollment-requires-no-existing-account |
loyalty-enrollment |
process | loyalty-member |
π΄ Invariant |
publish-catalogue-requires-products |
publish-catalogue |
service | catalogue |
π΄ Invariant |
reserve-and-collect-requires-reservation |
reserve-and-collect |
process | reservation |
π΄ Invariant |
retail-media-requires-consent-aware-audience |
retail-media-attribution |
process | sponsored-offer |
π΄ Invariant |
return-anywhere-requires-return-window |
return-anywhere |
process | return |
π‘ Constraint |
self-checkout-requires-active-terminal |
self-checkout |
process | terminal |
π΄ Invariant |
ship-from-store-requires-routed-order |
ship-from-store |
process | order |
π΄ Invariant |
ship-to-store-requires-routed-order |
ship-to-store |
process | order |
π΄ Invariant |
voucher-redemption-requires-valid-voucher |
voucher-redemption |
process | voucher |
π΄ Invariant |
??? details "Rule Descriptions"
**`bopis-requires-channel`** β BOPIS requires an active digital channel (web or mobile) as the ordering touchpoint.
*Condition:* `channel.lifecycle = active AND channel.type in [web, mobile-app]`
**`bopis-requires-store-inventory`** β BOPIS requires available inventory at the selected store before an order can be placed and confirmed.
*Condition:* `inventory-item.available-quantity >= 1 at selected store`
**`boris-requires-order-with-items`** β BORIS (Buy Online Return In Store) requires a closed online order with at least one item eligible for in-store return.
*Condition:* `order.lifecycle = closed AND order.count(order-line) >= 1`
**`capture-payment-requires-authorization`** β Payment capture can only execute against a Payment in authorized state. Attempting to capture an unauthorized payment must fail.
*Condition:* `payment.lifecycle = authorized`
**`checkout-requires-active-basket`** β The checkout process requires an active basket with at least one basket line. An empty or abandoned basket cannot proceed to checkout.
*Condition:* `basket.lifecycle = active AND basket.count(basket-line) >= 1`
**`checkout-requires-active-product`** β Every product referenced by a basket line must be active. Discontinued or inactive products cannot be checked out.
*Condition:* `product.lifecycle = active for each basket-line`
**`close-order-requires-fulfillment-complete`** β An order can only be closed when all its fulfillment orders have been either delivered or cancelled.
*Condition:* `all fulfillment-orders for order.lifecycle in [delivered, cancelled]`
**`confirm-reservation-requires-reserved`** β A reservation can only be confirmed from reserved state. Confirming an already-confirmed or expired reservation must fail.
*Condition:* `reservation.lifecycle = reserved`
**`customer-registration-requires-no-duplicate`** β Customer registration must not create duplicate profiles. Uniqueness is enforced on email address or phone number.
*Condition:* `no customer exists with same email or phone`
**`endless-aisle-requires-active-channel`** β Endless Aisle requires an active store channel to initiate the extended catalogue order.
*Condition:* `channel.lifecycle = active AND channel.type = store`
**`exchange-anywhere-requires-closed-order`** β Exchange Anywhere requires a closed order with at least one exchangeable item.
*Condition:* `order.lifecycle = closed AND order.count(order-line) >= 1`
**`issue-points-requires-closed-order`** β Loyalty points should only be issued against a closed order with a corresponding loyalty member record.
*Condition:* `order.lifecycle = closed AND loyalty-member exists for customer`
**`loss-prevention-intervention-requires-policy`** β A loss-prevention intervention requires recorded evidence and an authorised intervention policy; an anomaly alone does not establish culpability.
*Condition:* `loss-prevention-case.evidence-reference is not null AND loss-prevention-case.intervention-policy is not null`
**`loyalty-enrollment-requires-no-existing-account`** β A customer can only be enrolled in loyalty once. Re-enrollment is not valid if an active loyalty account already exists.
*Condition:* `customer has no existing loyalty-member record`
**`publish-catalogue-requires-products`** β A catalogue can only be published if it contains at least one active product.
*Condition:* `catalogue.count(product) >= 1 AND all products.lifecycle = active`
**`reserve-and-collect-requires-reservation`** β Reserve and Collect can only proceed if the customer's reservation is confirmed and has not expired.
*Condition:* `reservation.lifecycle = confirmed AND reservation.expiry > now()`
**`retail-media-requires-consent-aware-audience`** β Sponsored-offer activation and attribution require an approved audience policy and applicable customer consent when personal data is used.
*Condition:* `sponsored-offer.audience-policy is not null AND customer-consent.lifecycle = active when personal data is used`
**`return-anywhere-requires-return-window`** β Return Anywhere should only be processed within the defined return policy window from the original order date.
*Condition:* `order.lifecycle = closed AND order.date within return-policy-window`
**`self-checkout-requires-active-terminal`** β Self-checkout requires an active self-checkout terminal. Regular POS terminals cannot be used for self-checkout flow.
*Condition:* `terminal.lifecycle = active AND terminal.type = self-checkout`
**`ship-from-store-requires-routed-order`** β Ship From Store can only begin after an order has been confirmed and a fulfillment order has been created by the routing engine.
*Condition:* `order.lifecycle = confirmed AND fulfillment-order.lifecycle = created`
**`ship-to-store-requires-routed-order`** β Ship To Store can only begin after order confirmation and fulfillment order creation.
*Condition:* `order.lifecycle = confirmed AND fulfillment-order.lifecycle = created`
**`voucher-redemption-requires-valid-voucher`** β Voucher redemption requires an active, non-expired voucher with remaining balance.
*Condition:* `voucher.lifecycle = active AND voucher.expiry > now() AND voucher.balance > 0`
π§ Transition GuardΒΆ
What must be true for a lifecycle state transition to be permitted.
| Rule | Subject | From | To | Condition Summary | Severity |
|---|---|---|---|---|---|
decision-execution-requires-approval |
decision-record |
approved |
executed |
decision-record.policy-reference is not null AND decision-reβ¦ | π΄ Invariant |
fulfillment-order-dispatch-requires-picking-complete |
fulfillment-order |
picking |
dispatched |
all picking-tasks.lifecycle = completed | π΄ Invariant |
loss-prevention-resolution-requires-outcome |
loss-prevention-case |
investigated |
resolved |
loss-prevention-case.resolution is not null | π΄ Invariant |
loyalty-account-close-requires-zero-balance |
loyalty-account |
active |
closed |
loyalty-account.balance = 0 | π‘ Constraint |
order-close-requires-all-fulfillment-done |
order |
confirmed |
closed |
all fulfillment-orders.lifecycle in [delivered, cancelled] | π΄ Invariant |
order-confirmed-requires-authorized-payment |
order |
validated |
confirmed |
payment.lifecycle = authorized | π΄ Invariant |
payment-void-from-authorized-only |
payment |
authorized |
voided |
order.lifecycle not in [closed] | π΄ Invariant |
product-deactivate-requires-no-active-basket-lines |
product |
active |
inactive |
no basket-line references this product with basket.lifecycleβ¦ | π‘ Constraint |
reservation-expire-from-reserved |
reservation |
reserved |
expired |
reservation.expiry < now() | π΄ Invariant |
??? details "Rule Descriptions"
**`decision-execution-requires-approval`** β A material automated decision can execute only after approved authority and policy reference are recorded.
*Condition:* `decision-record.policy-reference is not null AND decision-record.reviewed-by is not null`
**`fulfillment-order-dispatch-requires-picking-complete`** β A Fulfillment Order can only be dispatched when all its Picking Tasks have been completed.
*Condition:* `all picking-tasks.lifecycle = completed`
**`loss-prevention-resolution-requires-outcome`** β A loss-prevention case cannot resolve without a verified outcome that is auditable after the transaction.
*Condition:* `loss-prevention-case.resolution is not null`
**`loyalty-account-close-requires-zero-balance`** β A Loyalty Account should only be closed after its point balance has been exhausted or transferred.
*Condition:* `loyalty-account.balance = 0`
**`order-close-requires-all-fulfillment-done`** β An Order can only close when every associated Fulfillment Order has reached a terminal state.
*Condition:* `all fulfillment-orders.lifecycle in [delivered, cancelled]`
**`order-confirmed-requires-authorized-payment`** β An Order can only transition to confirmed state if its associated Payment has been successfully authorized.
*Condition:* `payment.lifecycle = authorized`
**`payment-void-from-authorized-only`** β A Payment can only be voided from authorized state and only if its associated Order has not been closed.
*Condition:* `order.lifecycle not in [closed]`
**`product-deactivate-requires-no-active-basket-lines`** β A Product should not be deactivated while it is referenced by an active basket line.
*Condition:* `no basket-line references this product with basket.lifecycle = active`
**`reservation-expire-from-reserved`** β A Reservation can only expire from reserved state and only when its expiry timestamp has passed.
*Condition:* `reservation.expiry < now()`
β¬οΈ Post-ConditionΒΆ
What must be true after an operation has completed.
| Rule | Applies To | Context | Severity |
|---|---|---|---|
authorize-payment-sets-authorized |
authorize-payment |
service | π΄ Invariant |
checkout-clears-basket |
checkout |
process | π΄ Invariant |
checkout-creates-order |
checkout |
process | π΄ Invariant |
loyalty-enrollment-creates-member |
loyalty-enrollment |
process | π΄ Invariant |
reserve-inventory-creates-reservation |
reserve-inventory |
service | π΄ Invariant |
??? details "Rule Descriptions"
**`authorize-payment-sets-authorized`** β After payment authorization, the Payment must be in authorized state with a valid authorization code.
*Condition:* `payment.lifecycle = authorized AND payment.authorization-code is not null`
**`checkout-clears-basket`** β After checkout completes, the originating basket must be in checked-out state and no longer mutable.
*Condition:* `basket.lifecycle = checked-out`
**`checkout-creates-order`** β After checkout completes, a confirmed Order must exist with the same number of lines as the originating basket.
*Condition:* `order.lifecycle = confirmed AND order.count(order-line) = basket.count(basket-line)`
**`loyalty-enrollment-creates-member`** β After loyalty enrollment, an active Loyalty Member record and a zero-balance Loyalty Account must exist for the customer.
*Condition:* `loyalty-member.lifecycle = active AND loyalty-account.balance = 0`
**`reserve-inventory-creates-reservation`** β After inventory reservation, a Reservation record must exist in reserved state with a valid expiry.
*Condition:* `reservation.lifecycle = reserved AND reservation.expiry > now()`
Generated from
catalogs/validation-rules.yamlΒ· Specification:specifications/015-semantic-model/constraint-vs-rule.md