# Credit Score Production Readiness

## Purpose

This checklist is the final production gate for credit-score V1.

Credit scoring remains **decision support only**. Nothing in this rollout may automatically approve or reject a loan, rewrite historical application snapshots, or silently change V1 weights, bands, thresholds, or overlays.

## Frozen V1 contract

Production V1 is expected to retain:

- score range: `300-850`;
- repayment behaviour: `40%`;
- loan history: `20%`;
- affordability/current exposure: `20%`;
- collateral: `10%`;
- profile/financial completeness: `5%`;
- conduct/control flags: `5%`;
- immutable application-time score history;
- branch-isolated current scores, histories, reports and recalculation;
- no gender, marital status, date of birth/age, ethnicity, religion, customer geographic location, NIN availability or similar personal traits as score inputs.

Any material formula change must ship as a new score version. Do not edit V1 in place.

## Deployment order

1. Deploy the application release containing all credit-score migrations.
2. Run migrations before serving the new report and review UI.
3. Clear and rebuild normal Laravel production caches according to the deployment procedure.
4. Run the production gates below.
5. Verify the scheduler is running every minute on the host.
6. Verify a lending user can view an in-scope score and cannot access an out-of-scope customer/history.
7. Verify the Portfolio and Calibration reports with an authorized branch selection.
8. Confirm the stale-score command completes without creating scheduled history noise.
9. Only then treat the credit-score feature as production-ready.

## Required production gates

Run on the deployed production release:

```bash
php artisan production:check
php artisan credit-score:production-check
php artisan database:performance-check
```

On the supported MySQL production database, also inspect representative plans:

```bash
php artisan database:performance-check --explain
```

The credit-score production gate verifies:

- the V1 score configuration is present and internally valid;
- required current-risk, immutable-history and loan-snapshot columns exist;
- required score/history indexes exist;
- `credit-score.view`, `credit-score.history`, and `credit-score.recalculate` exist;
- the loan application snapshot relationship is structurally available;
- the MySQL deployment has the snapshot foreign key.

A failed gate blocks the credit-score rollout. Do not work around it by deleting score history or weakening branch isolation.

## Test gate

Before deployment, run the full application suite. At minimum, the credit-score subset must pass:

```bash
php artisan test --filter=CreditScore
```

The final hardening suite also guards:

- exact V1 configuration integrity;
- protected/sensitive-field exclusion from scoring services;
- immutable application snapshots;
- branch and permission boundaries;
- bounded Portfolio and Calibration report query counts;
- score-history/reporting indexes;
- scheduled refresh without artificial history snapshots;
- calibration drift minimum-sample safeguards.

## Scheduler and stale-score safety net

The server must execute Laravel's scheduler every minute, for example through the deployment's normal cron/systemd mechanism:

```text
* * * * * php /path/to/artisan schedule:run
```

The application schedules `credit-scores:refresh-stale` daily. The command is a fallback for missed event-driven recalculations and updates the current risk profile without creating artificial immutable-history rows.

Operational spot check for one branch:

```bash
php artisan credit-scores:refresh-stale --branch=<branch-id> --hours=24
```

Do not schedule manual-history recalculation as a substitute for the stale refresh command.

## Smoke checks

### Customer and loan review

Confirm an authorized lending user can:

- see current score, band, confidence, thin-file/manual-review state and explanation;
- open immutable score history only with the history permission;
- recalculate only with the recalculation permission;
- see the immutable application score on loan review;
- see a newer current score separately when it differs.

Confirm the score itself does not approve or reject the application.

### Reports

Verify:

- `/credit-score-reports/portfolio` contains only authorized branches;
- `/credit-score-reports/calibration` contains only authorized branches;
- CSV exports enforce the corresponding report export permission;
- report page loads do not recalculate or mutate customer scores/history;
- application-score migration comparisons keep different score versions separate.

## Audit and explainability review

Before sign-off, sample at least one score from each populated band and confirm:

- explanation factors correspond to stored component data;
- confidence is displayed separately from score;
- thin-file customers are not presented as defaulters solely because history is limited;
- manual-review flags are advisory;
- manual recalculation produces the `credit_score.recalculated` audit event;
- application-time snapshots remain unchanged after later recalculation/payment activity.

## Calibration and V2 guardrail

The Calibration report is observational. Drift warnings are not instructions to change the model.

A future V2 should be considered only after there is enough mature repayment outcome data to compare score bands and versions reliably. Any V2 proposal should document sample size, arrears/default/write-off outcomes, branch effects, validation method, expected impact and rollback plan before changing configuration.

Historical V1 rows must remain V1 forever.

## Rollback

If application code must be rolled back after deployment:

- preserve `customer_credit_score_histories`;
- preserve `loans.application_credit_score_history_id` relationships;
- do not mass-delete current/history rows to make an older release fit;
- restore application compatibility through a reviewed forward migration or compatible release;
- keep V1 version labels unchanged.

Deleting immutable score history destroys the audit/calibration trail and is not an acceptable rollback strategy.

## Final sign-off

Credit-score V1 is ready for production only when:

- production configuration gate passes;
- credit-score production gate passes;
- database performance/index gate passes;
- credit-score tests pass;
- scheduler is confirmed running;
- branch-isolation and permission smoke checks pass;
- reports remain read-only;
- no V1 formula mutation is included in the deployment diff.
