compctl 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -0
- package/dist/commands/adverse.d.ts +6 -0
- package/dist/commands/adverse.d.ts.map +1 -0
- package/dist/commands/adverse.js +85 -0
- package/dist/commands/adverse.js.map +1 -0
- package/dist/commands/atr.d.ts +6 -0
- package/dist/commands/atr.d.ts.map +1 -0
- package/dist/commands/atr.js +131 -0
- package/dist/commands/atr.js.map +1 -0
- package/dist/commands/trid.d.ts +6 -0
- package/dist/commands/trid.d.ts.map +1 -0
- package/dist/commands/trid.js +68 -0
- package/dist/commands/trid.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/checks.d.ts +30 -0
- package/dist/lib/checks.d.ts.map +1 -0
- package/dist/lib/checks.js +256 -0
- package/dist/lib/checks.js.map +1 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/jest.config.js +8 -0
- package/package.json +28 -0
- package/src/commands/adverse.ts +90 -0
- package/src/commands/atr.ts +100 -0
- package/src/commands/trid.ts +64 -0
- package/src/index.ts +27 -0
- package/src/lib/checks.ts +279 -0
- package/src/types.ts +115 -0
- package/tests/checks.test.ts +159 -0
- package/tsconfig.json +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# compctl
|
|
2
|
+
|
|
3
|
+
Lending compliance checks for TRID, ATR/QM, HMDA, and ECOA. Part of the **LendCtl Suite**.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **TRID Timing** — LE/CD disclosure deadline tracking
|
|
8
|
+
- **ATR/QM Check** — Qualified mortgage determination
|
|
9
|
+
- **Adverse Action** — ECOA-compliant denial notices
|
|
10
|
+
- **Risk Flags** — Identify compliance issues early
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g compctl
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### Check TRID Timing
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
compctl trid --app-date 2026-02-20 --closing-date 2026-03-15
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Check ATR/QM Compliance
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
compctl atr --loan-amount 300000 --dti 42 --points-fees 5000
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Generate Adverse Action Notice
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# List standard reasons
|
|
36
|
+
compctl adverse --list-reasons
|
|
37
|
+
|
|
38
|
+
# Generate notice
|
|
39
|
+
compctl adverse --applicant "John Smith" --reasons "1,2,5"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Commands
|
|
43
|
+
|
|
44
|
+
### `compctl trid`
|
|
45
|
+
Check TRID timing compliance.
|
|
46
|
+
|
|
47
|
+
Options:
|
|
48
|
+
- `--app-date <date>` - Application date (required)
|
|
49
|
+
- `--le-date <date>` - Loan Estimate disclosure date
|
|
50
|
+
- `--cd-date <date>` - Closing Disclosure date
|
|
51
|
+
- `--closing-date <date>` - Scheduled closing date
|
|
52
|
+
|
|
53
|
+
### `compctl atr`
|
|
54
|
+
Check ATR/QM compliance.
|
|
55
|
+
|
|
56
|
+
Options:
|
|
57
|
+
- `--loan-amount <amount>` - Loan amount
|
|
58
|
+
- `--dti <percent>` - Debt-to-income ratio
|
|
59
|
+
- `--points-fees <amount>` - Points and fees
|
|
60
|
+
- `--neg-am` - Has negative amortization
|
|
61
|
+
- `--interest-only` - Has interest-only period
|
|
62
|
+
- `--balloon` - Has balloon payment
|
|
63
|
+
|
|
64
|
+
### `compctl adverse`
|
|
65
|
+
Generate adverse action notice.
|
|
66
|
+
|
|
67
|
+
Options:
|
|
68
|
+
- `--applicant <name>` - Applicant name
|
|
69
|
+
- `--reasons <codes>` - Reason codes (1-16) or text
|
|
70
|
+
- `--list-reasons` - Show standard reasons
|
|
71
|
+
|
|
72
|
+
## Compliance Regulations
|
|
73
|
+
|
|
74
|
+
### TRID (TILA-RESPA Integrated Disclosure)
|
|
75
|
+
- Loan Estimate within 3 business days of application
|
|
76
|
+
- Closing Disclosure 3 business days before closing
|
|
77
|
+
|
|
78
|
+
### ATR/QM (Ability to Repay / Qualified Mortgage)
|
|
79
|
+
- No risky features (neg-am, interest-only, balloon)
|
|
80
|
+
- Points and fees under 3% (for loans ≥$100k)
|
|
81
|
+
- DTI ≤43% for safe harbor
|
|
82
|
+
|
|
83
|
+
### ECOA (Equal Credit Opportunity Act)
|
|
84
|
+
- Specific reasons required for adverse action
|
|
85
|
+
- Maximum 4 primary factors
|
|
86
|
+
- Standard notices required
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT © Avatar Consulting
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adverse.d.ts","sourceRoot":"","sources":["../../src/commands/adverse.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,oBAAoB,IAAI,OAAO,CAkF9C"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* compctl adverse command - Generate adverse action notice
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createAdverseCommand = createAdverseCommand;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const checks_1 = require("../lib/checks");
|
|
9
|
+
function createAdverseCommand() {
|
|
10
|
+
const adverse = new commander_1.Command('adverse')
|
|
11
|
+
.description('Generate ECOA-compliant adverse action notice')
|
|
12
|
+
.option('--applicant <name>', 'Applicant name', 'Applicant')
|
|
13
|
+
.option('--app-date <date>', 'Application date', new Date().toISOString().split('T')[0])
|
|
14
|
+
.option('--creditor <name>', 'Creditor name', 'Lender')
|
|
15
|
+
.option('--creditor-address <addr>', 'Creditor address', '123 Main St')
|
|
16
|
+
.option('--reasons <codes>', 'Comma-separated reason codes (1-16) or text')
|
|
17
|
+
.option('--list-reasons', 'List standard adverse action reasons', false)
|
|
18
|
+
.option('--format <type>', 'Output format (json|text)', 'text')
|
|
19
|
+
.action(async (options) => {
|
|
20
|
+
if (options.listReasons) {
|
|
21
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
22
|
+
console.log('STANDARD ADVERSE ACTION REASONS');
|
|
23
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
24
|
+
checks_1.ADVERSE_ACTION_REASONS.forEach((reason, i) => {
|
|
25
|
+
console.log(`${(i + 1).toString().padStart(2)}. ${reason}`);
|
|
26
|
+
});
|
|
27
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let reasons = [];
|
|
31
|
+
if (options.reasons) {
|
|
32
|
+
const parts = options.reasons.split(',');
|
|
33
|
+
for (const part of parts) {
|
|
34
|
+
const trimmed = part.trim();
|
|
35
|
+
const num = parseInt(trimmed);
|
|
36
|
+
if (!isNaN(num) && num >= 1 && num <= checks_1.ADVERSE_ACTION_REASONS.length) {
|
|
37
|
+
reasons.push(checks_1.ADVERSE_ACTION_REASONS[num - 1]);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
reasons.push(trimmed);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const notice = (0, checks_1.generateAdverseAction)(options.applicant, options.appDate, options.creditor, options.creditorAddress, reasons);
|
|
45
|
+
if (options.format === 'json') {
|
|
46
|
+
console.log(JSON.stringify(notice, null, 2));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
50
|
+
console.log('NOTICE OF ADVERSE ACTION');
|
|
51
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
52
|
+
console.log('');
|
|
53
|
+
console.log(`Date: ${notice.decisionDate}`);
|
|
54
|
+
console.log(`To: ${notice.applicantName}`);
|
|
55
|
+
console.log('');
|
|
56
|
+
console.log(`Your application for credit dated ${notice.applicationDate} has been`);
|
|
57
|
+
console.log('denied based on the following reason(s):');
|
|
58
|
+
console.log('');
|
|
59
|
+
if (notice.reasons.length > 0) {
|
|
60
|
+
for (const reason of notice.reasons) {
|
|
61
|
+
console.log(` • ${reason}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(' [No specific reasons provided - COMPLIANCE WARNING]');
|
|
66
|
+
}
|
|
67
|
+
console.log('');
|
|
68
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
69
|
+
console.log('EQUAL CREDIT OPPORTUNITY ACT NOTICE');
|
|
70
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
71
|
+
console.log(notice.ecoaNotice);
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
74
|
+
console.log('FAIR CREDIT REPORTING ACT NOTICE');
|
|
75
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
76
|
+
console.log(notice.fcraNotice);
|
|
77
|
+
console.log('');
|
|
78
|
+
console.log(`${notice.creditorName}`);
|
|
79
|
+
console.log(`${notice.creditorAddress}`);
|
|
80
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
return adverse;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=adverse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adverse.js","sourceRoot":"","sources":["../../src/commands/adverse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atr.d.ts","sourceRoot":"","sources":["../../src/commands/atr.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,gBAAgB,IAAI,OAAO,CA0F1C"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* compctl atr command - Check ATR/QM compliance
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.createAtrCommand = createAtrCommand;
|
|
40
|
+
const commander_1 = require("commander");
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const checks_1 = require("../lib/checks");
|
|
43
|
+
function createAtrCommand() {
|
|
44
|
+
const atr = new commander_1.Command('atr')
|
|
45
|
+
.description('Check ATR/QM compliance')
|
|
46
|
+
.option('-f, --file <path>', 'Loan data JSON file')
|
|
47
|
+
.option('--loan-amount <amount>', 'Loan amount')
|
|
48
|
+
.option('--dti <percent>', 'Debt-to-income ratio')
|
|
49
|
+
.option('--points-fees <amount>', 'Total points and fees')
|
|
50
|
+
.option('--neg-am', 'Has negative amortization', false)
|
|
51
|
+
.option('--interest-only', 'Has interest-only period', false)
|
|
52
|
+
.option('--balloon', 'Has balloon payment', false)
|
|
53
|
+
.option('--prepay-penalty', 'Has prepayment penalty', false)
|
|
54
|
+
.option('--term <months>', 'Loan term in months', '360')
|
|
55
|
+
.option('--format <type>', 'Output format (json|table)', 'table')
|
|
56
|
+
.action(async (options) => {
|
|
57
|
+
let loan;
|
|
58
|
+
if (options.file) {
|
|
59
|
+
const content = fs.readFileSync(options.file, 'utf-8');
|
|
60
|
+
loan = JSON.parse(content);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
loan = {
|
|
64
|
+
loanId: 'CLI-INPUT',
|
|
65
|
+
applicationDate: new Date().toISOString().split('T')[0],
|
|
66
|
+
loanAmount: parseFloat(options.loanAmount || '300000'),
|
|
67
|
+
propertyValue: parseFloat(options.loanAmount || '300000') * 1.25,
|
|
68
|
+
interestRate: 6.5,
|
|
69
|
+
termMonths: parseInt(options.term),
|
|
70
|
+
monthlyPayment: 0,
|
|
71
|
+
dti: parseFloat(options.dti || '35'),
|
|
72
|
+
ltv: 80,
|
|
73
|
+
creditScore: 720,
|
|
74
|
+
pointsAndFees: parseFloat(options.pointsFees || '0'),
|
|
75
|
+
negativeAmortization: options.negAm,
|
|
76
|
+
interestOnly: options.interestOnly,
|
|
77
|
+
balloonPayment: options.balloon,
|
|
78
|
+
prepaymentPenalty: options.prepayPenalty,
|
|
79
|
+
borrowerIncome: 100000,
|
|
80
|
+
propertyType: 'single-family',
|
|
81
|
+
occupancy: 'primary',
|
|
82
|
+
loanPurpose: 'purchase',
|
|
83
|
+
loanType: 'conventional',
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const result = (0, checks_1.checkAtrQm)(loan);
|
|
87
|
+
if (options.format === 'json') {
|
|
88
|
+
console.log(JSON.stringify(result, null, 2));
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
92
|
+
console.log('ATR/QM COMPLIANCE CHECK');
|
|
93
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
94
|
+
console.log('');
|
|
95
|
+
const qmStatus = result.isQm ? '✓ QUALIFIED MORTGAGE' : '✗ NON-QM';
|
|
96
|
+
console.log(`QM Status: ${qmStatus}`);
|
|
97
|
+
if (result.qmType) {
|
|
98
|
+
console.log(`QM Type: ${result.qmType.toUpperCase()}`);
|
|
99
|
+
}
|
|
100
|
+
console.log('');
|
|
101
|
+
console.log('KEY METRICS');
|
|
102
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
103
|
+
const dtiStatus = result.dti <= result.dtiLimit ? '✓' : '⚠';
|
|
104
|
+
console.log(`${dtiStatus} DTI: ${result.dti}% (limit: ${result.dtiLimit}%)`);
|
|
105
|
+
const pfStatus = result.pointsAndFees <= result.pointsAndFeesLimit ? '✓' : '✗';
|
|
106
|
+
console.log(`${pfStatus} Points & Fees: $${result.pointsAndFees.toLocaleString()} (limit: $${result.pointsAndFeesLimit.toLocaleString()})`);
|
|
107
|
+
if (result.riskyFeatures.length > 0) {
|
|
108
|
+
console.log('');
|
|
109
|
+
console.log('RISKY FEATURES');
|
|
110
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
111
|
+
for (const feature of result.riskyFeatures) {
|
|
112
|
+
console.log(` ✗ ${feature}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (result.findings.length > 0) {
|
|
116
|
+
console.log('');
|
|
117
|
+
console.log('FINDINGS');
|
|
118
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
119
|
+
for (const f of result.findings) {
|
|
120
|
+
const icon = f.severity === 'critical' ? '🚨' : f.severity === 'major' ? '⚠' : 'ℹ';
|
|
121
|
+
console.log(`${icon} [${f.code}] ${f.description}`);
|
|
122
|
+
if (f.remediation)
|
|
123
|
+
console.log(` → ${f.remediation}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return atr;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=atr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atr.js","sourceRoot":"","sources":["../../src/commands/atr.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trid.d.ts","sourceRoot":"","sources":["../../src/commands/trid.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,iBAAiB,IAAI,OAAO,CAwD3C"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* compctl trid command - Check TRID timing compliance
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createTridCommand = createTridCommand;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const checks_1 = require("../lib/checks");
|
|
9
|
+
function createTridCommand() {
|
|
10
|
+
const trid = new commander_1.Command('trid')
|
|
11
|
+
.description('Check TRID timing compliance')
|
|
12
|
+
.requiredOption('--app-date <date>', 'Application date (YYYY-MM-DD)')
|
|
13
|
+
.option('--le-date <date>', 'Loan Estimate disclosure date')
|
|
14
|
+
.option('--cd-date <date>', 'Closing Disclosure date')
|
|
15
|
+
.option('--closing-date <date>', 'Scheduled closing date')
|
|
16
|
+
.option('--format <type>', 'Output format (json|table)', 'table')
|
|
17
|
+
.action(async (options) => {
|
|
18
|
+
const result = (0, checks_1.checkTridTiming)({
|
|
19
|
+
applicationDate: options.appDate,
|
|
20
|
+
leDisclosureDate: options.leDate,
|
|
21
|
+
cdDisclosureDate: options.cdDate,
|
|
22
|
+
closingDate: options.closingDate,
|
|
23
|
+
});
|
|
24
|
+
if (options.format === 'json') {
|
|
25
|
+
console.log(JSON.stringify(result, null, 2));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
29
|
+
console.log('TRID TIMING COMPLIANCE');
|
|
30
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
31
|
+
console.log('');
|
|
32
|
+
console.log(`Application Date: ${result.applicationDate}`);
|
|
33
|
+
if (result.leDisclosureDate)
|
|
34
|
+
console.log(`LE Disclosure: ${result.leDisclosureDate}`);
|
|
35
|
+
if (result.cdDisclosureDate)
|
|
36
|
+
console.log(`CD Disclosure: ${result.cdDisclosureDate}`);
|
|
37
|
+
if (result.closingDate)
|
|
38
|
+
console.log(`Closing Date: ${result.closingDate}`);
|
|
39
|
+
console.log('');
|
|
40
|
+
console.log('STATUS');
|
|
41
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
42
|
+
const leStatus = result.leCompliant ? '✓ COMPLIANT' : '✗ NON-COMPLIANT';
|
|
43
|
+
const cdStatus = result.cdCompliant ? '✓ COMPLIANT' : '✗ NON-COMPLIANT';
|
|
44
|
+
console.log(`Loan Estimate: ${leStatus}`);
|
|
45
|
+
if (result.daysUntilLeDeadline) {
|
|
46
|
+
console.log(` Days until deadline: ${result.daysUntilLeDeadline}`);
|
|
47
|
+
}
|
|
48
|
+
console.log(`Closing Disclosure: ${cdStatus}`);
|
|
49
|
+
if (result.daysUntilCdDeadline) {
|
|
50
|
+
console.log(` Days until deadline: ${result.daysUntilCdDeadline}`);
|
|
51
|
+
}
|
|
52
|
+
if (result.findings.length > 0) {
|
|
53
|
+
console.log('');
|
|
54
|
+
console.log('FINDINGS');
|
|
55
|
+
console.log('───────────────────────────────────────────────────────────────');
|
|
56
|
+
for (const f of result.findings) {
|
|
57
|
+
const icon = f.severity === 'critical' ? '🚨' : f.severity === 'major' ? '⚠' : 'ℹ';
|
|
58
|
+
console.log(`${icon} [${f.code}] ${f.description}`);
|
|
59
|
+
if (f.remediation)
|
|
60
|
+
console.log(` → ${f.remediation}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return trid;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=trid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trid.js","sourceRoot":"","sources":["../../src/commands/trid.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;GAGG;AAoBH,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* compctl - Lending compliance checks
|
|
5
|
+
* Part of the LendCtl Suite
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
19
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
const commander_1 = require("commander");
|
|
23
|
+
const trid_1 = require("./commands/trid");
|
|
24
|
+
const atr_1 = require("./commands/atr");
|
|
25
|
+
const adverse_1 = require("./commands/adverse");
|
|
26
|
+
const program = new commander_1.Command();
|
|
27
|
+
program
|
|
28
|
+
.name('compctl')
|
|
29
|
+
.description('Lending compliance checks (TRID, ATR/QM, HMDA, ECOA) - part of the LendCtl Suite')
|
|
30
|
+
.version('0.1.0');
|
|
31
|
+
program.addCommand((0, trid_1.createTridCommand)());
|
|
32
|
+
program.addCommand((0, atr_1.createAtrCommand)());
|
|
33
|
+
program.addCommand((0, adverse_1.createAdverseCommand)());
|
|
34
|
+
program.parse();
|
|
35
|
+
__exportStar(require("./lib/checks"), exports);
|
|
36
|
+
__exportStar(require("./types"), exports);
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAEA;;;GAGG;;;;;;;;;;;;;;;;AAEH,yCAAoC;AACpC,0CAAoD;AACpD,wCAAkD;AAClD,gDAA0D;AAE1D,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,kFAAkF,CAAC;KAC/F,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,IAAA,wBAAiB,GAAE,CAAC,CAAC;AACxC,OAAO,CAAC,UAAU,CAAC,IAAA,sBAAgB,GAAE,CAAC,CAAC;AACvC,OAAO,CAAC,UAAU,CAAC,IAAA,8BAAoB,GAAE,CAAC,CAAC;AAE3C,OAAO,CAAC,KAAK,EAAE,CAAC;AAEhB,+CAA6B;AAC7B,0CAAwB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compliance check implementations
|
|
3
|
+
*/
|
|
4
|
+
import { LoanData, TridTiming, AtrQmResult, ComplianceCheck, AdverseActionNotice } from '../types';
|
|
5
|
+
/**
|
|
6
|
+
* Check TRID timing requirements
|
|
7
|
+
*/
|
|
8
|
+
export declare function checkTridTiming(data: {
|
|
9
|
+
applicationDate: string;
|
|
10
|
+
leDisclosureDate?: string;
|
|
11
|
+
cdDisclosureDate?: string;
|
|
12
|
+
closingDate?: string;
|
|
13
|
+
}): TridTiming;
|
|
14
|
+
/**
|
|
15
|
+
* Check ATR/QM requirements
|
|
16
|
+
*/
|
|
17
|
+
export declare function checkAtrQm(loan: LoanData): AtrQmResult;
|
|
18
|
+
/**
|
|
19
|
+
* Check ECOA compliance and generate adverse action notice
|
|
20
|
+
*/
|
|
21
|
+
export declare function checkEcoa(loan: LoanData, decision: 'approved' | 'denied' | 'countered', reasons?: string[]): ComplianceCheck;
|
|
22
|
+
/**
|
|
23
|
+
* Generate ECOA-compliant adverse action notice
|
|
24
|
+
*/
|
|
25
|
+
export declare function generateAdverseAction(applicantName: string, applicationDate: string, creditorName: string, creditorAddress: string, reasons: string[]): AdverseActionNotice;
|
|
26
|
+
/**
|
|
27
|
+
* Standard adverse action reasons
|
|
28
|
+
*/
|
|
29
|
+
export declare const ADVERSE_ACTION_REASONS: string[];
|
|
30
|
+
//# sourceMappingURL=checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/lib/checks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAW,eAAe,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAE5G;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,UAAU,CAyEb;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,WAAW,CA4EtD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,GAAG,QAAQ,GAAG,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,eAAe,CAwB5H;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAAE,GAChB,mBAAmB,CAWrB;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,UAiBlC,CAAC"}
|