@sungen/driver-data-factory 3.2.10-beta.6 → 3.2.12-beta.10
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/common/experience/auth-account-states.yaml +19 -0
- package/common/field-types/currency.yaml +10 -10
- package/common/field-types/email.yaml +19 -16
- package/common/field-types/jp/katakana.yaml +12 -12
- package/common/field-types/number-float.yaml +10 -10
- package/common/field-types/number-integer.yaml +12 -12
- package/common/field-types/password.yaml +22 -22
- package/common/field-types/phone.yaml +14 -14
- package/common/field-types/postcode.yaml +8 -8
- package/common/field-types/string.yaml +11 -11
- package/common/security/broken-auth.yaml +6 -6
- package/common/security/idor.yaml +5 -5
- package/common/security/input-validation.yaml +5 -5
- package/common/security/sqli.yaml +7 -7
- package/common/security/upload.yaml +7 -7
- package/common/security/xss.yaml +9 -9
- package/common/techniques/boundary.yaml +4 -4
- package/common/techniques/decision-table.yaml +4 -4
- package/common/techniques/equivalence.yaml +4 -4
- package/common/techniques/state-transition.yaml +4 -4
- package/package.json +3 -3
- package/src/applicability.ts +80 -0
- package/src/boundary.ts +319 -0
- package/src/catalog-loader.ts +104 -18
- package/src/cli.ts +233 -14
- package/src/contract.ts +93 -0
- package/src/crosscheck.ts +149 -0
- package/src/detect.ts +122 -0
- package/src/fixture.ts +111 -0
- package/src/generator.ts +231 -98
- package/src/index.ts +17 -2
- package/src/lint.ts +31 -16
- package/src/readme.ts +52 -0
- package/src/sensor.ts +32 -4
- package/src/state.ts +225 -0
- package/src/types.ts +82 -1
- package/src/validate.ts +77 -0
package/src/validate.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data Factory — the deterministic data-quality validator (the Driver's contribution to the harness).
|
|
3
|
+
*
|
|
4
|
+
* `lint.ts` answers "is the coverage enough?" (≥1 valid, boundary present, error codes mapped).
|
|
5
|
+
* This module answers the harder question both reviews flagged: "is each generated value SEMANTICALLY
|
|
6
|
+
* correct?" — i.e. does a value labeled `valid` actually satisfy the constraints, and does a value
|
|
7
|
+
* labeled `invalid` actually violate them? It is the machine oracle a future Master "Data Gate"
|
|
8
|
+
* (see docs/spec/data-factory-quality-roadmap.md) calls; today it powers the golden tests and the
|
|
9
|
+
* `sungen data validate` CLI. Pure + deterministic — no AI, no runtime.
|
|
10
|
+
*/
|
|
11
|
+
import type { Catalog, SelectionContext } from './types';
|
|
12
|
+
import { expandFieldMap, type FieldMap, type FieldDef, type ExpandedField, type ExpandedPoint } from './generator';
|
|
13
|
+
import { satisfiesConstraints } from './boundary';
|
|
14
|
+
|
|
15
|
+
export interface ValidationFinding {
|
|
16
|
+
field: string;
|
|
17
|
+
pointId: string;
|
|
18
|
+
severity: 'error' | 'warn';
|
|
19
|
+
code: 'VALUE_NOT_VALID' | 'INVALID_LOOKS_VALID';
|
|
20
|
+
message: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Validate the values a set of expanded points, given the effective constraints for that field. */
|
|
24
|
+
export function validatePoints(field: string, type: string | undefined, points: ExpandedPoint[], c: Record<string, any>): ValidationFinding[] {
|
|
25
|
+
const out: ValidationFinding[] = [];
|
|
26
|
+
if (!type) return out;
|
|
27
|
+
for (const p of points) {
|
|
28
|
+
if (p.value == null) continue; // open/todo — lint handles these
|
|
29
|
+
const oracle = satisfiesConstraints(type, p.value, c);
|
|
30
|
+
if (oracle == null) continue; // no length/range constraint to judge against
|
|
31
|
+
if (p.expectedValidity === 'valid' && oracle === false) {
|
|
32
|
+
out.push({
|
|
33
|
+
field, pointId: p.id, severity: 'error', code: 'VALUE_NOT_VALID',
|
|
34
|
+
message: `${p.id}: value ${JSON.stringify(p.value)} is expected VALID but violates the field constraints (${describe(type, c)})`,
|
|
35
|
+
});
|
|
36
|
+
} else if (p.expectedValidity === 'invalid' && oracle === true && p.synthesized) {
|
|
37
|
+
// Only second-guess a SYNTHESIZED (boundary/range) invalid: its whole claim is about range, so
|
|
38
|
+
// satisfying the range means the boundary was mis-synthesized. Literal charset/format invalids and
|
|
39
|
+
// security payloads legitimately pass the length oracle — not a finding.
|
|
40
|
+
out.push({
|
|
41
|
+
field, pointId: p.id, severity: 'warn', code: 'INVALID_LOOKS_VALID',
|
|
42
|
+
message: `${p.id}: value ${JSON.stringify(p.value)} is expected INVALID (out of range) but satisfies the constraints (${describe(type, c)}) — the boundary was mis-synthesized`,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function describe(type: string, c: Record<string, any>): string {
|
|
50
|
+
const parts: string[] = [];
|
|
51
|
+
if (Number.isFinite(c.minLength ?? c.length)) parts.push(`minLen=${c.minLength ?? c.length}`);
|
|
52
|
+
if (Number.isFinite(c.maxLength ?? c.length)) parts.push(`maxLen=${c.maxLength ?? c.length}`);
|
|
53
|
+
if (Number.isFinite(c.min)) parts.push(`min=${c.min}`);
|
|
54
|
+
if (Number.isFinite(c.max)) parts.push(`max=${c.max}`);
|
|
55
|
+
if (Number.isFinite(c.maxLocal)) parts.push(`maxLocal=${c.maxLocal}`);
|
|
56
|
+
if (Number.isFinite(c.maxTotal)) parts.push(`maxTotal=${c.maxTotal}`);
|
|
57
|
+
if (Number.isFinite(c.decimalPlaces)) parts.push(`decimalPlaces=${c.decimalPlaces}`);
|
|
58
|
+
return parts.join(', ') || type;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Validate a whole field-map: expand it, then check every value against its expected validity. */
|
|
62
|
+
export function validateGenerated(map: FieldMap, catalog: Catalog, ctx: SelectionContext = {}): ValidationFinding[] {
|
|
63
|
+
const expanded = expandFieldMap(map, catalog, ctx);
|
|
64
|
+
const out: ValidationFinding[] = [];
|
|
65
|
+
const walk = (efs: ExpandedField[], defs: FieldDef[], prefix: string) => {
|
|
66
|
+
for (const ef of efs) {
|
|
67
|
+
const def = defs.find((d) => d.name === ef.name);
|
|
68
|
+
const path = prefix ? `${prefix}.${ef.name}` : ef.name;
|
|
69
|
+
if (ef.children) { walk(ef.children, def?.fields || [], path); continue; }
|
|
70
|
+
const ft = ef.type ? catalog.fieldTypes[ef.type] : undefined;
|
|
71
|
+
const c = { ...(ft?.constraints || {}), ...(def?.constraints || {}) };
|
|
72
|
+
out.push(...validatePoints(path, ef.type, ef.points, c));
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
walk(expanded, map.fields, '');
|
|
76
|
+
return out;
|
|
77
|
+
}
|