divhanimajokweni-ctrl's picture
feat: submit ProofBridge Liner to LabLab AI AMD Developer Hackathon
93c7565
// prover/validator.js
// ProofBridge Liner β€” Deterministic Document Structure Gate
//
// First Principles Build:
// A South African deed of transfer is authentic if and only if it
// contains a fixed set of mandatory structural markers. Their presence
// is a necessary condition for legal validity β€” not sufficient, but necessary.
//
// Architecture:
// Pure function. Zero dependencies. Regex-based. Conjunction gate.
// All six rules must pass for documentValid = true.
//
// Integration:
// PDF Buffer β†’ extractTextFromPDF() β†’ validateDeed() β†’ scoreAsset()
// When documentValid = false, scorer clamps triggerScore to β‰₯ 0.80.
//
// Safety Kernel v1.0: FROZEN β€” no on-chain changes required.
const RULES = [
{
id: 'TITLE_DEED_NUMBER',
label: 'Title deed number present (e.g. T12345/2023)',
check: (text) => /T\d{5,}\/20\d{2}/i.test(text),
},
{
id: 'PROPERTY_DESCRIPTION',
label: 'Property description (ERF, FARM, or SECTIONAL TITLE)',
check: (text) =>
/\b(ERF\s+\d+|FARM\s+\d+|SECTIONAL\s+TITLE)\b/i.test(text),
},
{
id: 'VESTING_CLAUSE',
label: 'Vesting clause present (hereby transferred)',
check: (text) => /(hereby transferred|do hereby transfer)/i.test(text),
},
{
id: 'EXECUTION_DATE',
label: 'Execution date present and within last 50 years',
check: (text) => {
const match = text.match(
/(\d{1,2}\s+(January|February|March|April|May|June|July|August|September|October|November|December)\s+\d{4})/i
);
if (!match) return false;
const year = parseInt(match[0].match(/\d{4}/)[0], 10);
const currentYear = new Date().getFullYear();
return year >= currentYear - 50 && year <= currentYear;
},
},
{
id: 'REGISTRAR_SIGNATURE',
label: 'Registrar of Deeds signature block',
check: (text) => /REGISTRAR\s+OF\s+DEEDS/i.test(text),
},
{
id: 'MINIMUM_LENGTH',
label: 'Document text at least 500 characters',
check: (text) => text.length >= 500,
},
];
/**
* Validates extracted deed text against mandatory structural markers.
* @param {string} text - Extracted PDF text
* @returns {{ valid: boolean, failures: Array<{id: string, label: string}> }}
*/
function validateDeed(text) {
if (!text || typeof text !== 'string') {
return {
valid: false,
failures: [{ id: 'INPUT', label: 'No text provided' }],
};
}
const failures = [];
for (const rule of RULES) {
try {
if (!rule.check(text)) {
failures.push({ id: rule.id, label: rule.label });
}
} catch (err) {
failures.push({
id: rule.id,
label: `${rule.label} (error: ${err.message})`,
});
}
}
return {
valid: failures.length === 0,
failures,
};
}
module.exports = { validateDeed, RULES };