@tracelens/shared 0.1.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 (63) hide show
  1. package/dist/__tests__/validation.test.d.ts +2 -0
  2. package/dist/__tests__/validation.test.d.ts.map +1 -0
  3. package/dist/__tests__/validation.test.js +16 -0
  4. package/dist/index.d.ts +4 -0
  5. package/dist/index.d.ts.map +1 -0
  6. package/dist/index.js +4 -0
  7. package/dist/schemas/dependency.schema.d.ts +177 -0
  8. package/dist/schemas/dependency.schema.d.ts.map +1 -0
  9. package/dist/schemas/dependency.schema.js +187 -0
  10. package/dist/schemas/error.schema.d.ts +170 -0
  11. package/dist/schemas/error.schema.d.ts.map +1 -0
  12. package/dist/schemas/error.schema.js +176 -0
  13. package/dist/schemas/index.d.ts +5 -0
  14. package/dist/schemas/index.d.ts.map +1 -0
  15. package/dist/schemas/index.js +5 -0
  16. package/dist/schemas/performance.schema.d.ts +333 -0
  17. package/dist/schemas/performance.schema.d.ts.map +1 -0
  18. package/dist/schemas/performance.schema.js +200 -0
  19. package/dist/schemas/trace.schema.d.ts +325 -0
  20. package/dist/schemas/trace.schema.d.ts.map +1 -0
  21. package/dist/schemas/trace.schema.js +145 -0
  22. package/dist/types/dependency.types.d.ts +109 -0
  23. package/dist/types/dependency.types.d.ts.map +1 -0
  24. package/dist/types/dependency.types.js +8 -0
  25. package/dist/types/index.d.ts +10 -0
  26. package/dist/types/index.d.ts.map +1 -0
  27. package/dist/types/index.js +5 -0
  28. package/dist/types/performance.types.d.ts +95 -0
  29. package/dist/types/performance.types.d.ts.map +1 -0
  30. package/dist/types/performance.types.js +1 -0
  31. package/dist/types/security.types.d.ts +154 -0
  32. package/dist/types/security.types.d.ts.map +1 -0
  33. package/dist/types/security.types.js +8 -0
  34. package/dist/types/trace.types.d.ts +57 -0
  35. package/dist/types/trace.types.d.ts.map +1 -0
  36. package/dist/types/trace.types.js +20 -0
  37. package/dist/utils/index.d.ts +3 -0
  38. package/dist/utils/index.d.ts.map +1 -0
  39. package/dist/utils/index.js +5 -0
  40. package/dist/utils/validation.d.ts +21 -0
  41. package/dist/utils/validation.d.ts.map +1 -0
  42. package/dist/utils/validation.js +157 -0
  43. package/jest.config.js +14 -0
  44. package/package.json +22 -0
  45. package/src/__tests__/validation.test.ts +19 -0
  46. package/src/index.d.ts.map +1 -0
  47. package/src/index.ts +4 -0
  48. package/src/schemas/dependency.schema.ts +187 -0
  49. package/src/schemas/error.schema.ts +176 -0
  50. package/src/schemas/index.ts +5 -0
  51. package/src/schemas/performance.schema.ts +200 -0
  52. package/src/schemas/trace.schema.ts +146 -0
  53. package/src/types/dependency.types.ts +120 -0
  54. package/src/types/index.d.ts.map +1 -0
  55. package/src/types/index.ts +11 -0
  56. package/src/types/performance.types.ts +108 -0
  57. package/src/types/security.types.ts +172 -0
  58. package/src/types/trace.types.ts +62 -0
  59. package/src/utils/index.d.ts.map +1 -0
  60. package/src/utils/index.ts +6 -0
  61. package/src/utils/validation.ts +209 -0
  62. package/tsconfig.json +9 -0
  63. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,172 @@
