# Indirect Goods Upgrade — Phase 13 Deployment, Cutover and Rollback

## Current readiness result

The current application environment passed the strict cutover audit on 2026-07-12:

- 10 required additive tables present.
- 3 parity/provenance migrations applied.
- 10 operational cutover permissions present.
- All 5 rollout flags enabled.
- 615 of 615 released request lines covered by fulfillments.
- 0 unlinked indirect issue movements.
- 0 duplicate fulfillment idempotency keys.
- Project reconciliation variance: 0.0000.
- 0 negative warehouse, project or FOC rows.
- 0 over-accounted fulfillments or allocations.

Backfill dry runs were idempotent:

- Fulfillments: 615 existing, 0 created, 0 exceptions.
- Consumption provenance: 1 existing link, 0 created, 0 exceptions.
- Both dry runs rolled back and retained zero variance.

## Pre-deployment ownership

Assign named owners before starting:

| Responsibility | Required owner |
|---|---|
| Go/no-go decision | Warehouse operations lead |
| Database backup and restore verification | Database administrator |
| Application deployment | Release engineer |
| Stock reconciliation sign-off | Inventory controller |
| Supervised workflow acceptance | Warehouse supervisor and project representative |
| Rollback decision | Operations lead plus release engineer |

Record backup locations, checksums, timestamps, release identifier and approvers in the deployment ticket. Do not store backup credentials in the repository.

## Deployment sequence

### 1. Back up and establish the baseline

1. Enter the approved maintenance window.
2. Take a full database backup using the organization's approved backup mechanism.
3. Back up uploaded issue, delivery and return documents, including `public/uploads` and the configured public storage disk.
4. Verify that both backups can be listed/read and record their checksums.
5. Export the pre-deployment reconciliation result:

```bash
php artisan indirect-goods:cutover-check --json
```

Stop if the backup cannot be verified or any readiness check fails.

### 2. Deploy additive code with features disabled

Set these values before warming application caches:

```dotenv
INDIRECT_GOODS_WAREHOUSE_ISSUE_ENABLED=false
INDIRECT_GOODS_DIRECT_DELIVERY_ENABLED=false
INDIRECT_GOODS_FOC_ISSUE_ENABLED=false
INDIRECT_GOODS_RETURNS_ENABLED=false
INDIRECT_GOODS_REPORTS_V2_ENABLED=false
```

Deploy the release, run additive migrations, seed permissions and clear/rebuild caches according to the normal release process:

```bash
php artisan migrate --force
php artisan db:seed --class=IndirectGoodsPermissionsSeeder --force
php artisan optimize:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache
```

Do not use `migrate:fresh`, `db:wipe`, destructive schema commands, or migration rollback for an operational rollback.

### 3. Backfill and reconcile

```bash
php artisan indirect-goods:backfill-fulfillments --dry-run
php artisan indirect-goods:backfill-consumption-links --dry-run
```

Review every exception. If both dry runs pass, execute the committed modes once:

```bash
php artisan indirect-goods:backfill-fulfillments --commit
php artisan indirect-goods:backfill-consumption-links --commit
php artisan indirect-goods:cutover-check
```

Committed commands are idempotent, but reruns still require reconciliation review.

### 4. Enable features one gate at a time

After each environment change, rebuild the configuration cache, perform the specified supervised scenario and rerun the readiness check.

| Gate | Flag | Supervised acceptance |
|---:|---|---|
| 1 | `INDIRECT_GOODS_WAREHOUSE_ISSUE_ENABLED=true` | Partial warehouse issue across at least two batches; verify warehouse/project/movement totals |
| 2 | `INDIRECT_GOODS_DIRECT_DELIVERY_ENABLED=true` | Supplier delivery with accepted and rejected quantities; verify no warehouse outflow |
| 3 | `INDIRECT_GOODS_FOC_ISSUE_ENABLED=true` | Serviceable FOC issue; prove quarantined conditions remain unavailable |
| 4 | `INDIRECT_GOODS_RETURNS_ENABLED=true` | Partial serviceable return and a quarantined-condition return; prove destination is indirect FOC only |
| 5 | `INDIRECT_GOODS_REPORTS_V2_ENABLED=true` | Compare screen, Excel/PDF and authoritative SQL totals for issues, returns and project stock |

Run after every gate:

```bash
php artisan config:cache
php artisan indirect-goods:cutover-check
php artisan test
```

Use `--require-enabled` only after all five gates are enabled.

## Go/no-go criteria

Proceed only when:

- Strict readiness exits successfully.
- Full tests pass.
- Released lines equal fulfillment coverage.
- All reconciliation and negative/over-accounting metrics are zero.
- Direct-goods comparison totals have no unexplained change.
- Warehouse issue, supplier delivery, FOC issue and FOC-only return scenarios are signed off.
- Issue and return documents render and retain their source references.

## Operational rollback

An operational rollback stops new activity; it does not erase completed stock transactions.

Disable flags in reverse order:

```dotenv
INDIRECT_GOODS_REPORTS_V2_ENABLED=false
INDIRECT_GOODS_RETURNS_ENABLED=false
INDIRECT_GOODS_FOC_ISSUE_ENABLED=false
INDIRECT_GOODS_DIRECT_DELIVERY_ENABLED=false
INDIRECT_GOODS_WAREHOUSE_ISSUE_ENABLED=false
```

Then rebuild the configuration cache and run the non-strict readiness check. Preserve all new tables and audit rows. Correct committed business transactions only through approved compensating operations with reasons and users; never delete fulfillments, movements, adjustments, deliveries or completed returns.

## Disaster restore

A database restore is permitted only for an approved full disaster rollback when application writes have been stopped and the operations lead accepts loss of post-backup transactions. Restore database and uploaded documents as one consistent recovery point, deploy the matching prior application release, verify checksums, and run both direct and indirect reconciliation before reopening access.

## Post-cutover handoff

Retain the pre/post readiness JSON, dry-run output, committed backfill output, full test output, supervised scenario document numbers and sign-offs in the deployment ticket. Phase 14 supplies the recurring monitoring controls after the observation window begins.

