# FAVO Reward Lifecycle V1.1 — Auto Unlock

## Purpose

Integrates the existing validated Reward Lifecycle V1 `UnlockService::evaluate()`
into the existing validated PurchaseService flow.

Target flow:

Purchase validation
-> server-side reward calculation
-> loyalty EARN
-> auto unlock evaluation
-> audit
-> COMMIT

The integration is deliberately narrow:
- existing PurchaseService security rules remain in place;
- existing transaction UUID idempotency remains in place;
- existing LoyaltyService remains unchanged;
- UnlockService remains the source of reward-cycle rules;
- no database migration is required;
- unlock evaluation runs before PurchaseService COMMIT;
- an idempotent retry returns before EARN/unlock and cannot create duplicate unlocks.

## Important

This package assumes the server currently contains:
- the Reward Lifecycle V1 `UnlockService.php`;
- the transaction security/idempotency PurchaseService;
- TransactionController as deployed during the FAVO V2 security work.

The deploy script validates expected source anchors and stops instead of making a
partial change if the current files differ materially.

## Deploy

Extract this package outside `/var/www/html/favo`, then:

```bash
cd /var/www/html/favo_reward_lifecycle_v1_1
chmod +x bin/deploy-reward-lifecycle-v1_1
./bin/deploy-reward-lifecycle-v1_1
```

The script creates a timestamped backup under:

`/var/www/html/favo/storage/backups/reward_lifecycle_v1_1_auto_unlock_TIMESTAMP`

## No migration

V1.1 uses the already-installed migration 009 and requires no new SQL migration.

## Test

Use a fresh transaction UUID for a real purchase test. Do not reuse an existing
production/test UUID if the intention is to test a new purchase.

Example route:

`?page=transaction_create`

The JSON response now includes:

`auto_unlocked`

For a purchase that crosses a reward threshold, this contains the unlock result.

For a repeated request using the same transaction UUID, `idempotent` must be `true`
and `auto_unlocked` must be empty.

## Atomicity

Auto Unlock is executed inside the existing PurchaseService database transaction.
If auto-unlock throws an error, the purchase and loyalty EARN are rolled back.

## Notes

The current Reward Lifecycle model is entitlement-based:
unlock/redeem does not deduct loyalty points. Point deduction, if desired, remains
a separate future redemption-side business rule.
