← back to Commercialrealestate
scripts/sources/fnma-cpm.js
61 lines
// sources/fnma-cpm.js — credentialed adapter for FANNIE MAE Condo Project Manager (CPM).
//
// PURPOSE: Fannie Mae's CPM holds per-complex condo-project approvals / rejections / conditions — beyond
// our HUD FHA-approved list (which only covers FHA). For the 'standard-condo' segment (run the complex
// through CPM for prior approvals) this is the authoritative warrantability source. CPM is credentialed
// and partly manual (lender portal). This adapter is the plug-in slot: once Steve provides CPM access,
// getProjectStatus(project) returns the real status; until then it is INERT and returns {available:false}.
//
// PLUG-IN CONTRACT:
// status() -> { available:boolean, needs?:string }
// getProjectStatus({ project, address, city, zip })
// -> { available:false, needs:string } // not configured
// -> { available:true, matched:boolean, status?:'Approved'|'Conditional'|
// 'Unavailable'|'Ineligible', date?:ISO, conditions?:string[] } // configured
//
// GATED: CPM access is Steve-provided (lender credential; some lookups are manual). Fabricates NOTHING.
'use strict';
const CREDENTIAL_ENV = 'FNMA_CPM_API_KEY'; // CPM credential / session token (or a marker that manual export is used)
const BASE_URL_ENV = 'FNMA_CPM_BASE_URL'; // CPM endpoint, when an API/export path is available
function readCredential() {
if (process.env[CREDENTIAL_ENV]) return { key: process.env[CREDENTIAL_ENV], baseUrl: process.env[BASE_URL_ENV] || null };
try {
const fs = require('fs'), path = require('path');
const env = fs.readFileSync(path.join(__dirname, '..', '..', '.env'), 'utf8');
const m = env.match(new RegExp('^' + CREDENTIAL_ENV + '=(.*)$', 'm'));
if (m) return {
key: m[1].replace(/['"]/g, '').trim(),
baseUrl: (env.match(new RegExp('^' + BASE_URL_ENV + '=(.*)$', 'm')) || [])[1]?.replace(/['"]/g, '').trim() || null
};
} catch (_) {}
return null;
}
const NEEDS = `Fannie Mae Condo Project Manager (CPM) access — an ${CREDENTIAL_ENV} (lender CPM credential / `
+ `session token, or a marker that lookups are done manually and exported) and optional ${BASE_URL_ENV}. `
+ `CPM is credentialed and partly manual; Steve provides lender access. Set in .env, or supply a periodic `
+ `CPM export this adapter can read.`;
async function status() {
const cred = readCredential();
return cred ? { available: true } : { available: false, needs: NEEDS };
}
// CPM project status for one complex. While uncredentialed, {available:false} -> the condo segment uses
// the HUD FHA-approved proxy only and labels it as such.
async function getProjectStatus({ project, address, city, zip } = {}) {
const cred = readCredential();
if (!cred) return { available: false, needs: NEEDS };
// --- INTEGRATION POINT (wire when CPM access exists) ------------------------------------------------
// CPM has no public API; integration is typically a credentialed lookup or a periodic export this
// adapter reads. Example (export-file path):
// const rec = lookupCpmExport({ project, zip }); // local CPM export keyed by project name + zip
// if (rec) return { available:true, matched:true, status:rec.status, date:rec.statusDate, conditions:rec.conditions };
return { available: true, matched: false, note: 'credential present; CPM lookup/export not yet wired' };
}
module.exports = { status, getProjectStatus, CREDENTIAL_ENV, BASE_URL_ENV, NEEDS };