Validation
How to run a PDTF transaction through a validator, decode the errors, and validate verified-claims envelopes. The package wraps Ajv with the right keyword configuration so you don't have to assemble it yourself.
getValidator()
const { getValidator } = require('@pdtf/schemas');
const validate = getValidator(
'https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json',
['baspi5', 'nts2']
);
const ok = validate(transaction);
if (!ok) {
console.error(validate.errors);
}
Returns an Ajv-compiled validator. The Ajv instance is shared across calls and configured with:
allErrors: true— surface every validation error, not just the firststrictSchema: false— PDTF carries non-standard keywords likebaspi5Ref; strict mode would reject themdiscriminator: true— enables the OpenAPI-style discriminator pattern used inoneOfbranchesajv-formats— addsdate,date-time,email,uri, etc.
Decoding errors
Ajv error format. Each entry has instancePath, schemaPath, keyword, params, message.
// Example error from a missing required field
{
instancePath: '/propertyPack/priceInformation',
schemaPath: '#/properties/propertyPack/required',
keyword: 'required',
params: { missingProperty: 'price' },
message: "must have required property 'price'"
}
Useful patterns:
| You see | Likely cause | Fix |
|---|---|---|
must have required property 'X' |
Overlay made it required; base didn't | Add it, or drop the overlay if it doesn't apply |
must match exactly one schema in oneOf |
Discriminator field has no match, or matches more than one branch | Check the value of the discriminator (usually role, yesNo, capacity etc.) |
must be equal to one of the allowed values |
Enum violation | Look up the enum in the merged schema; case sensitivity matters |
strict mode: unknown keyword: "X" |
You configured Ajv strictly | Use getValidator rather than rolling your own Ajv instance |
validateVerifiedClaims()
PDTF transactions can be expressed as Verified Claims (W3C VC Data Model 2.0 envelopes). The package exports a dedicated validator for that case:
const { validateVerifiedClaims } = require('@pdtf/schemas');
const errors = validateVerifiedClaims(
verifiedClaimsData,
'https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json',
['baspi5']
);
if (errors.length === 0) {
console.log('All claims valid');
}
Each claim inside the VC envelope is validated against the merged PDTF
transaction schema at the path the claim describes (using its
credentialSubject path). Returns an array of error objects;
empty array means all claims passed.
See Verified claims for the envelope shape.
Validating a sub-path
For a producer who only emits one part of the transaction (e.g. just the
BASPI section), you don't need the whole base schema. getValidator
accepts a JSON Pointer path:
const { getValidator } = require('@pdtf/schemas');
const validate = getValidator(
BASE_ID,
['baspi5'],
'/properties/propertyPack/properties/priceInformation'
);
The validator now only checks the priceInformation sub-tree against the merged schema.
Performance
- Validator compilation is the expensive step — done once per
(schemaId, overlay-key, path)tuple, cached for re-use. - Validating a typical transaction (~5 KB JSON) against a single overlay takes < 1 ms after warm-up.
- Cache stats:
require('@pdtf/schemas').cacheStatsexposes hit/miss counts, useful for tuning long-running services.