@rigour-labs/core 4.3.1 → 4.3.3

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.
@@ -36,9 +36,10 @@ export class PromiseSafetyGate extends Gate {
36
36
  return [];
37
37
  const violations = [];
38
38
  const allPatterns = Object.values(LANG_GLOBS).flat();
39
+ const scanPatterns = context.patterns || allPatterns;
39
40
  const files = await FileScanner.findFiles({
40
41
  cwd: context.cwd,
41
- patterns: allPatterns,
42
+ patterns: scanPatterns,
42
43
  ignore: [...(context.ignore || []), '**/node_modules/**', '**/dist/**', '**/build/**',
43
44
  '**/*.test.*', '**/*.spec.*', '**/vendor/**', '**/__pycache__/**',
44
45
  '**/bin/Debug/**', '**/bin/Release/**', '**/obj/**', '**/venv/**', '**/.venv/**'],
@@ -87,7 +88,7 @@ export class PromiseSafetyGate extends Gate {
87
88
  if (!/\.then\s*\(/.test(line))
88
89
  continue;
89
90
  let hasCatch = false;
90
- for (let j = i; j < Math.min(i + 10, lines.length); j++) {
91
+ for (let j = i; j < Math.min(i + 50, lines.length); j++) {
91
92
  const lookahead = this.sanitizeLine(lines[j]);
92
93
  if (/\.catch\s*\(/.test(lookahead)) {
93
94
  hasCatch = true;
@@ -209,7 +210,7 @@ export class PromiseSafetyGate extends Gate {
209
210
  if (!httpPatterns.test(lines[i]) || isInsidePythonTry(lines, i))
210
211
  continue;
211
212
  let hasCheck = false;
212
- for (let j = i; j < Math.min(i + 10, lines.length); j++) {
213
+ for (let j = i; j < Math.min(i + 50, lines.length); j++) {
213
214
  if (/raise_for_status|status_code/.test(lines[j])) {
214
215
  hasCheck = true;
215
216
  break;
@@ -317,7 +318,7 @@ export class PromiseSafetyGate extends Gate {
317
318
  for (let i = 0; i < lines.length; i++) {
318
319
  if (/\.(?:GetAsync|PostAsync|SendAsync)\s*\(/.test(lines[i]) && !isInsideTryBlock(lines, i)) {
319
320
  let hasCheck = false;
320
- for (let j = i; j < Math.min(i + 10, lines.length); j++) {
321
+ for (let j = i; j < Math.min(i + 50, lines.length); j++) {
321
322
  if (/EnsureSuccess|IsSuccessStatusCode|StatusCode/.test(lines[j])) {
322
323
  hasCheck = true;
323
324
  break;
@@ -15,6 +15,7 @@ import { RetryLoopBreakerGate } from './retry-loop-breaker.js';
15
15
  import { AgentTeamGate } from './agent-team.js';
16
16
  import { CheckpointGate } from './checkpoint.js';
17
17
  import { SecurityPatternsGate } from './security-patterns.js';
18
+ import { FrontendSecretExposureGate } from './frontend-secret-exposure.js';
18
19
  import { DuplicationDriftGate } from './duplication-drift.js';
19
20
  import { HallucinatedImportsGate } from './hallucinated-imports.js';
20
21
  import { InconsistentErrorHandlingGate } from './inconsistent-error-handling.js';
@@ -67,6 +68,9 @@ export class GateRunner {
67
68
  if (this.config.gates.security?.enabled !== false) {
68
69
  this.gates.push(new SecurityPatternsGate(this.config.gates.security));
69
70
  }
71
+ if (this.config.gates.frontend_secret_exposure?.enabled !== false) {
72
+ this.gates.push(new FrontendSecretExposureGate(this.config.gates.frontend_secret_exposure));
73
+ }
70
74
  // v2.16+ AI-Native Drift Detection Gates (enabled by default)
71
75
  if (this.config.gates.duplication_drift?.enabled !== false) {
72
76
  this.gates.push(new DuplicationDriftGate(this.config.gates.duplication_drift));
@@ -195,13 +199,13 @@ export class GateRunner {
195
199
  }
196
200
  const isLocalDeepExecution = !deepOptions.apiKey || (deepOptions.provider || '').toLowerCase() === 'local';
197
201
  const deepTier = isLocalDeepExecution
198
- ? (deepOptions.pro ? 'pro' : 'deep')
202
+ ? (deepOptions.pro ? 'deep' : 'lite')
199
203
  : 'cloud';
200
204
  deepStats = {
201
205
  enabled: true,
202
206
  tier: deepTier,
203
207
  model: isLocalDeepExecution
204
- ? (deepOptions.pro ? 'Qwen2.5-Coder-1.5B' : 'Qwen2.5-Coder-0.5B')
208
+ ? (deepOptions.pro ? 'Qwen2.5-Coder-1.5B' : 'Qwen3.5-0.8B')
205
209
  : (deepOptions.modelName || deepOptions.provider || 'cloud'),
206
210
  total_ms: Date.now() - deepSetupStart,
207
211
  findings_count: deepFailures.length,
@@ -25,7 +25,7 @@ describe('GateRunner deep stats execution mode', () => {
25
25
  },
26
26
  });
27
27
  }
28
- it('reports local deep tier when provider=local even with apiKey', async () => {
28
+ it('reports local lite tier when provider=local even with apiKey', async () => {
29
29
  vi.spyOn(DeepAnalysisGate.prototype, 'run').mockResolvedValue([]);
30
30
  const runner = createRunner();
31
31
  const report = await runner.run(testDir, undefined, {
@@ -34,10 +34,10 @@ describe('GateRunner deep stats execution mode', () => {
34
34
  provider: 'local',
35
35
  pro: false,
36
36
  });
37
- expect(report.stats.deep?.tier).toBe('deep');
38
- expect(report.stats.deep?.model).toBe('Qwen2.5-Coder-0.5B');
37
+ expect(report.stats.deep?.tier).toBe('lite');
38
+ expect(report.stats.deep?.model).toBe('Qwen3.5-0.8B');
39
39
  });
40
- it('reports local pro tier when provider=local and pro=true', async () => {
40
+ it('reports local deep tier when provider=local and pro=true', async () => {
41
41
  vi.spyOn(DeepAnalysisGate.prototype, 'run').mockResolvedValue([]);
42
42
  const runner = createRunner();
43
43
  const report = await runner.run(testDir, undefined, {
@@ -46,7 +46,7 @@ describe('GateRunner deep stats execution mode', () => {
46
46
  provider: 'local',
47
47
  pro: true,
48
48
  });
49
- expect(report.stats.deep?.tier).toBe('pro');
49
+ expect(report.stats.deep?.tier).toBe('deep');
50
50
  expect(report.stats.deep?.model).toBe('Qwen2.5-Coder-1.5B');
51
51
  });
52
52
  it('reports cloud tier/model for cloud providers', async () => {
@@ -251,9 +251,10 @@ export class SecurityPatternsGate extends Gate {
251
251
  }
252
252
  const failures = [];
253
253
  const vulnerabilities = [];
254
+ const scanPatterns = context.patterns || ['**/*.{ts,js,tsx,jsx,py,java,go}'];
254
255
  const files = await FileScanner.findFiles({
255
256
  cwd: context.cwd,
256
- patterns: ['**/*.{ts,js,tsx,jsx,py,java,go}'],
257
+ patterns: scanPatterns,
257
258
  ignore: [...(context.ignore || []), '**/node_modules/**', '**/dist/**', '**/build/**', '**/.next/**', '**/coverage/**'],
258
259
  });
259
260
  const scanFiles = files.filter(file => !this.shouldSkipSecurityFile(file));
@@ -73,9 +73,10 @@ export class SideEffectAnalysisGate extends Gate {
73
73
  if (!this.cfg.enabled)
74
74
  return [];
75
75
  const violations = [];
76
+ const scanPatterns = context.patterns || FILE_GLOBS;
76
77
  const files = await FileScanner.findFiles({
77
78
  cwd: context.cwd,
78
- patterns: FILE_GLOBS,
79
+ patterns: scanPatterns,
79
80
  ignore: [
80
81
  ...(context.ignore || []),
81
82
  '**/node_modules/**', '**/dist/**', '**/build/**',
@@ -50,16 +50,18 @@ export class TestQualityGate extends Gate {
50
50
  return [];
51
51
  const failures = [];
52
52
  const issues = [];
53
+ const defaultPatterns = [
54
+ '**/*.test.{ts,js,tsx,jsx}', '**/*.spec.{ts,js,tsx,jsx}',
55
+ '**/__tests__/**/*.{ts,js,tsx,jsx}',
56
+ '**/test_*.py', '**/*_test.py', '**/tests/**/*.py',
57
+ '**/*_test.go',
58
+ '**/*Test.java', '**/*Tests.java', '**/src/test/**/*.java',
59
+ '**/*Test.kt', '**/*Tests.kt', '**/src/test/**/*.kt',
60
+ ];
61
+ const scanPatterns = context.patterns || defaultPatterns;
53
62
  const files = await FileScanner.findFiles({
54
63
  cwd: context.cwd,
55
- patterns: [
56
- '**/*.test.{ts,js,tsx,jsx}', '**/*.spec.{ts,js,tsx,jsx}',
57
- '**/__tests__/**/*.{ts,js,tsx,jsx}',
58
- '**/test_*.py', '**/*_test.py', '**/tests/**/*.py',
59
- '**/*_test.go',
60
- '**/*Test.java', '**/*Tests.java', '**/src/test/**/*.java',
61
- '**/*Test.kt', '**/*Tests.kt', '**/src/test/**/*.kt',
62
- ],
64
+ patterns: scanPatterns,
63
65
  ignore: [...(context.ignore || []), '**/node_modules/**', '**/dist/**', '**/build/**',
64
66
  '**/.venv/**', '**/venv/**', '**/vendor/**',
65
67
  '**/target/**', '**/.gradle/**', '**/out/**'],
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from './types/fix-packet.js';
7
7
  export { Gate, GateContext } from './gates/base.js';
8
8
  export { RetryLoopBreakerGate } from './gates/retry-loop-breaker.js';
9
9
  export { SideEffectAnalysisGate } from './gates/side-effect-analysis.js';
10
+ export { FrontendSecretExposureGate } from './gates/frontend-secret-exposure.js';
10
11
  export * from './utils/logger.js';
11
12
  export * from './services/score-history.js';
12
13
  export * from './hooks/index.js';
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ export * from './types/fix-packet.js';
7
7
  export { Gate } from './gates/base.js';
8
8
  export { RetryLoopBreakerGate } from './gates/retry-loop-breaker.js';
9
9
  export { SideEffectAnalysisGate } from './gates/side-effect-analysis.js';
10
+ export { FrontendSecretExposureGate } from './gates/frontend-secret-exposure.js';
10
11
  export * from './utils/logger.js';
11
12
  export * from './services/score-history.js';
12
13
  export * from './hooks/index.js';
@@ -18,6 +18,8 @@ export function createProvider(options) {
18
18
  });
19
19
  }
20
20
  // Default: local sidecar
21
- const tier = options.pro ? 'pro' : 'deep';
21
+ // deep = Qwen2.5-Coder-1.5B (full power, company-hosted)
22
+ // lite = Qwen3.5-0.8B (lightweight, default CLI sidecar)
23
+ const tier = options.pro ? 'deep' : 'lite';
22
24
  return new SidecarProvider(tier);
23
25
  }
@@ -27,7 +27,7 @@ export class SidecarProvider {
27
27
  modelPath = null;
28
28
  tier;
29
29
  threads;
30
- constructor(tier = 'deep', threads = 4) {
30
+ constructor(tier = 'lite', threads = 4) {
31
31
  this.tier = tier;
32
32
  this.threads = threads;
33
33
  }
@@ -60,8 +60,12 @@ export interface DeepAnalysisResult {
60
60
  }
61
61
  /**
62
62
  * Available model tiers.
63
+ *
64
+ * - deep: Qwen2.5-Coder-1.5B fine-tuned — full power, company-hosted
65
+ * - lite: Qwen3.5-0.8B fine-tuned — lightweight, ships as default CLI sidecar
66
+ * - legacy: Qwen2.5-Coder-0.5B fine-tuned — previous default, reproducibility
63
67
  */
64
- export type ModelTier = 'deep' | 'pro';
68
+ export type ModelTier = 'deep' | 'lite' | 'legacy';
65
69
  /**
66
70
  * Model info for download/caching.
67
71
  */
@@ -8,20 +8,28 @@ export const MODEL_VERSION = '1';
8
8
  export const MODELS = {
9
9
  deep: {
10
10
  tier: 'deep',
11
- name: 'Rigour-Deep-v1 (Qwen2.5-Coder-0.5B fine-tuned)',
11
+ name: 'Rigour-Deep-v1 (Qwen2.5-Coder-1.5B fine-tuned)',
12
12
  filename: `rigour-deep-v${MODEL_VERSION}-q4_k_m.gguf`,
13
13
  url: `https://huggingface.co/rigour-labs/rigour-deep-v1-gguf/resolve/main/rigour-deep-v${MODEL_VERSION}-q4_k_m.gguf`,
14
- sizeBytes: 350_000_000,
15
- sizeHuman: '350MB',
16
- },
17
- pro: {
18
- tier: 'pro',
19
- name: 'Rigour-Pro-v1 (Qwen2.5-Coder-1.5B fine-tuned)',
20
- filename: `rigour-pro-v${MODEL_VERSION}-q4_k_m.gguf`,
21
- url: `https://huggingface.co/rigour-labs/rigour-pro-v1-gguf/resolve/main/rigour-pro-v${MODEL_VERSION}-q4_k_m.gguf`,
22
14
  sizeBytes: 900_000_000,
23
15
  sizeHuman: '900MB',
24
16
  },
17
+ lite: {
18
+ tier: 'lite',
19
+ name: 'Rigour-Lite-v1 (Qwen3.5-0.8B fine-tuned)',
20
+ filename: `rigour-lite-v${MODEL_VERSION}-q4_k_m.gguf`,
21
+ url: `https://huggingface.co/rigour-labs/rigour-lite-v1-gguf/resolve/main/rigour-lite-v${MODEL_VERSION}-q4_k_m.gguf`,
22
+ sizeBytes: 500_000_000,
23
+ sizeHuman: '500MB',
24
+ },
25
+ legacy: {
26
+ tier: 'legacy',
27
+ name: 'Rigour-Legacy-v1 (Qwen2.5-Coder-0.5B fine-tuned)',
28
+ filename: `rigour-legacy-v${MODEL_VERSION}-q4_k_m.gguf`,
29
+ url: `https://huggingface.co/rigour-labs/rigour-legacy-v1-gguf/resolve/main/rigour-legacy-v${MODEL_VERSION}-q4_k_m.gguf`,
30
+ sizeBytes: 350_000_000,
31
+ sizeHuman: '350MB',
32
+ },
25
33
  };
26
34
  /**
27
35
  * Fallback stock models — used when fine-tuned model is not yet
@@ -30,18 +38,26 @@ export const MODELS = {
30
38
  export const FALLBACK_MODELS = {
31
39
  deep: {
32
40
  tier: 'deep',
33
- name: 'Qwen2.5-Coder-0.5B-Instruct (stock)',
34
- filename: 'qwen2.5-coder-0.5b-instruct-q4_k_m.gguf',
35
- url: 'https://huggingface.co/Qwen/Qwen2.5-Coder-0.5B-Instruct-GGUF/resolve/main/qwen2.5-coder-0.5b-instruct-q4_k_m.gguf',
36
- sizeBytes: 350_000_000,
37
- sizeHuman: '350MB',
38
- },
39
- pro: {
40
- tier: 'pro',
41
41
  name: 'Qwen2.5-Coder-1.5B-Instruct (stock)',
42
42
  filename: 'qwen2.5-coder-1.5b-instruct-q4_k_m.gguf',
43
43
  url: 'https://huggingface.co/Qwen/Qwen2.5-Coder-1.5B-Instruct-GGUF/resolve/main/qwen2.5-coder-1.5b-instruct-q4_k_m.gguf',
44
44
  sizeBytes: 900_000_000,
45
45
  sizeHuman: '900MB',
46
46
  },
47
+ lite: {
48
+ tier: 'lite',
49
+ name: 'Qwen3.5-0.8B (stock)',
50
+ filename: 'qwen3.5-0.8b-q4_k_m.gguf',
51
+ url: 'https://huggingface.co/Qwen/Qwen3.5-0.8B-GGUF/resolve/main/qwen3.5-0.8b-q4_k_m.gguf',
52
+ sizeBytes: 500_000_000,
53
+ sizeHuman: '500MB',
54
+ },
55
+ legacy: {
56
+ tier: 'legacy',
57
+ name: 'Qwen2.5-Coder-0.5B-Instruct (stock)',
58
+ filename: 'qwen2.5-coder-0.5b-instruct-q4_k_m.gguf',
59
+ url: 'https://huggingface.co/Qwen/Qwen2.5-Coder-0.5B-Instruct-GGUF/resolve/main/qwen2.5-coder-0.5b-instruct-q4_k_m.gguf',
60
+ sizeBytes: 350_000_000,
61
+ sizeHuman: '350MB',
62
+ },
47
63
  };
@@ -72,6 +72,36 @@ export const UNIVERSAL_CONFIG = {
72
72
  command_injection: true,
73
73
  block_on_severity: 'high',
74
74
  },
75
+ frontend_secret_exposure: {
76
+ enabled: true,
77
+ block_on_severity: 'high',
78
+ check_process_env: true,
79
+ check_import_meta_env: true,
80
+ secret_env_name_patterns: [
81
+ '(?:^|_)(?:secret|private)(?:_|$)',
82
+ '(?:^|_)(?:token|api[_-]?key|access[_-]?key|client[_-]?secret|signing|webhook)(?:_|$)',
83
+ '(?:^|_)(?:db[_-]?url|database[_-]?url|connection[_-]?string)(?:_|$)',
84
+ ],
85
+ safe_public_prefixes: ['NEXT_PUBLIC_', 'VITE_', 'PUBLIC_', 'NUXT_PUBLIC_', 'REACT_APP_'],
86
+ frontend_path_patterns: [
87
+ '(^|/)pages/(?!api/)',
88
+ '(^|/)components/',
89
+ '(^|/)src/components/',
90
+ '(^|/)src/views/',
91
+ '(^|/)src/app/',
92
+ '(^|/)app/(?!api/)',
93
+ '(^|/)views/',
94
+ '(^|/)public/',
95
+ ],
96
+ server_path_patterns: [
97
+ '(^|/)pages/api/',
98
+ '(^|/)src/pages/api/',
99
+ '(^|/)app/api/',
100
+ '(^|/)src/app/api/',
101
+ '\\.server\\.(?:ts|tsx|js|jsx|mjs|cjs)$',
102
+ ],
103
+ allowlist_env_names: [],
104
+ },
75
105
  adaptive: {
76
106
  enabled: false,
77
107
  base_coverage_threshold: 80,
@@ -213,6 +213,37 @@ export declare const GatesSchema: z.ZodObject<{
213
213
  command_injection?: boolean | undefined;
214
214
  block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
215
215
  }>>>;
216
+ frontend_secret_exposure: z.ZodDefault<z.ZodOptional<z.ZodObject<{
217
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
218
+ block_on_severity: z.ZodDefault<z.ZodOptional<z.ZodEnum<["critical", "high", "medium", "low"]>>>;
219
+ check_process_env: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
220
+ check_import_meta_env: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
221
+ secret_env_name_patterns: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
222
+ safe_public_prefixes: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
223
+ frontend_path_patterns: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
224
+ server_path_patterns: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
225
+ allowlist_env_names: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
226
+ }, "strip", z.ZodTypeAny, {
227
+ enabled: boolean;
228
+ block_on_severity: "critical" | "high" | "medium" | "low";
229
+ check_process_env: boolean;
230
+ check_import_meta_env: boolean;
231
+ secret_env_name_patterns: string[];
232
+ safe_public_prefixes: string[];
233
+ frontend_path_patterns: string[];
234
+ server_path_patterns: string[];
235
+ allowlist_env_names: string[];
236
+ }, {
237
+ enabled?: boolean | undefined;
238
+ block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
239
+ check_process_env?: boolean | undefined;
240
+ check_import_meta_env?: boolean | undefined;
241
+ secret_env_name_patterns?: string[] | undefined;
242
+ safe_public_prefixes?: string[] | undefined;
243
+ frontend_path_patterns?: string[] | undefined;
244
+ server_path_patterns?: string[] | undefined;
245
+ allowlist_env_names?: string[] | undefined;
246
+ }>>>;
216
247
  adaptive: z.ZodDefault<z.ZodOptional<z.ZodObject<{
217
248
  enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
218
249
  base_coverage_threshold: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
@@ -674,6 +705,17 @@ export declare const GatesSchema: z.ZodObject<{
674
705
  command_injection: boolean;
675
706
  block_on_severity: "critical" | "high" | "medium" | "low";
676
707
  };
708
+ frontend_secret_exposure: {
709
+ enabled: boolean;
710
+ block_on_severity: "critical" | "high" | "medium" | "low";
711
+ check_process_env: boolean;
712
+ check_import_meta_env: boolean;
713
+ secret_env_name_patterns: string[];
714
+ safe_public_prefixes: string[];
715
+ frontend_path_patterns: string[];
716
+ server_path_patterns: string[];
717
+ allowlist_env_names: string[];
718
+ };
677
719
  adaptive: {
678
720
  enabled: boolean;
679
721
  base_coverage_threshold: number;
@@ -874,6 +916,17 @@ export declare const GatesSchema: z.ZodObject<{
874
916
  command_injection?: boolean | undefined;
875
917
  block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
876
918
  } | undefined;
919
+ frontend_secret_exposure?: {
920
+ enabled?: boolean | undefined;
921
+ block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
922
+ check_process_env?: boolean | undefined;
923
+ check_import_meta_env?: boolean | undefined;
924
+ secret_env_name_patterns?: string[] | undefined;
925
+ safe_public_prefixes?: string[] | undefined;
926
+ frontend_path_patterns?: string[] | undefined;
927
+ server_path_patterns?: string[] | undefined;
928
+ allowlist_env_names?: string[] | undefined;
929
+ } | undefined;
877
930
  adaptive?: {
878
931
  enabled?: boolean | undefined;
879
932
  base_coverage_threshold?: number | undefined;
@@ -1245,6 +1298,37 @@ export declare const ConfigSchema: z.ZodObject<{
1245
1298
  command_injection?: boolean | undefined;
1246
1299
  block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
1247
1300
  }>>>;
1301
+ frontend_secret_exposure: z.ZodDefault<z.ZodOptional<z.ZodObject<{
1302
+ enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1303
+ block_on_severity: z.ZodDefault<z.ZodOptional<z.ZodEnum<["critical", "high", "medium", "low"]>>>;
1304
+ check_process_env: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1305
+ check_import_meta_env: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1306
+ secret_env_name_patterns: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
1307
+ safe_public_prefixes: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
1308
+ frontend_path_patterns: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
1309
+ server_path_patterns: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
1310
+ allowlist_env_names: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>;
1311
+ }, "strip", z.ZodTypeAny, {
1312
+ enabled: boolean;
1313
+ block_on_severity: "critical" | "high" | "medium" | "low";
1314
+ check_process_env: boolean;
1315
+ check_import_meta_env: boolean;
1316
+ secret_env_name_patterns: string[];
1317
+ safe_public_prefixes: string[];
1318
+ frontend_path_patterns: string[];
1319
+ server_path_patterns: string[];
1320
+ allowlist_env_names: string[];
1321
+ }, {
1322
+ enabled?: boolean | undefined;
1323
+ block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
1324
+ check_process_env?: boolean | undefined;
1325
+ check_import_meta_env?: boolean | undefined;
1326
+ secret_env_name_patterns?: string[] | undefined;
1327
+ safe_public_prefixes?: string[] | undefined;
1328
+ frontend_path_patterns?: string[] | undefined;
1329
+ server_path_patterns?: string[] | undefined;
1330
+ allowlist_env_names?: string[] | undefined;
1331
+ }>>>;
1248
1332
  adaptive: z.ZodDefault<z.ZodOptional<z.ZodObject<{
1249
1333
  enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
1250
1334
  base_coverage_threshold: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
@@ -1706,6 +1790,17 @@ export declare const ConfigSchema: z.ZodObject<{
1706
1790
  command_injection: boolean;
1707
1791
  block_on_severity: "critical" | "high" | "medium" | "low";
1708
1792
  };
1793
+ frontend_secret_exposure: {
1794
+ enabled: boolean;
1795
+ block_on_severity: "critical" | "high" | "medium" | "low";
1796
+ check_process_env: boolean;
1797
+ check_import_meta_env: boolean;
1798
+ secret_env_name_patterns: string[];
1799
+ safe_public_prefixes: string[];
1800
+ frontend_path_patterns: string[];
1801
+ server_path_patterns: string[];
1802
+ allowlist_env_names: string[];
1803
+ };
1709
1804
  adaptive: {
1710
1805
  enabled: boolean;
1711
1806
  base_coverage_threshold: number;
@@ -1906,6 +2001,17 @@ export declare const ConfigSchema: z.ZodObject<{
1906
2001
  command_injection?: boolean | undefined;
1907
2002
  block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
1908
2003
  } | undefined;
2004
+ frontend_secret_exposure?: {
2005
+ enabled?: boolean | undefined;
2006
+ block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
2007
+ check_process_env?: boolean | undefined;
2008
+ check_import_meta_env?: boolean | undefined;
2009
+ secret_env_name_patterns?: string[] | undefined;
2010
+ safe_public_prefixes?: string[] | undefined;
2011
+ frontend_path_patterns?: string[] | undefined;
2012
+ server_path_patterns?: string[] | undefined;
2013
+ allowlist_env_names?: string[] | undefined;
2014
+ } | undefined;
1909
2015
  adaptive?: {
1910
2016
  enabled?: boolean | undefined;
1911
2017
  base_coverage_threshold?: number | undefined;
@@ -2148,6 +2254,17 @@ export declare const ConfigSchema: z.ZodObject<{
2148
2254
  command_injection: boolean;
2149
2255
  block_on_severity: "critical" | "high" | "medium" | "low";
2150
2256
  };
2257
+ frontend_secret_exposure: {
2258
+ enabled: boolean;
2259
+ block_on_severity: "critical" | "high" | "medium" | "low";
2260
+ check_process_env: boolean;
2261
+ check_import_meta_env: boolean;
2262
+ secret_env_name_patterns: string[];
2263
+ safe_public_prefixes: string[];
2264
+ frontend_path_patterns: string[];
2265
+ server_path_patterns: string[];
2266
+ allowlist_env_names: string[];
2267
+ };
2151
2268
  adaptive: {
2152
2269
  enabled: boolean;
2153
2270
  base_coverage_threshold: number;
@@ -2374,6 +2491,17 @@ export declare const ConfigSchema: z.ZodObject<{
2374
2491
  command_injection?: boolean | undefined;
2375
2492
  block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
2376
2493
  } | undefined;
2494
+ frontend_secret_exposure?: {
2495
+ enabled?: boolean | undefined;
2496
+ block_on_severity?: "critical" | "high" | "medium" | "low" | undefined;
2497
+ check_process_env?: boolean | undefined;
2498
+ check_import_meta_env?: boolean | undefined;
2499
+ secret_env_name_patterns?: string[] | undefined;
2500
+ safe_public_prefixes?: string[] | undefined;
2501
+ frontend_path_patterns?: string[] | undefined;
2502
+ server_path_patterns?: string[] | undefined;
2503
+ allowlist_env_names?: string[] | undefined;
2504
+ } | undefined;
2377
2505
  adaptive?: {
2378
2506
  enabled?: boolean | undefined;
2379
2507
  base_coverage_threshold?: number | undefined;
@@ -2620,7 +2748,7 @@ export declare const ReportSchema: z.ZodObject<{
2620
2748
  }>>;
2621
2749
  deep: z.ZodOptional<z.ZodObject<{
2622
2750
  enabled: z.ZodBoolean;
2623
- tier: z.ZodOptional<z.ZodEnum<["deep", "pro", "cloud"]>>;
2751
+ tier: z.ZodOptional<z.ZodEnum<["deep", "lite", "legacy", "cloud"]>>;
2624
2752
  model: z.ZodOptional<z.ZodString>;
2625
2753
  total_ms: z.ZodOptional<z.ZodNumber>;
2626
2754
  files_analyzed: z.ZodOptional<z.ZodNumber>;
@@ -2628,7 +2756,7 @@ export declare const ReportSchema: z.ZodObject<{
2628
2756
  findings_verified: z.ZodOptional<z.ZodNumber>;
2629
2757
  }, "strip", z.ZodTypeAny, {
2630
2758
  enabled: boolean;
2631
- tier?: "deep" | "pro" | "cloud" | undefined;
2759
+ tier?: "deep" | "lite" | "legacy" | "cloud" | undefined;
2632
2760
  model?: string | undefined;
2633
2761
  total_ms?: number | undefined;
2634
2762
  files_analyzed?: number | undefined;
@@ -2636,7 +2764,7 @@ export declare const ReportSchema: z.ZodObject<{
2636
2764
  findings_verified?: number | undefined;
2637
2765
  }, {
2638
2766
  enabled: boolean;
2639
- tier?: "deep" | "pro" | "cloud" | undefined;
2767
+ tier?: "deep" | "lite" | "legacy" | "cloud" | undefined;
2640
2768
  model?: string | undefined;
2641
2769
  total_ms?: number | undefined;
2642
2770
  files_analyzed?: number | undefined;
@@ -2647,7 +2775,7 @@ export declare const ReportSchema: z.ZodObject<{
2647
2775
  duration_ms: number;
2648
2776
  deep?: {
2649
2777
  enabled: boolean;
2650
- tier?: "deep" | "pro" | "cloud" | undefined;
2778
+ tier?: "deep" | "lite" | "legacy" | "cloud" | undefined;
2651
2779
  model?: string | undefined;
2652
2780
  total_ms?: number | undefined;
2653
2781
  files_analyzed?: number | undefined;
@@ -2670,7 +2798,7 @@ export declare const ReportSchema: z.ZodObject<{
2670
2798
  duration_ms: number;
2671
2799
  deep?: {
2672
2800
  enabled: boolean;
2673
- tier?: "deep" | "pro" | "cloud" | undefined;
2801
+ tier?: "deep" | "lite" | "legacy" | "cloud" | undefined;
2674
2802
  model?: string | undefined;
2675
2803
  total_ms?: number | undefined;
2676
2804
  files_analyzed?: number | undefined;
@@ -2695,7 +2823,7 @@ export declare const ReportSchema: z.ZodObject<{
2695
2823
  duration_ms: number;
2696
2824
  deep?: {
2697
2825
  enabled: boolean;
2698
- tier?: "deep" | "pro" | "cloud" | undefined;
2826
+ tier?: "deep" | "lite" | "legacy" | "cloud" | undefined;
2699
2827
  model?: string | undefined;
2700
2828
  total_ms?: number | undefined;
2701
2829
  files_analyzed?: number | undefined;
@@ -2737,7 +2865,7 @@ export declare const ReportSchema: z.ZodObject<{
2737
2865
  duration_ms: number;
2738
2866
  deep?: {
2739
2867
  enabled: boolean;
2740
- tier?: "deep" | "pro" | "cloud" | undefined;
2868
+ tier?: "deep" | "lite" | "legacy" | "cloud" | undefined;
2741
2869
  model?: string | undefined;
2742
2870
  total_ms?: number | undefined;
2743
2871
  files_analyzed?: number | undefined;
@@ -95,6 +95,42 @@ export const GatesSchema = z.object({
95
95
  command_injection: z.boolean().optional().default(true),
96
96
  block_on_severity: z.enum(['critical', 'high', 'medium', 'low']).optional().default('high'),
97
97
  }).optional().default({}),
98
+ frontend_secret_exposure: z.object({
99
+ enabled: z.boolean().optional().default(true),
100
+ block_on_severity: z.enum(['critical', 'high', 'medium', 'low']).optional().default('high'),
101
+ check_process_env: z.boolean().optional().default(true),
102
+ check_import_meta_env: z.boolean().optional().default(true),
103
+ secret_env_name_patterns: z.array(z.string()).optional().default([
104
+ '(?:^|_)(?:secret|private)(?:_|$)',
105
+ '(?:^|_)(?:token|api[_-]?key|access[_-]?key|client[_-]?secret|signing|webhook)(?:_|$)',
106
+ '(?:^|_)(?:db[_-]?url|database[_-]?url|connection[_-]?string)(?:_|$)',
107
+ ]),
108
+ safe_public_prefixes: z.array(z.string()).optional().default([
109
+ 'NEXT_PUBLIC_',
110
+ 'VITE_',
111
+ 'PUBLIC_',
112
+ 'NUXT_PUBLIC_',
113
+ 'REACT_APP_',
114
+ ]),
115
+ frontend_path_patterns: z.array(z.string()).optional().default([
116
+ '(^|/)pages/(?!api/)',
117
+ '(^|/)components/',
118
+ '(^|/)src/components/',
119
+ '(^|/)src/views/',
120
+ '(^|/)src/app/',
121
+ '(^|/)app/(?!api/)',
122
+ '(^|/)views/',
123
+ '(^|/)public/',
124
+ ]),
125
+ server_path_patterns: z.array(z.string()).optional().default([
126
+ '(^|/)pages/api/',
127
+ '(^|/)src/pages/api/',
128
+ '(^|/)app/api/',
129
+ '(^|/)src/app/api/',
130
+ '\\.server\\.(?:ts|tsx|js|jsx|mjs|cjs)$',
131
+ ]),
132
+ allowlist_env_names: z.array(z.string()).optional().default([]),
133
+ }).optional().default({}),
98
134
  adaptive: z.object({
99
135
  enabled: z.boolean().optional().default(false),
100
136
  base_coverage_threshold: z.number().optional().default(80),
@@ -347,7 +383,7 @@ export const ReportSchema = z.object({
347
383
  }).optional(),
348
384
  deep: z.object({
349
385
  enabled: z.boolean(),
350
- tier: z.enum(['deep', 'pro', 'cloud']).optional(),
386
+ tier: z.enum(['deep', 'lite', 'legacy', 'cloud']).optional(),
351
387
  model: z.string().optional(),
352
388
  total_ms: z.number().optional(),
353
389
  files_analyzed: z.number().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigour-labs/core",
3
- "version": "4.3.1",
3
+ "version": "4.3.3",
4
4
  "description": "Deterministic quality gate engine for AI-generated code. AST analysis, drift detection, and Fix Packet generation across TypeScript, JavaScript, Python, Go, Ruby, and C#.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://rigour.run",
@@ -59,11 +59,11 @@
59
59
  "@xenova/transformers": "^2.17.2",
60
60
  "better-sqlite3": "^11.0.0",
61
61
  "openai": "^4.104.0",
62
- "@rigour-labs/brain-darwin-arm64": "4.3.1",
63
- "@rigour-labs/brain-darwin-x64": "4.3.1",
64
- "@rigour-labs/brain-linux-arm64": "4.3.1",
65
- "@rigour-labs/brain-win-x64": "4.3.1",
66
- "@rigour-labs/brain-linux-x64": "4.3.1"
62
+ "@rigour-labs/brain-darwin-arm64": "4.3.3",
63
+ "@rigour-labs/brain-linux-arm64": "4.3.3",
64
+ "@rigour-labs/brain-darwin-x64": "4.3.3",
65
+ "@rigour-labs/brain-win-x64": "4.3.3",
66
+ "@rigour-labs/brain-linux-x64": "4.3.3"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@types/better-sqlite3": "^7.6.12",