@euconform/core 1.3.0 → 1.5.0

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.
Files changed (69) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +24 -0
  3. package/assets/datasets/crows-pairs-de.json +613 -0
  4. package/assets/datasets/crows-pairs-en.json +9055 -0
  5. package/dist/datasets/crows-pairs.d.ts +7 -0
  6. package/dist/datasets/crows-pairs.d.ts.map +1 -0
  7. package/dist/datasets/crows-pairs.js +41 -0
  8. package/dist/evidence/output.d.ts.map +1 -1
  9. package/dist/evidence/output.js +1 -0
  10. package/dist/evidence/types.d.ts +8 -2
  11. package/dist/evidence/types.d.ts.map +1 -1
  12. package/dist/evidence/validate.d.ts.map +1 -1
  13. package/dist/evidence/validate.js +59 -39
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/inference/index.d.ts +1 -1
  17. package/dist/inference/index.d.ts.map +1 -1
  18. package/dist/inference/index.js +1 -1
  19. package/dist/inference/ollama-client.d.ts +9 -3
  20. package/dist/inference/ollama-client.d.ts.map +1 -1
  21. package/dist/inference/ollama-client.js +23 -11
  22. package/dist/sbom/component-mapper.d.ts +26 -0
  23. package/dist/sbom/component-mapper.d.ts.map +1 -0
  24. package/dist/sbom/component-mapper.js +83 -0
  25. package/dist/sbom/cyclonedx-import.d.ts +34 -0
  26. package/dist/sbom/cyclonedx-import.d.ts.map +1 -0
  27. package/dist/sbom/cyclonedx-import.js +131 -0
  28. package/dist/sbom/index.d.ts +6 -0
  29. package/dist/sbom/index.d.ts.map +1 -0
  30. package/dist/sbom/index.js +4 -0
  31. package/dist/sbom/known-packages.d.ts +13 -0
  32. package/dist/sbom/known-packages.d.ts.map +1 -0
  33. package/dist/sbom/known-packages.js +129 -0
  34. package/dist/sbom/purl.d.ts +14 -0
  35. package/dist/sbom/purl.d.ts.map +1 -0
  36. package/dist/sbom/purl.js +56 -0
  37. package/dist/sbom/types.d.ts +39 -0
  38. package/dist/sbom/types.d.ts.map +1 -0
  39. package/dist/sbom/types.js +5 -0
  40. package/dist/validation/index.d.ts +2 -0
  41. package/dist/validation/index.d.ts.map +1 -0
  42. package/dist/validation/index.js +1 -0
  43. package/dist/validation/schema-validator.d.ts +18 -0
  44. package/dist/validation/schema-validator.d.ts.map +1 -0
  45. package/dist/validation/schema-validator.js +99 -0
  46. package/package.json +8 -2
  47. package/src/datasets/crows-pairs.ts +64 -0
  48. package/src/evidence/output.ts +1 -0
  49. package/src/evidence/types.ts +9 -2
  50. package/src/evidence/validate.ts +107 -70
  51. package/src/index.ts +1 -0
  52. package/src/inference/index.ts +6 -1
  53. package/src/inference/ollama-client.ts +30 -14
  54. package/src/sbom/component-mapper.ts +107 -0
  55. package/src/sbom/cyclonedx-import.ts +198 -0
  56. package/src/sbom/index.ts +12 -0
  57. package/src/sbom/known-packages.ts +142 -0
  58. package/src/sbom/purl.ts +66 -0
  59. package/src/sbom/types.ts +34 -0
  60. package/src/validation/index.ts +7 -0
  61. package/src/validation/schema-validator.ts +133 -0
  62. package/tests/evidence/{ecef-schemas.test.ts → spec-schemas.test.ts} +3 -3
  63. package/tests/fixtures/cyclonedx-minimal.json +13 -0
  64. package/tests/fixtures/cyclonedx-mixed.json +17 -0
  65. package/tests/fixtures/cyclonedx-ml-bom.json +25 -0
  66. package/tests/sbom/component-mapper.test.ts +258 -0
  67. package/tests/sbom/cyclonedx-import.test.ts +329 -0
  68. package/tests/sbom/purl.test.ts +102 -0
  69. package/tests/validation/schema-validator.test.ts +219 -0