1
+ // CVE and vulnerability types for TraceLens
2
+ export interface CVERecord {
3
+ id: string; // CVE-YYYY-NNNN format
4
+ published: string; // ISO date string
5
+ lastModified: string; // ISO date string
6
+ vulnStatus: VulnerabilityStatus;
7
+ descriptions: CVEDescription[];
8
+ metrics: CVEMetrics;
9
+ weaknesses: CVEWeakness[];
10
+ configurations: CVEConfiguration[];
11
+ references: CVEReference[];
12
+ vendorComments?: CVEVendorComment[];
13
+ }
14
+
15
+ export enum VulnerabilityStatus {
16
+ ANALYZED = 'Analyzed',
17
+ MODIFIED = 'Modified',
18
+ REJECTED = 'Rejected',
19
+ AWAITING_ANALYSIS = 'Awaiting Analysis',
20
+ RECEIVED = 'Received'
21
+ }
22
+
23
+ export interface CVEDescription {
24
+ lang: string;
25
+ value: string;
26
+ }
27
+
28
+ export interface CVEMetrics {
29
+ cvssMetricV31?: CVSSv31[];
30
+ cvssMetricV30?: CVSSv30[];
31
+ cvssMetricV2?: CVSSv2[];
32
+ }
33
+
34
+ export interface CVSSv31 {
35
+ source: string;
36
+ type: 'Primary' | 'Secondary';
37
+ cvssData: {
38
+ version: '3.1';
39
+ vectorString: string;
40
+ attackVector: 'NETWORK' | 'ADJACENT_NETWORK' | 'LOCAL' | 'PHYSICAL';
41
+ attackComplexity: 'LOW' | 'HIGH';
42
+ privilegesRequired: 'NONE' | 'LOW' | 'HIGH';
43
+ userInteraction: 'NONE' | 'REQUIRED';
44
+ scope: 'UNCHANGED' | 'CHANGED';
45
+ confidentialityImpact: 'NONE' | 'LOW' | 'HIGH';
46
+ integrityImpact: 'NONE' | 'LOW' | 'HIGH';
47
+ availabilityImpact: 'NONE' | 'LOW' | 'HIGH';
48
+ baseScore: number;
49
+ baseSeverity: 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
50
+ };
51
+ exploitabilityScore: number;
52
+ impactScore: number;
53
+ }
54
+
55
+ export interface CVSSv30 {
56
+ source: string;
57
+ type: 'Primary' | 'Secondary';
58
+ cvssData: {
59
+ version: '3.0';
60
+ vectorString: string;
61
+ baseScore: number;
62
+ baseSeverity: 'NONE' | 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
63
+ };
64
+ }
65
+
66
+ export interface CVSSv2 {
67
+ source: string;
68
+ type: 'Primary' | 'Secondary';
69
+ cvssData: {
70
+ version: '2.0';
71
+ vectorString: string;
72
+ baseScore: number;
73
+ };
74
+ }
75
+
76
+ export interface CVEWeakness {
77
+ source: string;
78
+ type: 'Primary' | 'Secondary';
79
+ description: CVEDescription[];
80
+ }
81
+
82
+ export interface CVEConfiguration {
83
+ nodes: CVENode[];
84
+ operator?: 'AND' | 'OR';
85
+ }
86
+
87
+ export interface CVENode {
88
+ operator: 'AND' | 'OR';
89
+ negate?: boolean;
90
+ cpeMatch: CPEMatch[];
91
+ }
92
+
93
+ export interface CPEMatch {
94
+ vulnerable: boolean;
95
+ criteria: string; // CPE 2.3 format
96
+ matchCriteriaId: string;
97
+ versionStartExcluding?: string;
98
+ versionStartIncluding?: string;
99
+ versionEndExcluding?: string;
100
+ versionEndIncluding?: string;
101
+ }
102
+
103
+ export interface CVEReference {
104
+ url: string;
105
+ source: string;
106
+ tags?: string[];
107
+ }
108
+
109
+ export interface CVEVendorComment {
110
+ organization: string;
111
+ comment: string;
112
+ lastModified: string;
113
+ }
114
+
115
+ export interface VulnerabilityAssessment {
116
+ cveId: string;
117
+ packageName: string;
118
+ packageVersion: string;
119
+ severity: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'NONE';
120
+ score: number;
121
+ vector: string;
122
+ runtimeRelevant: boolean;
123
+ executionPaths: string[];
124
+ exploitability: ExploitabilityAssessment;
125
+ mitigation: MitigationRecommendation;
126
+ }
127
+
128
+ export interface ExploitabilityAssessment {
129
+ isExploitable: boolean;
130
+ exploitComplexity: 'LOW' | 'MEDIUM' | 'HIGH';
131
+ requiresUserInteraction: boolean;
132
+ requiresPrivileges: boolean;
133
+ networkAccessible: boolean;
134
+ publicExploitAvailable: boolean;
135
+ }
136
+
137
+ export interface MitigationRecommendation {
138
+ action: 'UPDATE' | 'PATCH' | 'WORKAROUND' | 'MONITOR';
139
+ targetVersion?: string;
140
+ patchUrl?: string;
141
+ workaroundDescription?: string;
142
+ priority: 'IMMEDIATE' | 'HIGH' | 'MEDIUM' | 'LOW';
143
+ estimatedEffort: 'MINUTES' | 'HOURS' | 'DAYS' | 'WEEKS';
144
+ }
145
+
146
+ export interface SecurityScan {
147
+ id: string;
148
+ projectId: string;
149
+ timestamp: number;
150
+ scanType: 'FULL' | 'INCREMENTAL' | 'TARGETED';
151
+ vulnerabilities: VulnerabilityAssessment[];
152
+ summary: SecuritySummary;
153
+ runtimeAnalysis: RuntimeSecurityAnalysis;
154
+ }
155
+
156
+ export interface SecuritySummary {
157
+ totalVulnerabilities: number;
158
+ criticalCount: number;
159
+ highCount: number;
160
+ mediumCount: number;
161
+ lowCount: number;
162
+ runtimeRelevantCount: number;
163
+ exploitableCount: number;
164
+ }
165
+
166
+ export interface RuntimeSecurityAnalysis {
167
+ executedPackages: string[];
168
+ vulnerableExecutedPackages: string[];
169
+ criticalPathVulnerabilities: VulnerabilityAssessment[];
170
+ riskScore: number;
171
+ recommendations: MitigationRecommendation[];
172
+ }
@@ -0,0 +1,62 @@
1
+ // OpenTelemetry trace definitions for TraceLens
2
+ export interface TraceSpan {
3
+ traceId: string;
4
+ spanId: string;
5
+ parentSpanId?: string;
6
+ operationName: string;
7
+ startTime: number; // microseconds since epoch
8
+ endTime?: number;
9
+ duration?: number; // microseconds
10
+ tags: Record<string, string | number | boolean>;
11
+ logs?: TraceLog[];
12
+ status: SpanStatus;
13
+ }
14
+
15
+ export interface TraceLog {
16
+ timestamp: number;
17
+ fields: Record<string, string | number | boolean>;
18
+ }
19
+
20
+ export enum SpanStatus {
21
+ OK = 'OK',
22
+ CANCELLED = 'CANCELLED',
23
+ UNKNOWN = 'UNKNOWN',
24
+ INVALID_ARGUMENT = 'INVALID_ARGUMENT',
25
+ DEADLINE_EXCEEDED = 'DEADLINE_EXCEEDED',
26
+ NOT_FOUND = 'NOT_FOUND',
27
+ ALREADY_EXISTS = 'ALREADY_EXISTS',
28
+ PERMISSION_DENIED = 'PERMISSION_DENIED',
29
+ RESOURCE_EXHAUSTED = 'RESOURCE_EXHAUSTED',
30
+ FAILED_PRECONDITION = 'FAILED_PRECONDITION',
31
+ ABORTED = 'ABORTED',
32
+ OUT_OF_RANGE = 'OUT_OF_RANGE',
33
+ UNIMPLEMENTED = 'UNIMPLEMENTED',
34
+ INTERNAL = 'INTERNAL',
35
+ UNAVAILABLE = 'UNAVAILABLE',
36
+ DATA_LOSS = 'DATA_LOSS',
37
+ UNAUTHENTICATED = 'UNAUTHENTICATED'
38
+ }
39
+
40
+ export interface Trace {
41
+ traceId: string;
42
+ spans: TraceSpan[];
43
+ startTime: number;
44
+ endTime?: number;
45
+ duration?: number;
46
+ rootSpan?: TraceSpan;
47
+ }
48
+
49
+ export interface TraceContext {
50
+ traceId: string;
51
+ spanId: string;
52
+ traceFlags: number;
53
+ traceState?: string;
54
+ }
55
+
56
+ export interface TracingConfig {
57
+ serviceName: string;
58
+ serviceVersion: string;
59
+ environment: string;
60
+ samplingRate: number;
61
+ endpoint?: string;
62
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AACA,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
@@ -0,0 +1,6 @@
1
+ // Shared utilities
2
+ export * from './validation';
3
+
4
+ export function generateId(): string {
5
+ return Math.random().toString(36).substring(2, 15);
6
+ }
@@ -0,0 +1,209 @@
1
+ // Data validation utilities for TraceLens
2
+ import { TraceSpan, Trace } from '../types/trace.types';
3
+ import { WebVitalsMetrics, PerformanceEvent } from '../types/performance.types';
4
+ import { DependencySnapshot, PackageDependency } from '../types/dependency.types';
5
+ import { CVERecord, VulnerabilityAssessment } from '../types/security.types';
6
+
7
+ export class ValidationError extends Error {
8
+ constructor(
9
+ message: string,
10
+ public field: string,
11
+ public value: unknown
12
+ ) {
13
+ super(message);
14
+ this.name = 'ValidationError';
15
+ }
16
+ }
17
+
18
+ export function validateTraceSpan(span: unknown): TraceSpan {
19
+ if (!span || typeof span !== 'object') {
20
+ throw new ValidationError('Span must be an object', 'span', span);
21
+ }
22
+
23
+ const s = span as Record<string, unknown>;
24
+
25
+ if (!s.traceId || typeof s.traceId !== 'string') {
26
+ throw new ValidationError('traceId must be a string', 'traceId', s.traceId);
27
+ }
28
+
29
+ if (!s.spanId || typeof s.spanId !== 'string') {
30
+ throw new ValidationError('spanId must be a string', 'spanId', s.spanId);
31
+ }
32
+
33
+ if (!s.operationName || typeof s.operationName !== 'string') {
34
+ throw new ValidationError('operationName must be a string', 'operationName', s.operationName);
35
+ }
36
+
37
+ if (!s.startTime || typeof s.startTime !== 'number') {
38
+ throw new ValidationError('startTime must be a number', 'startTime', s.startTime);
39
+ }
40
+
41
+ if (s.endTime !== undefined && typeof s.endTime !== 'number') {
42
+ throw new ValidationError('endTime must be a number', 'endTime', s.endTime);
43
+ }
44
+
45
+ if (!s.tags || typeof s.tags !== 'object') {
46
+ throw new ValidationError('tags must be an object', 'tags', s.tags);
47
+ }
48
+
49
+ return s as unknown as TraceSpan;
50
+ }
51
+
52
+ export function validateTrace(trace: unknown): Trace {
53
+ if (!trace || typeof trace !== 'object') {
54
+ throw new ValidationError('Trace must be an object', 'trace', trace);
55
+ }
56
+
57
+ const t = trace as Record<string, unknown>;
58
+
59
+ if (!t.traceId || typeof t.traceId !== 'string') {
60
+ throw new ValidationError('traceId must be a string', 'traceId', t.traceId);
61
+ }
62
+
63
+ if (!Array.isArray(t.spans)) {
64
+ throw new ValidationError('spans must be an array', 'spans', t.spans);
65
+ }
66
+
67
+ // Validate each span
68
+ t.spans.forEach((span, index) => {
69
+ try {
70
+ validateTraceSpan(span);
71
+ } catch (error: unknown) {
72
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
73
+ throw new ValidationError(
74
+ `Invalid span at index ${index}: ${errorMessage}`,
75
+ `spans[${index}]`,
76
+ span
77
+ );
78
+ }
79
+ });
80
+
81
+ return t as unknown as Trace;
82
+ }
83
+
84
+ export function validatePerformanceEvent(event: unknown): PerformanceEvent {
85
+ if (!event || typeof event !== 'object') {
86
+ throw new ValidationError('Event must be an object', 'event', event);
87
+ }
88
+
89
+ const e = event as Record<string, unknown>;
90
+
91
+ if (!e.id || typeof e.id !== 'string') {
92
+ throw new ValidationError('id must be a string', 'id', e.id);
93
+ }
94
+
95
+ if (!e.timestamp || typeof e.timestamp !== 'number') {
96
+ throw new ValidationError('timestamp must be a number', 'timestamp', e.timestamp);
97
+ }
98
+
99
+ const validTypes = ['web-vitals', 'resource-timing', 'navigation-timing', 'long-task'];
100
+ if (!e.type || !validTypes.includes(e.type as string)) {
101
+ throw new ValidationError(
102
+ `type must be one of: ${validTypes.join(', ')}`,
103
+ 'type',
104
+ e.type
105
+ );
106
+ }
107
+
108
+ if (!e.url || typeof e.url !== 'string') {
109
+ throw new ValidationError('url must be a string', 'url', e.url);
110
+ }
111
+
112
+ return e as unknown as PerformanceEvent;
113
+ }
114
+
115
+ export function validateDependencySnapshot(snapshot: unknown): DependencySnapshot {
116
+ if (!snapshot || typeof snapshot !== 'object') {
117
+ throw new ValidationError('Snapshot must be an object', 'snapshot', snapshot);
118
+ }
119
+
120
+ const s = snapshot as Record<string, unknown>;
121
+
122
+ if (!s.id || typeof s.id !== 'string') {
123
+ throw new ValidationError('id must be a string', 'id', s.id);
124
+ }
125
+
126
+ if (!s.projectId || typeof s.projectId !== 'string') {
127
+ throw new ValidationError('projectId must be a string', 'projectId', s.projectId);
128
+ }
129
+
130
+ if (!s.timestamp || typeof s.timestamp !== 'number') {
131
+ throw new ValidationError('timestamp must be a number', 'timestamp', s.timestamp);
132
+ }
133
+
134
+ if (!Array.isArray(s.dependencies)) {
135
+ throw new ValidationError('dependencies must be an array', 'dependencies', s.dependencies);
136
+ }
137
+
138
+ return s as unknown as DependencySnapshot;
139
+ }
140
+
141
+ export function validateCVERecord(cve: unknown): CVERecord {
142
+ if (!cve || typeof cve !== 'object') {
143
+ throw new ValidationError('CVE must be an object', 'cve', cve);
144
+ }
145
+
146
+ const c = cve as Record<string, unknown>;
147
+
148
+ if (!c.id || typeof c.id !== 'string') {
149
+ throw new ValidationError('id must be a string', 'id', c.id);
150
+ }
151
+
152
+ // Validate CVE ID format
153
+ const cveIdPattern = /^CVE-\d{4}-\d{4,}$/;
154
+ if (!cveIdPattern.test(c.id as string)) {
155
+ throw new ValidationError('id must be in CVE-YYYY-NNNN format', 'id', c.id);
156
+ }
157
+
158
+ if (!c.published || typeof c.published !== 'string') {
159
+ throw new ValidationError('published must be a string', 'published', c.published);
160
+ }
161
+
162
+ return c as unknown as CVERecord;
163
+ }
164
+
165
+ export function sanitizeInput(input: string): string {
166
+ // Remove potentially dangerous characters
167
+ return input
168
+ .replace(/[<>]/g, '') // Remove angle brackets
169
+ .replace(/javascript:/gi, '') // Remove javascript: protocol
170
+ .replace(/on\w+=/gi, '') // Remove event handlers
171
+ .trim();
172
+ }
173
+
174
+ export function validateProjectId(projectId: string): boolean {
175
+ // Project ID should be alphanumeric with hyphens and underscores
176
+ const projectIdPattern = /^[a-zA-Z0-9_-]+$/;
177
+ return projectIdPattern.test(projectId) && projectId.length >= 3 && projectId.length <= 50;
178
+ }
179
+
180
+ export function validateTimestamp(timestamp: number): boolean {
181
+ // Timestamp should be a reasonable Unix timestamp (after 2020, before 2050)
182
+ const minTimestamp = 1577836800000; // 2020-01-01
183
+ const maxTimestamp = 2524608000000; // 2050-01-01
184
+ return timestamp >= minTimestamp && timestamp <= maxTimestamp;
185
+ }
186
+
187
+ export function validateUrl(url: string): boolean {
188
+ try {
189
+ new URL(url);
190
+ return true;
191
+ } catch {
192
+ return false;
193
+ }
194
+ }
195
+
196
+ export function validateVersion(version: string): boolean {
197
+ // Validate semantic version format
198
+ const semverPattern = /^\d+\.\d+\.\d+(?:-[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)?(?:\+[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*)?$/;
199
+ return semverPattern.test(version);
200
+ }
201
+
202
+ export function isValidJSON(str: string): boolean {
203
+ try {
204
+ JSON.parse(str);
205
+ return true;
206
+ } catch {
207
+ return false;
208
+ }
209
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@tracelens/tsconfig/base.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["dist", "node_modules"]
9
+ }