Reference
The rules
Two families of checks over one contract and one CSV. Linting reads only the contract; validation reads both. Every finding carries a stable code and one of three severities: error, warning, or info.
Lint rules (contract)
Linting needs only the contract, and it runs before any data is read. A structurally broken contract is not linted at all; it fails as DP-PARSE-000 instead.
| Code | Severity | What it catches |
|---|---|---|
DP-101 | error | A schema entry has no properties array, or a property object lacks a name. |
DP-102 | error | A property name is duplicated within the same schema. |
DP-103 | error | A property has a missing or unknown logicalType. |
DP-104 | error | A pattern is not a valid regular expression. |
DP-105 | error | A minimum or maximum is not a finite number, or minimum is greater than maximum. |
DP-106 | warning | An enum is present but empty, so it constrains nothing. |
DP-107 | warning | A format is present but not supported, so no format check runs. |
DP-108 | warning | required or unique is set on an object or array property, whose values are not type-checked. |
DP-109 | info | The contract has no top-level name. |
Validation rules (data)
Validation needs the contract and a CSV dataset, and it runs after linting. Every check that applies to a column runs on each non-empty cell, so one cell can produce more than one finding.
| Code | Severity | What it catches |
|---|---|---|
DP-201 | error | A required column is absent from the CSV header. |
DP-202 | info | A CSV header column is not declared in the contract. |
DP-203 | error | A value does not parse as the column's logical type. |
DP-204 | error | A value is empty in a required column. |
DP-205 | error | A non-empty value repeats in a unique column. |
DP-206 | error | A numeric value is below minimum. |
DP-207 | error | A numeric value is above maximum. |
DP-208 | error | A value does not match pattern. |
DP-209 | error | A value is not in enum. |
DP-210 | error | A value does not match format. |
Uniqueness and bounds. DP-205 compares values as exact, case-sensitive text, so 1 and 1.0 are different values and empty fields are never counted as duplicates. DP-206 and DP-207 fire only when the value parses to a finite number, so a type mismatch on a numeric column does not also produce a bounds finding.
Suppression and the cap (DP-250)
A large dataset can produce a finding on millions of cells. To keep a report usable, datapact caps validation findings at 50 per rule code per run. When a rule would report more, the first 50 are kept, the rest are suppressed, and one notice records how many were dropped. Contract lint findings are not capped.
| Code | Severity | What it catches |
|---|---|---|
DP-250 | info | More than 50 findings of one rule code were produced; the extras were suppressed. One notice is emitted per truncated code, and neither DP-250 nor DP-PARSE-000 is ever capped. |
Parse errors (DP-PARSE-000)
| Code | Severity | What it catches |
|---|---|---|
DP-PARSE-000 | error | The contract is not valid YAML or JSON, the contract is structurally invalid (the top level is not a mapping, schema is missing or not an array, or a property is not an object or lacks a name), or the CSV has no header row. |
When either the contract or the CSV fails to parse, the run yields a single DP-PARSE-000 with location -, always exits 2, and is never reported as clean, so a gate cannot pass on input the tool did not understand. JSON is parsed by the same YAML reader, so a JSON contract is valid input.
Logical types
A property's logicalType decides how each cell is interpreted. The alias type is accepted for the same field.
| logicalType | Accepted values |
|---|---|
string | Any non-empty UTF-8 text. A string value never produces a type mismatch. |
number | Any text JavaScript Number() parses to a finite value, for example 12, -3.5, 1e3, or 0x10. NaN and Infinity are mismatches. |
integer | A base-10 integer matching ^-?\d+$; a leading + is not accepted. |
boolean | true, false, yes, no, 1, or 0, case-insensitive. |
date | A calendar date, exactly YYYY-MM-DD, validated against the real calendar including leap years. |
date-time | Any text JavaScript Date.parse() accepts, such as an ISO 8601 date-time. The parser is permissive, not a strict ISO 8601 grammar. |
timestamp | Any text JavaScript Date.parse() accepts, the same as date-time. |
object | Not type-checked. Any non-empty text is accepted; the value is not parsed as JSON. |
array | Not type-checked. Any non-empty text is accepted; the value is not parsed as JSON. |
A logical type not in this table is DP-103.
Formats
A format is checked in addition to the logical type. When a property's format merely repeats its logical type, the format check is skipped because the type check already covers the value.
| format | Accepted values |
|---|---|
date | A calendar date, exactly YYYY-MM-DD. |
date-time | A value JavaScript Date.parse() accepts, as the date-time logical type. |
email | A value matching ^[^\s@]+@[^\s@]+\.[^\s@]+$: a non-empty local part, an @, and a dotted domain with no whitespace. |
uri | A value the URL constructor accepts, which requires an absolute URL with a scheme and no whitespace. |
uuid | A canonical hyphenated UUID, [0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}. |
ipv4 | Four groups of one to three decimal digits, each 0–255, separated by .. Leading zeros are accepted. |
A format not in this table is DP-107, and no format check runs for that property.
The empty-value rule
A field is empty when it has zero length; both an unquoted empty field and a quoted empty field ("") are empty, while a field of only whitespace is not. The rule differs by column:
- In a required column, an empty field is
DP-204, and no further per-cell check runs for that field. - In an optional column, an empty field is skipped by the type, pattern, enum, format, minimum, maximum, and uniqueness checks. An empty cell in an optional column is never an error.
This is what lets a sparse column validate cleanly: absence is not a type error unless the contract marks the column required.
How a run is checked
The pipeline is static and has no warehouse step.
-
Parse
The contract is read as YAML or JSON; the CSV is read per RFC 4180. A failure here becomes a single
DP-PARSE-000and exit code2. -
Lint
The contract alone is checked for duplicate names, unknown types, bad patterns, invalid bounds, empty enums, and unknown formats.
-
Validate
Each CSV cell is checked against its property: presence, type, emptiness, uniqueness, bounds, pattern, enum, and format.
-
Report
Print text or JSON, write SARIF 2.1.0, and exit
0,1,2, or3for CI.
Try the lint here
This contract is deliberately broken. Lint it in the browser and watch the contract rules fire.
Nothing linted yet.