@@ -0,0 +1,219 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { validate } from "../../src/validation/schema-validator";
3
+
4
+ describe("schema-validator", () => {
5
+ describe("auto-detection", () => {
6
+ it("detects report.v1 schema type", () => {
7
+ const result = validate({
8
+ schemaVersion: "euconform.report.v1",
9
+ generatedAt: "2026-01-01T00:00:00Z",
10
+ tool: { name: "euconform", version: "1.0.0" },
11
+ target: {
12
+ name: "test",
13
+ rootPath: "/test",
14
+ repoType: "unknown",
15
+ detectedStack: [],
16
+ },
17
+ aiFootprint: {
18
+ usesAI: false,
19
+ inferenceModes: [],
20
+ providerHints: [],
21
+ ragHints: [],
22
+ },
23
+ complianceSignals: {
24
+ disclosure: { status: "unknown", confidence: "low", evidence: [] },
25
+ biasTesting: { status: "unknown", confidence: "low", evidence: [] },
26
+ reportingExports: { status: "unknown", confidence: "low", evidence: [] },
27
+ loggingMonitoring: { status: "unknown", confidence: "low", evidence: [] },
28
+ humanOversight: { status: "unknown", confidence: "low", evidence: [] },
29
+ dataGovernance: { status: "unknown", confidence: "low", evidence: [] },
30
+ incidentReporting: { status: "unknown", confidence: "low", evidence: [] },
31
+ },
32
+ assessmentHints: {
33
+ possibleModes: [],
34
+ riskIndicators: [],
35
+ gpaiIndicators: [],
36
+ openQuestions: [],
37
+ },
38
+ gaps: [],
39
+ recommendationSummary: [],
40
+ });
41
+ expect(result.schemaType).toBe("report.v1");
42
+ expect(result.valid).toBe(true);
43
+ expect(result.errors).toEqual([]);
44
+ });
45
+
46
+ it("detects aibom.v1 schema type", () => {
47
+ const result = validate({
48
+ schemaVersion: "euconform.aibom.v1",
49
+ generatedAt: "2026-01-01T00:00:00Z",
50
+ project: { name: "test", rootPath: "/test" },
51
+ components: [],
52
+ complianceCapabilities: {
53
+ biasEvaluation: false,
54
+ jsonExport: true,
55
+ pdfExport: false,
56
+ loggingInfrastructure: false,
57
+ humanReviewFlow: false,
58
+ incidentHandling: false,
59
+ },
60
+ });
61
+ expect(result.schemaType).toBe("aibom.v1");
62
+ expect(result.valid).toBe(true);
63
+ });
64
+
65
+ it("returns error for missing schemaVersion", () => {
66
+ const result = validate({ foo: "bar" });
67
+ expect(result.valid).toBe(false);
68
+ expect(result.errors[0].message).toContain("schemaVersion");
69
+ });
70
+
71
+ it("returns error for unknown schemaVersion", () => {
72
+ const result = validate({ schemaVersion: "euconform.unknown.v9" });
73
+ expect(result.valid).toBe(false);
74
+ expect(result.errors[0].message).toContain("unknown");
75
+ });
76
+ });
77
+
78
+ describe("validation errors", () => {
79
+ it("reports missing required fields", () => {
80
+ const result = validate({
81
+ schemaVersion: "euconform.aibom.v1",
82
+ });
83
+ expect(result.valid).toBe(false);
84
+ expect(result.errors.length).toBeGreaterThan(0);
85
+ const paths = result.errors.map((e) => e.path);
86
+ expect(paths).toContain("");
87
+ });
88
+
89
+ it("reports invalid enum values", () => {
90
+ const result = validate({
91
+ schemaVersion: "euconform.aibom.v1",
92
+ generatedAt: "2026-01-01T00:00:00Z",
93
+ project: { name: "test", rootPath: "/test" },
94
+ components: [
95
+ {
96
+ id: "bad:component",
97
+ kind: "invalid-kind",
98
+ name: "Bad",
99
+ source: "package.json",
100
+ },
101
+ ],
102
+ complianceCapabilities: {
103
+ biasEvaluation: false,
104
+ jsonExport: false,
105
+ pdfExport: false,
106
+ loggingInfrastructure: false,
107
+ humanReviewFlow: false,
108
+ incidentHandling: false,
109
+ },
110
+ });
111
+ expect(result.valid).toBe(false);
112
+ expect(result.errors.some((e) => e.keyword === "enum")).toBe(true);
113
+ });
114
+
115
+ it("reports additional properties", () => {
116
+ const result = validate({
117
+ schemaVersion: "euconform.aibom.v1",
118
+ generatedAt: "2026-01-01T00:00:00Z",
119
+ project: { name: "test", rootPath: "/test" },
120
+ components: [],
121
+ complianceCapabilities: {
122
+ biasEvaluation: false,
123
+ jsonExport: false,
124
+ pdfExport: false,
125
+ loggingInfrastructure: false,
126
+ humanReviewFlow: false,
127
+ incidentHandling: false,
128
+ },
129
+ extraField: "should fail",
130
+ });
131
+ expect(result.valid).toBe(false);
132
+ expect(result.errors.some((e) => e.keyword === "additionalProperties")).toBe(true);
133
+ });
134
+
135
+ it("accepts sbom-import as valid source", () => {
136
+ const result = validate({
137
+ schemaVersion: "euconform.aibom.v1",
138
+ generatedAt: "2026-01-01T00:00:00Z",
139
+ project: { name: "test", rootPath: "/test" },
140
+ components: [
141
+ {
142
+ id: "ai-framework:torch",
143
+ kind: "ai-framework",
144
+ name: "torch",
145
+ version: "2.0.0",
146
+ source: "sbom-import",
147
+ },
148
+ ],
149
+ complianceCapabilities: {
150
+ biasEvaluation: false,
151
+ jsonExport: false,
152
+ pdfExport: false,
153
+ loggingInfrastructure: false,
154
+ humanReviewFlow: false,
155
+ incidentHandling: false,
156
+ },
157
+ });
158
+ expect(result.valid).toBe(true);
159
+ });
160
+
161
+ it("accepts aibom v1.1 with metadata field", () => {
162
+ const result = validate({
163
+ schemaVersion: "euconform.aibom.v1.1",
164
+ generatedAt: "2026-01-01T00:00:00Z",
165
+ project: { name: "test", rootPath: "/test" },
166
+ components: [],
167
+ complianceCapabilities: {
168
+ biasEvaluation: false,
169
+ jsonExport: false,
170
+ pdfExport: false,
171
+ loggingInfrastructure: false,
172
+ humanReviewFlow: false,
173
+ incidentHandling: false,
174
+ },
175
+ metadata: {
176
+ importSource: "cyclonedx",
177
+ importTool: "cdxgen 10.0.0",
178
+ originalTimestamp: "2026-04-19T10:00:00Z",
179
+ },
180
+ });
181
+ expect(result.valid).toBe(true);
182
+ });
183
+
184
+ it("rejects aibom v1 with metadata field", () => {
185
+ const result = validate({
186
+ schemaVersion: "euconform.aibom.v1",
187
+ generatedAt: "2026-01-01T00:00:00Z",
188
+ project: { name: "test", rootPath: "/test" },
189
+ components: [],
190
+ complianceCapabilities: {
191
+ biasEvaluation: false,
192
+ jsonExport: false,
193
+ pdfExport: false,
194
+ loggingInfrastructure: false,
195
+ humanReviewFlow: false,
196
+ incidentHandling: false,
197
+ },
198
+ metadata: {
199
+ importSource: "cyclonedx",
200
+ },
201
+ });
202
+ expect(result.valid).toBe(false);
203
+ });
204
+ });
205
+
206
+ describe("ValidationResult structure", () => {
207
+ it("returns structured errors with path, message, keyword", () => {
208
+ const result = validate({
209
+ schemaVersion: "euconform.aibom.v1",
210
+ });
211
+ expect(result.valid).toBe(false);
212
+ for (const error of result.errors) {
213
+ expect(error).toHaveProperty("path");
214
+ expect(error).toHaveProperty("message");
215
+ expect(error).toHaveProperty("keyword");
216
+ }
217
+ });
218
+ });
219
+ });