qa360 1.0.4 → 1.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 (108) hide show
  1. package/dist/commands/history.js +1 -1
  2. package/dist/commands/pack.js +1 -1
  3. package/dist/commands/run.d.ts +1 -1
  4. package/dist/commands/run.d.ts.map +1 -1
  5. package/dist/commands/run.js +1 -1
  6. package/dist/commands/secrets.js +1 -1
  7. package/dist/commands/serve.js +1 -1
  8. package/dist/commands/verify.js +1 -1
  9. package/dist/core/adapters/gitleaks-secrets.d.ts +115 -0
  10. package/dist/core/adapters/gitleaks-secrets.d.ts.map +1 -0
  11. package/dist/core/adapters/gitleaks-secrets.js +410 -0
  12. package/dist/core/adapters/k6-perf.d.ts +86 -0
  13. package/dist/core/adapters/k6-perf.d.ts.map +1 -0
  14. package/dist/core/adapters/k6-perf.js +398 -0
  15. package/dist/core/adapters/osv-deps.d.ts +124 -0
  16. package/dist/core/adapters/osv-deps.d.ts.map +1 -0
  17. package/dist/core/adapters/osv-deps.js +372 -0
  18. package/dist/core/adapters/playwright-api.d.ts +82 -0
  19. package/dist/core/adapters/playwright-api.d.ts.map +1 -0
  20. package/dist/core/adapters/playwright-api.js +252 -0
  21. package/dist/core/adapters/playwright-ui.d.ts +115 -0
  22. package/dist/core/adapters/playwright-ui.d.ts.map +1 -0
  23. package/dist/core/adapters/playwright-ui.js +346 -0
  24. package/dist/core/adapters/semgrep-sast.d.ts +100 -0
  25. package/dist/core/adapters/semgrep-sast.d.ts.map +1 -0
  26. package/dist/core/adapters/semgrep-sast.js +322 -0
  27. package/dist/core/adapters/zap-dast.d.ts +134 -0
  28. package/dist/core/adapters/zap-dast.d.ts.map +1 -0
  29. package/dist/core/adapters/zap-dast.js +424 -0
  30. package/dist/core/hooks/compose.d.ts +62 -0
  31. package/dist/core/hooks/compose.d.ts.map +1 -0
  32. package/dist/core/hooks/compose.js +225 -0
  33. package/dist/core/hooks/runner.d.ts +69 -0
  34. package/dist/core/hooks/runner.d.ts.map +1 -0
  35. package/dist/core/hooks/runner.js +303 -0
  36. package/dist/core/index.d.ts +74 -0
  37. package/dist/core/index.d.ts.map +1 -0
  38. package/dist/core/index.js +39 -0
  39. package/dist/core/pack/migrator.d.ts +52 -0
  40. package/dist/core/pack/migrator.d.ts.map +1 -0
  41. package/dist/core/pack/migrator.js +304 -0
  42. package/dist/core/pack/validator.d.ts +43 -0
  43. package/dist/core/pack/validator.d.ts.map +1 -0
  44. package/dist/core/pack/validator.js +292 -0
  45. package/dist/core/proof/bundle.d.ts +138 -0
  46. package/dist/core/proof/bundle.d.ts.map +1 -0
  47. package/dist/core/proof/bundle.js +160 -0
  48. package/dist/core/proof/canonicalize.d.ts +48 -0
  49. package/dist/core/proof/canonicalize.d.ts.map +1 -0
  50. package/dist/core/proof/canonicalize.js +105 -0
  51. package/dist/core/proof/index.d.ts +14 -0
  52. package/dist/core/proof/index.d.ts.map +1 -0
  53. package/dist/core/proof/index.js +18 -0
  54. package/dist/core/proof/schema.d.ts +218 -0
  55. package/dist/core/proof/schema.d.ts.map +1 -0
  56. package/dist/core/proof/schema.js +263 -0
  57. package/dist/core/proof/signer.d.ts +112 -0
  58. package/dist/core/proof/signer.d.ts.map +1 -0
  59. package/dist/core/proof/signer.js +226 -0
  60. package/dist/core/proof/verifier.d.ts +98 -0
  61. package/dist/core/proof/verifier.d.ts.map +1 -0
  62. package/dist/core/proof/verifier.js +302 -0
  63. package/dist/core/runner/phase3-runner.d.ts +102 -0
  64. package/dist/core/runner/phase3-runner.d.ts.map +1 -0
  65. package/dist/core/runner/phase3-runner.js +471 -0
  66. package/dist/core/secrets/crypto.d.ts +76 -0
  67. package/dist/core/secrets/crypto.d.ts.map +1 -0
  68. package/dist/core/secrets/crypto.js +225 -0
  69. package/dist/core/secrets/manager.d.ts +77 -0
  70. package/dist/core/secrets/manager.d.ts.map +1 -0
  71. package/dist/core/secrets/manager.js +219 -0
  72. package/dist/core/security/redaction-patterns-extended.d.ts +28 -0
  73. package/dist/core/security/redaction-patterns-extended.d.ts.map +1 -0
  74. package/dist/core/security/redaction-patterns-extended.js +247 -0
  75. package/dist/core/security/redactor.d.ts +72 -0
  76. package/dist/core/security/redactor.d.ts.map +1 -0
  77. package/dist/core/security/redactor.js +279 -0
  78. package/dist/core/serve/diagnostics-collector.d.ts +33 -0
  79. package/dist/core/serve/diagnostics-collector.d.ts.map +1 -0
  80. package/dist/core/serve/diagnostics-collector.js +149 -0
  81. package/dist/core/serve/health-checker.d.ts +45 -0
  82. package/dist/core/serve/health-checker.d.ts.map +1 -0
  83. package/dist/core/serve/health-checker.js +219 -0
  84. package/dist/core/serve/index.d.ts +9 -0
  85. package/dist/core/serve/index.d.ts.map +1 -0
  86. package/dist/core/serve/index.js +8 -0
  87. package/dist/core/serve/metrics-collector.d.ts +25 -0
  88. package/dist/core/serve/metrics-collector.d.ts.map +1 -0
  89. package/dist/core/serve/metrics-collector.js +322 -0
  90. package/dist/core/serve/process-manager.d.ts +37 -0
  91. package/dist/core/serve/process-manager.d.ts.map +1 -0
  92. package/dist/core/serve/process-manager.js +213 -0
  93. package/dist/core/serve/server.d.ts +37 -0
  94. package/dist/core/serve/server.d.ts.map +1 -0
  95. package/dist/core/serve/server.js +191 -0
  96. package/dist/core/types/pack-v1.d.ts +162 -0
  97. package/dist/core/types/pack-v1.d.ts.map +1 -0
  98. package/dist/core/types/pack-v1.js +5 -0
  99. package/dist/core/types/trust-score.d.ts +70 -0
  100. package/dist/core/types/trust-score.d.ts.map +1 -0
  101. package/dist/core/types/trust-score.js +191 -0
  102. package/dist/core/vault/cas.d.ts +87 -0
  103. package/dist/core/vault/cas.d.ts.map +1 -0
  104. package/dist/core/vault/cas.js +255 -0
  105. package/dist/core/vault/index.d.ts +205 -0
  106. package/dist/core/vault/index.d.ts.map +1 -0
  107. package/dist/core/vault/index.js +631 -0
  108. package/package.json +12 -6
@@ -0,0 +1,191 @@
1
+ /**
2
+ * QA360 Core Observability Server
3
+ * Endpoints: /health, /diag, /metrics, /cancel
4
+ */
5
+ import { createServer } from 'http';
6
+ import { URL } from 'url';
7
+ import { SecurityRedactor } from '../security/redactor.js';
8
+ import { HealthChecker } from './health-checker.js';
9
+ import { DiagnosticsCollector } from './diagnostics-collector.js';
10
+ import { MetricsCollector } from './metrics-collector.js';
11
+ import { ProcessManager } from './process-manager.js';
12
+ export class QA360Server {
13
+ config;
14
+ server;
15
+ healthChecker;
16
+ diagnosticsCollector;
17
+ metricsCollector;
18
+ processManager;
19
+ redactor;
20
+ startTime;
21
+ constructor(config) {
22
+ this.config = config;
23
+ this.healthChecker = new HealthChecker();
24
+ this.diagnosticsCollector = new DiagnosticsCollector();
25
+ this.metricsCollector = new MetricsCollector();
26
+ this.processManager = new ProcessManager();
27
+ this.redactor = SecurityRedactor.forLogs();
28
+ this.startTime = Date.now();
29
+ }
30
+ async start() {
31
+ if (this.server)
32
+ return;
33
+ await new Promise((resolve, reject) => {
34
+ const srv = createServer(this.handleRequest.bind(this));
35
+ srv.on('error', (err) => {
36
+ if (err?.code === 'EADDRINUSE') {
37
+ this.log('error', 'Port already in use', { port: this.config.port, code: 'HLT003' });
38
+ reject(Object.assign(new Error('Port already in use'), { code: 'HLT003' }));
39
+ return;
40
+ }
41
+ reject(err);
42
+ });
43
+ srv.listen(this.config.port, this.config.host ?? '127.0.0.1', () => {
44
+ this.server = srv;
45
+ this.log('info', 'QA360 Server started', {
46
+ port: this.config.port,
47
+ host: this.config.host || '127.0.0.1',
48
+ metrics: this.config.metrics ?? true
49
+ });
50
+ resolve();
51
+ });
52
+ });
53
+ }
54
+ async stop() {
55
+ return new Promise((resolve) => {
56
+ if (this.server) {
57
+ this.server.close(() => {
58
+ this.log('info', 'QA360 Server stopped');
59
+ resolve();
60
+ });
61
+ }
62
+ else {
63
+ resolve();
64
+ }
65
+ });
66
+ }
67
+ async handleRequest(req, res) {
68
+ const url = new URL(req.url || '/', `http://${req.headers.host}`);
69
+ const method = req.method?.toUpperCase() || 'GET';
70
+ try {
71
+ const response = await this.routeRequest(method, url.pathname, req);
72
+ // Set headers
73
+ Object.entries(response.headers).forEach(([key, value]) => {
74
+ res.setHeader(key, value);
75
+ });
76
+ res.statusCode = response.status;
77
+ res.end(response.body);
78
+ this.log('info', 'Request handled', {
79
+ method,
80
+ path: url.pathname,
81
+ status: response.status
82
+ });
83
+ }
84
+ catch (error) {
85
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
86
+ this.log('error', 'Request failed', { method, path: url.pathname, error: errorMessage });
87
+ res.statusCode = 500;
88
+ res.setHeader('Content-Type', 'application/json');
89
+ res.end(JSON.stringify({
90
+ error: 'Internal Server Error',
91
+ code: 'SRV001',
92
+ message: errorMessage
93
+ }));
94
+ }
95
+ }
96
+ async routeRequest(method, path, req) {
97
+ // Health endpoint
98
+ if (method === 'GET' && path === '/health') {
99
+ return await this.handleHealth();
100
+ }
101
+ // Diagnostics endpoint
102
+ if (method === 'GET' && path === '/diag') {
103
+ return await this.handleDiagnostics();
104
+ }
105
+ // Metrics endpoint
106
+ if (method === 'GET' && path === '/metrics') {
107
+ return await this.handleMetrics();
108
+ }
109
+ // Cancel endpoint
110
+ if (method === 'POST' && path.startsWith('/cancel/')) {
111
+ const runId = path.split('/')[2];
112
+ return await this.handleCancel(runId, req);
113
+ }
114
+ // 404 Not Found
115
+ return {
116
+ status: 404,
117
+ headers: { 'Content-Type': 'application/json' },
118
+ body: JSON.stringify({
119
+ error: 'Not Found',
120
+ code: 'SRV404',
121
+ message: `Endpoint ${method} ${path} not found`
122
+ })
123
+ };
124
+ }
125
+ async handleHealth() {
126
+ const health = await this.healthChecker.check();
127
+ const status = health.status === 'ok' ? 200 : health.status === 'degraded' ? 200 : 503;
128
+ return {
129
+ status,
130
+ headers: { 'Content-Type': 'application/json' },
131
+ body: JSON.stringify({
132
+ ...health,
133
+ uptime_s: Math.floor((Date.now() - this.startTime) / 1000)
134
+ }, null, 2)
135
+ };
136
+ }
137
+ async handleDiagnostics() {
138
+ const diagnostics = await this.diagnosticsCollector.collect();
139
+ return {
140
+ status: 200,
141
+ headers: { 'Content-Type': 'application/json' },
142
+ body: JSON.stringify(diagnostics, null, 2)
143
+ };
144
+ }
145
+ async handleMetrics() {
146
+ if (!this.config.metrics) {
147
+ return {
148
+ status: 404,
149
+ headers: { 'Content-Type': 'text/plain' },
150
+ body: 'Metrics disabled'
151
+ };
152
+ }
153
+ const metrics = await this.metricsCollector.collect();
154
+ return {
155
+ status: 200,
156
+ headers: { 'Content-Type': 'text/plain; version=0.0.4' },
157
+ body: metrics
158
+ };
159
+ }
160
+ async handleCancel(runId, req) {
161
+ if (!runId) {
162
+ return {
163
+ status: 400,
164
+ headers: { 'Content-Type': 'application/json' },
165
+ body: JSON.stringify({
166
+ error: 'Bad Request',
167
+ code: 'SRV400',
168
+ message: 'runId is required'
169
+ })
170
+ };
171
+ }
172
+ const result = await this.processManager.cancelRun(runId);
173
+ return {
174
+ status: result.cancelled ? 200 : 404,
175
+ headers: { 'Content-Type': 'application/json' },
176
+ body: JSON.stringify(result)
177
+ };
178
+ }
179
+ log(level, message, meta = {}) {
180
+ if (!this.config.verbose && level === 'info')
181
+ return;
182
+ const logEntry = {
183
+ timestamp: new Date().toISOString(),
184
+ level,
185
+ message,
186
+ service: 'qa360-server',
187
+ ...(meta ? (this.redactor ? this.redactor.redactObject(meta) : meta) : {})
188
+ };
189
+ console.log(JSON.stringify(logEntry));
190
+ }
191
+ }
@@ -0,0 +1,162 @@
1
+ /**
2
+ * QA360 Pack v1 TypeScript Definitions
3
+ * Generated from pack.schema.json
4
+ */
5
+ export type QualityGate = 'api_smoke' | 'ui' | 'perf' | 'sast' | 'dast' | 'a11y';
6
+ export type DataProfile = 'demo' | 'staging' | 'production';
7
+ export type RetryPattern = 'ECONNRESET' | 'ETIMEDOUT' | '502' | '503' | '504' | 'element-detached' | 'navigation-timeout';
8
+ export type TraceLevel = 'none' | 'basic' | 'detailed';
9
+ export interface ApiTarget {
10
+ baseUrl: string;
11
+ smoke?: string[];
12
+ }
13
+ export interface WebTarget {
14
+ baseUrl: string;
15
+ pages?: string[];
16
+ }
17
+ export interface PackTargets {
18
+ api?: ApiTarget;
19
+ web?: WebTarget;
20
+ }
21
+ export interface PackBudgets {
22
+ perf_p95_ms?: number;
23
+ a11y_min?: number;
24
+ }
25
+ export interface PackSecurity {
26
+ sast?: {
27
+ max_high?: number;
28
+ max_critical?: number;
29
+ max_medium?: number;
30
+ };
31
+ secrets?: {
32
+ max_findings?: number;
33
+ };
34
+ dast?: {
35
+ max_high?: number;
36
+ max_critical?: number;
37
+ max_medium?: number;
38
+ timeout_ms?: number;
39
+ };
40
+ deps?: {
41
+ max_high?: number;
42
+ max_critical?: number;
43
+ max_medium?: number;
44
+ };
45
+ }
46
+ export interface PackData {
47
+ profile?: DataProfile;
48
+ seed?: number;
49
+ }
50
+ export type HookAction = {
51
+ run: string;
52
+ timeout?: number;
53
+ } | {
54
+ compose: 'up' | 'down';
55
+ timeout?: number;
56
+ } | {
57
+ wait_on: string;
58
+ timeout?: number;
59
+ method?: 'http' | 'tcp';
60
+ };
61
+ export interface PackHooks {
62
+ beforeAll?: HookAction[];
63
+ beforeEach?: HookAction[];
64
+ afterEach?: HookAction[];
65
+ afterAll?: HookAction[];
66
+ }
67
+ export interface PackExecution {
68
+ hook_timeout_ms?: number;
69
+ on_failure?: 'stop' | 'continue';
70
+ limits?: {
71
+ cpu?: string;
72
+ memory?: string;
73
+ };
74
+ compose_file?: string;
75
+ retry_on?: RetryPattern[];
76
+ max_retries?: number;
77
+ fail_on_readiness?: boolean;
78
+ timeout?: number;
79
+ }
80
+ export interface PackObservability {
81
+ metrics?: boolean;
82
+ trace?: TraceLevel;
83
+ }
84
+ export interface PackEnvironment {
85
+ [key: string]: string;
86
+ }
87
+ /**
88
+ * QA360 Pack Configuration v1
89
+ * Complete type definition for pack.yml files
90
+ */
91
+ export interface PackConfigV1 {
92
+ version: 1;
93
+ name: string;
94
+ description?: string;
95
+ gates: QualityGate[];
96
+ targets?: PackTargets;
97
+ budgets?: PackBudgets;
98
+ security?: PackSecurity;
99
+ data?: PackData;
100
+ hooks?: PackHooks;
101
+ execution?: PackExecution;
102
+ observability?: PackObservability;
103
+ environment?: PackEnvironment;
104
+ }
105
+ /**
106
+ * Pack validation result
107
+ */
108
+ export interface PackValidationResult {
109
+ valid: boolean;
110
+ errors: PackValidationError[];
111
+ warnings: PackValidationWarning[];
112
+ }
113
+ export interface PackValidationError {
114
+ code: string;
115
+ path: string;
116
+ message: string;
117
+ suggestion?: string;
118
+ }
119
+ export interface PackValidationWarning {
120
+ code: string;
121
+ path: string;
122
+ message: string;
123
+ suggestion?: string;
124
+ }
125
+ /**
126
+ * Pack migration result
127
+ */
128
+ export interface PackMigrationResult {
129
+ success: boolean;
130
+ fromVersion: string;
131
+ toVersion: string;
132
+ changes: PackMigrationChange[];
133
+ warnings: string[];
134
+ }
135
+ export interface PackMigrationChange {
136
+ type: 'added' | 'modified' | 'removed' | 'renamed';
137
+ path: string;
138
+ oldValue?: any;
139
+ newValue?: any;
140
+ reason: string;
141
+ }
142
+ /**
143
+ * Legacy pack configuration (v0.9.x)
144
+ * For migration compatibility
145
+ */
146
+ export interface LegacyPackConfig {
147
+ name: string;
148
+ version?: string;
149
+ description?: string;
150
+ adapters?: string[];
151
+ tests?: Array<{
152
+ name: string;
153
+ adapter: string;
154
+ config: any;
155
+ }>;
156
+ environment?: Record<string, string>;
157
+ hooks?: {
158
+ beforeAll?: string[];
159
+ afterAll?: string[];
160
+ };
161
+ }
162
+ //# sourceMappingURL=pack-v1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pack-v1.d.ts","sourceRoot":"","sources":["../../../src/core/types/pack-v1.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * QA360 Pack v1 TypeScript Definitions
3
+ * Generated from pack.schema.json
4
+ */
5
+ export {};
@@ -0,0 +1,70 @@
1
+ /**
2
+ * QA360 Trust Score Calculator
3
+ * Calcul du Trust Score pondéré basé sur les résultats des gates
4
+ */
5
+ export interface TrustScoreWeights {
6
+ ui?: number;
7
+ api?: number;
8
+ perf?: number;
9
+ a11y?: number;
10
+ sast?: number;
11
+ deps?: number;
12
+ secrets?: number;
13
+ dast?: number;
14
+ }
15
+ export interface GateResult {
16
+ name: string;
17
+ success: boolean;
18
+ score: number;
19
+ weight: number;
20
+ details?: {
21
+ passed?: number;
22
+ total?: number;
23
+ duration?: number;
24
+ errors?: string[];
25
+ };
26
+ }
27
+ export interface TrustScoreResult {
28
+ overallScore: number;
29
+ weightedScore: number;
30
+ gateResults: GateResult[];
31
+ weights: TrustScoreWeights;
32
+ recommendation: 'EXCELLENT' | 'GOOD' | 'ACCEPTABLE' | 'NEEDS_IMPROVEMENT' | 'CRITICAL';
33
+ summary: {
34
+ totalGates: number;
35
+ passedGates: number;
36
+ failedGates: number;
37
+ averageScore: number;
38
+ };
39
+ }
40
+ export declare class TrustScoreCalculator {
41
+ private static readonly DEFAULT_WEIGHTS;
42
+ /**
43
+ * Calculate Trust Score from gate results
44
+ */
45
+ static calculateTrustScore(gateResults: Omit<GateResult, 'weight'>[], customWeights?: Partial<TrustScoreWeights>): TrustScoreResult;
46
+ /**
47
+ * Get recommendation based on score and results
48
+ */
49
+ private static getRecommendation;
50
+ /**
51
+ * Generate Trust Score badge
52
+ */
53
+ static generateBadge(trustScore: TrustScoreResult): string;
54
+ /**
55
+ * Get badge color based on score
56
+ */
57
+ private static getBadgeColor;
58
+ /**
59
+ * Generate detailed Trust Score report
60
+ */
61
+ static generateReport(trustScore: TrustScoreResult): string;
62
+ /**
63
+ * Validate weights configuration
64
+ */
65
+ static validateWeights(weights: Partial<TrustScoreWeights>): {
66
+ valid: boolean;
67
+ errors: string[];
68
+ };
69
+ }
70
+ //# sourceMappingURL=trust-score.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trust-score.d.ts","sourceRoot":"","sources":["../../../src/core/types/trust-score.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACR,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,cAAc,EAAE,WAAW,GAAG,MAAM,GAAG,YAAY,GAAG,mBAAmB,GAAG,UAAU,CAAC;IACvF,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CASrC;IAEF;;OAEG;IACH,MAAM,CAAC,mBAAmB,CACxB,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,EACzC,aAAa,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GACzC,gBAAgB;IA6DnB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAoBhC;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,UAAU,EAAE,gBAAgB,GAAG,MAAM;IAQ1D;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAQ5B;;OAEG;IACH,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,gBAAgB,GAAG,MAAM;IA+D3D;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;CAqBlG"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * QA360 Trust Score Calculator
3
+ * Calcul du Trust Score pondéré basé sur les résultats des gates
4
+ */
5
+ export class TrustScoreCalculator {
6
+ static DEFAULT_WEIGHTS = {
7
+ ui: 20,
8
+ api: 20,
9
+ perf: 15,
10
+ a11y: 10,
11
+ sast: 15,
12
+ deps: 10,
13
+ secrets: 5,
14
+ dast: 5
15
+ };
16
+ /**
17
+ * Calculate Trust Score from gate results
18
+ */
19
+ static calculateTrustScore(gateResults, customWeights) {
20
+ const weights = { ...this.DEFAULT_WEIGHTS, ...customWeights };
21
+ // Normalize weights to sum to 100
22
+ const totalWeight = Object.values(weights).reduce((sum, w) => sum + (w || 0), 0);
23
+ const normalizedWeights = {};
24
+ for (const [gate, weight] of Object.entries(weights)) {
25
+ if (weight && weight > 0) {
26
+ normalizedWeights[gate] = (weight / totalWeight) * 100;
27
+ }
28
+ }
29
+ // Apply weights to gate results
30
+ const weightedGateResults = gateResults.map(gate => ({
31
+ ...gate,
32
+ weight: normalizedWeights[gate.name] || 0
33
+ }));
34
+ // Calculate weighted score
35
+ let weightedScore = 0;
36
+ let totalAppliedWeight = 0;
37
+ for (const gate of weightedGateResults) {
38
+ if (gate.weight > 0) {
39
+ weightedScore += (gate.score * gate.weight) / 100;
40
+ totalAppliedWeight += gate.weight;
41
+ }
42
+ }
43
+ // Normalize if not all gates are present
44
+ if (totalAppliedWeight > 0 && totalAppliedWeight < 100) {
45
+ weightedScore = (weightedScore / totalAppliedWeight) * 100;
46
+ }
47
+ // Calculate overall score (simple average)
48
+ const overallScore = gateResults.length > 0
49
+ ? gateResults.reduce((sum, gate) => sum + gate.score, 0) / gateResults.length
50
+ : 0;
51
+ // Calculate summary
52
+ const summary = {
53
+ totalGates: gateResults.length,
54
+ passedGates: gateResults.filter(g => g.success).length,
55
+ failedGates: gateResults.filter(g => !g.success).length,
56
+ averageScore: overallScore
57
+ };
58
+ // Determine recommendation
59
+ const recommendation = this.getRecommendation(weightedScore, summary);
60
+ return {
61
+ overallScore: Math.round(overallScore),
62
+ weightedScore: Math.round(weightedScore),
63
+ gateResults: weightedGateResults,
64
+ weights: normalizedWeights,
65
+ recommendation,
66
+ summary
67
+ };
68
+ }
69
+ /**
70
+ * Get recommendation based on score and results
71
+ */
72
+ static getRecommendation(score, summary) {
73
+ // Critical if any security gates failed
74
+ const hasSecurityFailures = summary.failedGates > 0;
75
+ if (score >= 90 && !hasSecurityFailures) {
76
+ return 'EXCELLENT';
77
+ }
78
+ else if (score >= 80 && !hasSecurityFailures) {
79
+ return 'GOOD';
80
+ }
81
+ else if (score >= 70) {
82
+ return 'ACCEPTABLE';
83
+ }
84
+ else if (score >= 50) {
85
+ return 'NEEDS_IMPROVEMENT';
86
+ }
87
+ else {
88
+ return 'CRITICAL';
89
+ }
90
+ }
91
+ /**
92
+ * Generate Trust Score badge
93
+ */
94
+ static generateBadge(trustScore) {
95
+ const score = trustScore.weightedScore;
96
+ const color = this.getBadgeColor(score);
97
+ const label = `Trust Score: ${score}%`;
98
+ return `https://img.shields.io/badge/Trust%20Score-${score}%25-${color}`;
99
+ }
100
+ /**
101
+ * Get badge color based on score
102
+ */
103
+ static getBadgeColor(score) {
104
+ if (score >= 90)
105
+ return 'brightgreen';
106
+ if (score >= 80)
107
+ return 'green';
108
+ if (score >= 70)
109
+ return 'yellow';
110
+ if (score >= 50)
111
+ return 'orange';
112
+ return 'red';
113
+ }
114
+ /**
115
+ * Generate detailed Trust Score report
116
+ */
117
+ static generateReport(trustScore) {
118
+ let report = `# QA360 Trust Score Report\n\n`;
119
+ report += `## Overall Assessment\n`;
120
+ report += `- **Trust Score**: ${trustScore.weightedScore}% (weighted)\n`;
121
+ report += `- **Simple Average**: ${trustScore.overallScore}%\n`;
122
+ report += `- **Recommendation**: ${trustScore.recommendation}\n`;
123
+ report += `- **Gates Passed**: ${trustScore.summary.passedGates}/${trustScore.summary.totalGates}\n\n`;
124
+ report += `## Gate Results\n\n`;
125
+ for (const gate of trustScore.gateResults) {
126
+ const status = gate.success ? '✅' : '❌';
127
+ report += `### ${status} ${gate.name.toUpperCase()} Gate\n`;
128
+ report += `- **Score**: ${gate.score}%\n`;
129
+ report += `- **Weight**: ${gate.weight.toFixed(1)}%\n`;
130
+ report += `- **Status**: ${gate.success ? 'PASSED' : 'FAILED'}\n`;
131
+ if (gate.details) {
132
+ if (gate.details.passed !== undefined && gate.details.total !== undefined) {
133
+ report += `- **Tests**: ${gate.details.passed}/${gate.details.total} passed\n`;
134
+ }
135
+ if (gate.details.duration) {
136
+ report += `- **Duration**: ${gate.details.duration}ms\n`;
137
+ }
138
+ if (gate.details.errors && gate.details.errors.length > 0) {
139
+ report += `- **Errors**: ${gate.details.errors.length} found\n`;
140
+ }
141
+ }
142
+ report += '\n';
143
+ }
144
+ report += `## Weights Configuration\n\n`;
145
+ for (const [gate, weight] of Object.entries(trustScore.weights)) {
146
+ if (weight && weight > 0) {
147
+ report += `- **${gate.toUpperCase()}**: ${weight.toFixed(1)}%\n`;
148
+ }
149
+ }
150
+ report += `\n## Recommendations\n\n`;
151
+ switch (trustScore.recommendation) {
152
+ case 'EXCELLENT':
153
+ report += `🎉 Excellent quality! Your application meets the highest standards.\n`;
154
+ break;
155
+ case 'GOOD':
156
+ report += `👍 Good quality with minor areas for improvement.\n`;
157
+ break;
158
+ case 'ACCEPTABLE':
159
+ report += `⚠️ Acceptable quality but consider addressing failed gates.\n`;
160
+ break;
161
+ case 'NEEDS_IMPROVEMENT':
162
+ report += `🔧 Significant improvements needed. Focus on failed gates.\n`;
163
+ break;
164
+ case 'CRITICAL':
165
+ report += `🚨 Critical issues found. Immediate attention required.\n`;
166
+ break;
167
+ }
168
+ return report;
169
+ }
170
+ /**
171
+ * Validate weights configuration
172
+ */
173
+ static validateWeights(weights) {
174
+ const errors = [];
175
+ // Check for negative weights
176
+ for (const [gate, weight] of Object.entries(weights)) {
177
+ if (weight !== undefined && weight < 0) {
178
+ errors.push(`Weight for ${gate} cannot be negative: ${weight}`);
179
+ }
180
+ }
181
+ // Check total weight
182
+ const totalWeight = Object.values(weights).reduce((sum, w) => sum + (w || 0), 0);
183
+ if (totalWeight === 0) {
184
+ errors.push('Total weight cannot be zero');
185
+ }
186
+ return {
187
+ valid: errors.length === 0,
188
+ errors
189
+ };
190
+ }
191
+ }