@rigour-labs/core 6.8.0 → 6.8.1
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/dist/inference/cloud-provider.js +12 -2
- package/package.json +11 -8
- package/dist/brief/briefing.test.d.ts +0 -1
- package/dist/brief/briefing.test.js +0 -107
- package/dist/context/automatic-index-cache.test.d.ts +0 -1
- package/dist/context/automatic-index-cache.test.js +0 -30
- package/dist/context/automatic-index.test.d.ts +0 -1
- package/dist/context/automatic-index.test.js +0 -45
- package/dist/context/cache-engine.test.d.ts +0 -1
- package/dist/context/cache-engine.test.js +0 -99
- package/dist/context/dependency-graph.test.d.ts +0 -1
- package/dist/context/dependency-graph.test.js +0 -13
- package/dist/context/index-status.test.d.ts +0 -1
- package/dist/context/index-status.test.js +0 -26
- package/dist/context.test.d.ts +0 -1
- package/dist/context.test.js +0 -228
- package/dist/deep/agent-review.test.d.ts +0 -1
- package/dist/deep/agent-review.test.js +0 -53
- package/dist/deep/code-context.test.d.ts +0 -1
- package/dist/deep/code-context.test.js +0 -48
- package/dist/deep/code-pass.test.d.ts +0 -1
- package/dist/deep/code-pass.test.js +0 -112
- package/dist/deep/code-review-prompt.test.d.ts +0 -1
- package/dist/deep/code-review-prompt.test.js +0 -20
- package/dist/deep/code-verifier.test.d.ts +0 -1
- package/dist/deep/code-verifier.test.js +0 -54
- package/dist/deep/diff-tests/calls.test.d.ts +0 -1
- package/dist/deep/diff-tests/calls.test.js +0 -33
- package/dist/deep/diff-tests/run.test.d.ts +0 -1
- package/dist/deep/diff-tests/run.test.js +0 -58
- package/dist/deep/fact-extractor.test.d.ts +0 -1
- package/dist/deep/fact-extractor.test.js +0 -581
- package/dist/deep/parse-findings.test.d.ts +0 -1
- package/dist/deep/parse-findings.test.js +0 -25
- package/dist/deep/pr-review.test.d.ts +0 -1
- package/dist/deep/pr-review.test.js +0 -80
- package/dist/deep/prompts.test.d.ts +0 -1
- package/dist/deep/prompts.test.js +0 -235
- package/dist/deep/reference-pack.test.d.ts +0 -1
- package/dist/deep/reference-pack.test.js +0 -46
- package/dist/deep/related-changes.test.d.ts +0 -1
- package/dist/deep/related-changes.test.js +0 -33
- package/dist/deep/review-context-export.test.d.ts +0 -1
- package/dist/deep/review-context-export.test.js +0 -32
- package/dist/deep/review-tools.test.d.ts +0 -1
- package/dist/deep/review-tools.test.js +0 -39
- package/dist/deep/risk.test.d.ts +0 -1
- package/dist/deep/risk.test.js +0 -101
- package/dist/deep/verifier.test.d.ts +0 -1
- package/dist/deep/verifier.test.js +0 -635
- package/dist/discovery.test.d.ts +0 -1
- package/dist/discovery.test.js +0 -93
- package/dist/environment.test.d.ts +0 -1
- package/dist/environment.test.js +0 -94
- package/dist/firewall/firewall.test.d.ts +0 -1
- package/dist/firewall/firewall.test.js +0 -117
- package/dist/firewall/trust-boundaries.test.d.ts +0 -1
- package/dist/firewall/trust-boundaries.test.js +0 -64
- package/dist/firewall/trusted-control.test.d.ts +0 -1
- package/dist/firewall/trusted-control.test.js +0 -188
- package/dist/gates/agent-team.test.d.ts +0 -1
- package/dist/gates/agent-team.test.js +0 -113
- package/dist/gates/ast.test.d.ts +0 -1
- package/dist/gates/ast.test.js +0 -112
- package/dist/gates/checkpoint.test.d.ts +0 -1
- package/dist/gates/checkpoint.test.js +0 -105
- package/dist/gates/content.test.d.ts +0 -1
- package/dist/gates/content.test.js +0 -73
- package/dist/gates/coverage.test.d.ts +0 -1
- package/dist/gates/coverage.test.js +0 -53
- package/dist/gates/dedupe-failures.test.d.ts +0 -1
- package/dist/gates/dedupe-failures.test.js +0 -12
- package/dist/gates/deep-analysis.test.d.ts +0 -1
- package/dist/gates/deep-analysis.test.js +0 -86
- package/dist/gates/deep-intent.test.d.ts +0 -1
- package/dist/gates/deep-intent.test.js +0 -51
- package/dist/gates/deep-timeout.test.d.ts +0 -1
- package/dist/gates/deep-timeout.test.js +0 -10
- package/dist/gates/deprecated-apis.test.d.ts +0 -1
- package/dist/gates/deprecated-apis.test.js +0 -318
- package/dist/gates/deprecated-dependencies.test.d.ts +0 -1
- package/dist/gates/deprecated-dependencies.test.js +0 -55
- package/dist/gates/frontend-secret-exposure.test.d.ts +0 -1
- package/dist/gates/frontend-secret-exposure.test.js +0 -148
- package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.d.ts +0 -1
- package/dist/gates/hallucinated-imports/framework-modules-nuxt.test.js +0 -27
- package/dist/gates/hallucinated-imports/js-resolver-types.test.d.ts +0 -1
- package/dist/gates/hallucinated-imports/js-resolver-types.test.js +0 -14
- package/dist/gates/hallucinated-imports-sveltekit.test.d.ts +0 -1
- package/dist/gates/hallucinated-imports-sveltekit.test.js +0 -132
- package/dist/gates/hallucinated-imports.test.d.ts +0 -1
- package/dist/gates/hallucinated-imports.test.js +0 -1206
- package/dist/gates/js-style-context.test.d.ts +0 -1
- package/dist/gates/js-style-context.test.js +0 -35
- package/dist/gates/logic-drift.test.d.ts +0 -1
- package/dist/gates/logic-drift.test.js +0 -52
- package/dist/gates/phantom-apis.test.d.ts +0 -1
- package/dist/gates/phantom-apis.test.js +0 -396
- package/dist/gates/promise-safety.test.d.ts +0 -1
- package/dist/gates/promise-safety.test.js +0 -34
- package/dist/gates/runner.test.d.ts +0 -1
- package/dist/gates/runner.test.js +0 -77
- package/dist/gates/scoped-gates.test.d.ts +0 -1
- package/dist/gates/scoped-gates.test.js +0 -52
- package/dist/gates/security-patterns-owasp.test.d.ts +0 -1
- package/dist/gates/security-patterns-owasp.test.js +0 -186
- package/dist/gates/security-patterns.test.d.ts +0 -1
- package/dist/gates/security-patterns.test.js +0 -194
- package/dist/gates/semantic-bugs.test.d.ts +0 -1
- package/dist/gates/semantic-bugs.test.js +0 -76
- package/dist/gates/side-effect-analysis.test.d.ts +0 -1
- package/dist/gates/side-effect-analysis.test.js +0 -162
- package/dist/gates/style-drift.test.d.ts +0 -1
- package/dist/gates/style-drift.test.js +0 -26
- package/dist/gates/test-quality.test.d.ts +0 -1
- package/dist/gates/test-quality.test.js +0 -325
- package/dist/gates/trusted-reviews.test.d.ts +0 -1
- package/dist/gates/trusted-reviews.test.js +0 -16
- package/dist/gates/unindexed-reads/queries.test.d.ts +0 -1
- package/dist/gates/unindexed-reads/queries.test.js +0 -54
- package/dist/gates/unindexed-reads/schema.test.d.ts +0 -1
- package/dist/gates/unindexed-reads/schema.test.js +0 -81
- package/dist/gates/unindexed-reads/unindexed-reads.test.d.ts +0 -1
- package/dist/gates/unindexed-reads/unindexed-reads.test.js +0 -90
- package/dist/hooks/checker.test.d.ts +0 -1
- package/dist/hooks/checker.test.js +0 -159
- package/dist/hooks/dlp-confidence.test.d.ts +0 -1
- package/dist/hooks/dlp-confidence.test.js +0 -51
- package/dist/hooks/dlp-feedback.test.d.ts +0 -1
- package/dist/hooks/dlp-feedback.test.js +0 -131
- package/dist/hooks/input-validator.test.d.ts +0 -1
- package/dist/hooks/input-validator.test.js +0 -329
- package/dist/hooks/templates.test.d.ts +0 -1
- package/dist/hooks/templates.test.js +0 -27
- package/dist/inference/brain-placeholder.test.d.ts +0 -1
- package/dist/inference/brain-placeholder.test.js +0 -28
- package/dist/inference/cloud-provider.test.d.ts +0 -1
- package/dist/inference/cloud-provider.test.js +0 -139
- package/dist/inference/executable.test.d.ts +0 -1
- package/dist/inference/executable.test.js +0 -41
- package/dist/inference/http-download.test.d.ts +0 -1
- package/dist/inference/http-download.test.js +0 -109
- package/dist/inference/llama-engine-checksum.test.d.ts +0 -1
- package/dist/inference/llama-engine-checksum.test.js +0 -27
- package/dist/inference/llama-engine.test.d.ts +0 -1
- package/dist/inference/llama-engine.test.js +0 -51
- package/dist/inference/llama-process.test.d.ts +0 -1
- package/dist/inference/llama-process.test.js +0 -61
- package/dist/inference/local-model.test.d.ts +0 -1
- package/dist/inference/local-model.test.js +0 -23
- package/dist/inference/model-download.test.d.ts +0 -1
- package/dist/inference/model-download.test.js +0 -125
- package/dist/inference/model-manager.test.d.ts +0 -1
- package/dist/inference/model-manager.test.js +0 -24
- package/dist/inference/types.test.d.ts +0 -1
- package/dist/inference/types.test.js +0 -19
- package/dist/memory/recall.test.d.ts +0 -1
- package/dist/memory/recall.test.js +0 -36
- package/dist/pattern-index/indexer.test.d.ts +0 -6
- package/dist/pattern-index/indexer.test.js +0 -197
- package/dist/pattern-index/matcher.test.d.ts +0 -6
- package/dist/pattern-index/matcher.test.js +0 -238
- package/dist/pattern-index/pattern-reuse.test.d.ts +0 -1
- package/dist/pattern-index/pattern-reuse.test.js +0 -76
- package/dist/pattern-index/semantic-runtime.test.d.ts +0 -1
- package/dist/pattern-index/semantic-runtime.test.js +0 -31
- package/dist/pattern-index/staleness.test.d.ts +0 -6
- package/dist/pattern-index/staleness.test.js +0 -211
- package/dist/review/agent-fixes.test.d.ts +0 -1
- package/dist/review/agent-fixes.test.js +0 -32
- package/dist/review/backtest-init.test.d.ts +0 -1
- package/dist/review/backtest-init.test.js +0 -136
- package/dist/review/backtest-judges.test.d.ts +0 -1
- package/dist/review/backtest-judges.test.js +0 -32
- package/dist/review/backtest-last.test.d.ts +0 -1
- package/dist/review/backtest-last.test.js +0 -109
- package/dist/review/backtest.test.d.ts +0 -1
- package/dist/review/backtest.test.js +0 -183
- package/dist/review/baseline.test.d.ts +0 -1
- package/dist/review/baseline.test.js +0 -22
- package/dist/review/branch-checks.test.d.ts +0 -1
- package/dist/review/branch-checks.test.js +0 -48
- package/dist/review/check-outcomes.test.d.ts +0 -1
- package/dist/review/check-outcomes.test.js +0 -56
- package/dist/review/code-patterns.test.d.ts +0 -1
- package/dist/review/code-patterns.test.js +0 -142
- package/dist/review/dead-code.test.d.ts +0 -1
- package/dist/review/dead-code.test.js +0 -154
- package/dist/review/deep-runs.test.d.ts +0 -1
- package/dist/review/deep-runs.test.js +0 -23
- package/dist/review/effectiveness.test.d.ts +0 -1
- package/dist/review/effectiveness.test.js +0 -42
- package/dist/review/fix-scope.test.d.ts +0 -1
- package/dist/review/fix-scope.test.js +0 -104
- package/dist/review/generated-files.test.d.ts +0 -1
- package/dist/review/generated-files.test.js +0 -25
- package/dist/review/migration-order.test.d.ts +0 -1
- package/dist/review/migration-order.test.js +0 -62
- package/dist/review/quiet.test.d.ts +0 -1
- package/dist/review/quiet.test.js +0 -38
- package/dist/review/receipt.test.d.ts +0 -1
- package/dist/review/receipt.test.js +0 -60
- package/dist/review/review-task.test.d.ts +0 -1
- package/dist/review/review-task.test.js +0 -89
- package/dist/review/review.test.d.ts +0 -1
- package/dist/review/review.test.js +0 -203
- package/dist/review/reviewer/adapters.test.d.ts +0 -1
- package/dist/review/reviewer/adapters.test.js +0 -100
- package/dist/review/reviewer/api-judge.test.d.ts +0 -1
- package/dist/review/reviewer/api-judge.test.js +0 -108
- package/dist/review/reviewer/background.test.d.ts +0 -1
- package/dist/review/reviewer/background.test.js +0 -118
- package/dist/review/reviewer/context.test.d.ts +0 -1
- package/dist/review/reviewer/context.test.js +0 -45
- package/dist/review/reviewer/exec.test.d.ts +0 -1
- package/dist/review/reviewer/exec.test.js +0 -59
- package/dist/review/reviewer/inputs.test.d.ts +0 -1
- package/dist/review/reviewer/inputs.test.js +0 -52
- package/dist/review/reviewer/panel.test.d.ts +0 -1
- package/dist/review/reviewer/panel.test.js +0 -110
- package/dist/review/reviewer/record.test.d.ts +0 -1
- package/dist/review/reviewer/record.test.js +0 -40
- package/dist/review/reviewer/rule-writer.test.d.ts +0 -1
- package/dist/review/reviewer/rule-writer.test.js +0 -52
- package/dist/review/reviewer/settings.test.d.ts +0 -1
- package/dist/review/reviewer/settings.test.js +0 -57
- package/dist/review/reviewer/usage.test.d.ts +0 -1
- package/dist/review/reviewer/usage.test.js +0 -14
- package/dist/review/reviewer.test.d.ts +0 -1
- package/dist/review/reviewer.test.js +0 -792
- package/dist/review/stories.test.d.ts +0 -1
- package/dist/review/stories.test.js +0 -58
- package/dist/review/toolchain.test.d.ts +0 -1
- package/dist/review/toolchain.test.js +0 -108
- package/dist/review/typed/redundancy.test.d.ts +0 -1
- package/dist/review/typed/redundancy.test.js +0 -315
- package/dist/review/typed/schema-nullability.test.d.ts +0 -1
- package/dist/review/typed/schema-nullability.test.js +0 -63
- package/dist/review-learning/human-edits.test.d.ts +0 -1
- package/dist/review-learning/human-edits.test.js +0 -47
- package/dist/review-learning/repo-rules.test.d.ts +0 -1
- package/dist/review-learning/repo-rules.test.js +0 -93
- package/dist/review-learning/review-learning.test.d.ts +0 -1
- package/dist/review-learning/review-learning.test.js +0 -249
- package/dist/safety.test.d.ts +0 -1
- package/dist/safety.test.js +0 -42
- package/dist/semantic/benchmark.test.d.ts +0 -1
- package/dist/semantic/benchmark.test.js +0 -22
- package/dist/semantic/intent/intent.test.d.ts +0 -1
- package/dist/semantic/intent/intent.test.js +0 -46
- package/dist/semantic/learn/learn.test.d.ts +0 -1
- package/dist/semantic/learn/learn.test.js +0 -67
- package/dist/semantic/origins.test.d.ts +0 -1
- package/dist/semantic/origins.test.js +0 -77
- package/dist/semantic/project-facts.test.d.ts +0 -1
- package/dist/semantic/project-facts.test.js +0 -45
- package/dist/semantic/sites/call-sites.test.d.ts +0 -1
- package/dist/semantic/sites/call-sites.test.js +0 -46
- package/dist/services/adaptive-thresholds.test.d.ts +0 -1
- package/dist/services/adaptive-thresholds.test.js +0 -53
- package/dist/services/agent-history.test.d.ts +0 -1
- package/dist/services/agent-history.test.js +0 -69
- package/dist/services/context-scope-summary.test.d.ts +0 -1
- package/dist/services/context-scope-summary.test.js +0 -17
- package/dist/services/context-telemetry-service.test.d.ts +0 -1
- package/dist/services/context-telemetry-service.test.js +0 -182
- package/dist/services/cursor-usage-sync.test.d.ts +0 -1
- package/dist/services/cursor-usage-sync.test.js +0 -173
- package/dist/services/engineering-knowledge-graph.test.d.ts +0 -1
- package/dist/services/engineering-knowledge-graph.test.js +0 -76
- package/dist/services/model-pricing.test.d.ts +0 -1
- package/dist/services/model-pricing.test.js +0 -44
- package/dist/services/observed-savings.test.d.ts +0 -1
- package/dist/services/observed-savings.test.js +0 -37
- package/dist/services/score-history.test.d.ts +0 -1
- package/dist/services/score-history.test.js +0 -61
- package/dist/smoke.test.d.ts +0 -1
- package/dist/smoke.test.js +0 -17
- package/dist/storage/cache-cleanup.test.d.ts +0 -1
- package/dist/storage/cache-cleanup.test.js +0 -54
- package/dist/storage/context-telemetry.test.d.ts +0 -1
- package/dist/storage/context-telemetry.test.js +0 -80
- package/dist/storage/db.test.d.ts +0 -1
- package/dist/storage/db.test.js +0 -46
- package/dist/storage/fix-lessons.test.d.ts +0 -1
- package/dist/storage/fix-lessons.test.js +0 -61
- package/dist/storage/lessons.test.d.ts +0 -1
- package/dist/storage/lessons.test.js +0 -81
- package/dist/storage/local-encryption.test.d.ts +0 -1
- package/dist/storage/local-encryption.test.js +0 -34
- package/dist/storage/local-memory.test.d.ts +0 -1
- package/dist/storage/local-memory.test.js +0 -55
- package/dist/storage/share-memory.test.d.ts +0 -1
- package/dist/storage/share-memory.test.js +0 -34
- package/dist/storage/team-diagnostics.test.d.ts +0 -1
- package/dist/storage/team-diagnostics.test.js +0 -51
- package/dist/storage/team-scope.test.d.ts +0 -1
- package/dist/storage/team-scope.test.js +0 -22
- package/dist/storage/team-store.test.d.ts +0 -1
- package/dist/storage/team-store.test.js +0 -11
- package/dist/storage/team-sync-scope.test.d.ts +0 -1
- package/dist/storage/team-sync-scope.test.js +0 -100
- package/dist/storage/team-vector-store.test.d.ts +0 -1
- package/dist/storage/team-vector-store.test.js +0 -56
- package/dist/storage/telemetry-scope.test.d.ts +0 -1
- package/dist/storage/telemetry-scope.test.js +0 -38
- package/dist/task/thread.test.d.ts +0 -1
- package/dist/task/thread.test.js +0 -133
- package/dist/telemetry/telemetry.test.d.ts +0 -1
- package/dist/telemetry/telemetry.test.js +0 -64
- package/dist/types/index.test.d.ts +0 -1
- package/dist/types/index.test.js +0 -33
- package/dist/utils/command-line.test.d.ts +0 -1
- package/dist/utils/command-line.test.js +0 -8
- package/dist/utils/diff-removed.test.d.ts +0 -1
- package/dist/utils/diff-removed.test.js +0 -29
- package/dist/utils/diff.test.d.ts +0 -1
- package/dist/utils/diff.test.js +0 -38
- package/dist/utils/glob-paths.test.d.ts +0 -1
- package/dist/utils/glob-paths.test.js +0 -40
- package/dist/utils/profile.test.d.ts +0 -1
- package/dist/utils/profile.test.js +0 -68
- package/dist/utils/scanner.test.d.ts +0 -1
- package/dist/utils/scanner.test.js +0 -48
- package/dist/utils/scope.test.d.ts +0 -1
- package/dist/utils/scope.test.js +0 -38
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the hooks fast-checker module.
|
|
3
|
-
* Verifies all 4 fast gates: file-size, hallucinated-imports, promise-safety, security-patterns.
|
|
4
|
-
*/
|
|
5
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
6
|
-
import { runHookChecker } from './checker.js';
|
|
7
|
-
import * as fs from 'fs';
|
|
8
|
-
import * as path from 'path';
|
|
9
|
-
import * as os from 'os';
|
|
10
|
-
import yaml from 'yaml';
|
|
11
|
-
describe('runHookChecker', () => {
|
|
12
|
-
let testDir;
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'hook-checker-test-'));
|
|
15
|
-
// Write minimal rigour.yml
|
|
16
|
-
fs.writeFileSync(path.join(testDir, 'rigour.yml'), yaml.stringify({
|
|
17
|
-
version: 1,
|
|
18
|
-
gates: { max_file_lines: 50 },
|
|
19
|
-
}));
|
|
20
|
-
// Write package.json for import resolution
|
|
21
|
-
fs.writeFileSync(path.join(testDir, 'package.json'), JSON.stringify({
|
|
22
|
-
name: 'test-proj',
|
|
23
|
-
dependencies: { express: '^4.0.0' },
|
|
24
|
-
}));
|
|
25
|
-
});
|
|
26
|
-
afterEach(() => {
|
|
27
|
-
fs.rmSync(testDir, { recursive: true, force: true });
|
|
28
|
-
});
|
|
29
|
-
it('should return pass for clean files', async () => {
|
|
30
|
-
const filePath = path.join(testDir, 'clean.ts');
|
|
31
|
-
fs.writeFileSync(filePath, 'export const x = 1;\n');
|
|
32
|
-
const result = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
33
|
-
expect(result.status).toBe('pass');
|
|
34
|
-
expect(result.failures).toHaveLength(0);
|
|
35
|
-
expect(result.duration_ms).toBeGreaterThanOrEqual(0);
|
|
36
|
-
});
|
|
37
|
-
it('lets an agent edit CLAUDE.md by default, and blocks it only when the team opts in', async () => {
|
|
38
|
-
const filePath = path.join(testDir, 'CLAUDE.md');
|
|
39
|
-
fs.writeFileSync(filePath, '# Rules\n\n- Use the retry wrapper for partner APIs.\n');
|
|
40
|
-
const byDefault = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
41
|
-
expect(byDefault.failures.filter(f => f.gate === 'governance')).toEqual([]);
|
|
42
|
-
fs.writeFileSync(path.join(testDir, 'rigour.yml'), yaml.stringify({ version: 1, gates: { governance: { enforce_memory: true } } }));
|
|
43
|
-
const optedIn = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
44
|
-
expect(optedIn.failures.some(f => f.gate === 'governance')).toBe(true);
|
|
45
|
-
});
|
|
46
|
-
it("refuses an agent edit to Rigour's own state, even when rigour.yml ignores .rigour/", async () => {
|
|
47
|
-
fs.writeFileSync(path.join(testDir, 'rigour.yml'), 'version: 1\nignore:\n - ".rigour/**"\n');
|
|
48
|
-
fs.mkdirSync(path.join(testDir, '.rigour'), { recursive: true });
|
|
49
|
-
fs.writeFileSync(path.join(testDir, '.rigour', 'dismissed.json'), '{"version":1,"entries":[]}');
|
|
50
|
-
const result = await runHookChecker({ cwd: testDir, files: ['.rigour/dismissed.json'] });
|
|
51
|
-
expect(result.status).toBe('fail');
|
|
52
|
-
expect(result.failures[0]).toMatchObject({ gate: 'file-guard', severity: 'critical' });
|
|
53
|
-
});
|
|
54
|
-
it('catches a real vendor key whatever it is named, and leaves publishable and test keys alone', async () => {
|
|
55
|
-
// Built at runtime: a key-shaped literal in this source would be (rightly) refused by secret scanning.
|
|
56
|
-
const fake = (prefix) => `${prefix}_${'51HxQ'}${'abcdefghijklmnopqrstuv'}`;
|
|
57
|
-
fs.writeFileSync(path.join(testDir, 'pay.ts'), `export const stripe = {\n value: "${fake('sk_live')}",\n};\n`);
|
|
58
|
-
fs.writeFileSync(path.join(testDir, 'public.ts'), `export const key = "${fake('pk_live')}";\nexport const t = "${fake('sk_test')}";\n`);
|
|
59
|
-
const leaked = await runHookChecker({ cwd: testDir, files: ['pay.ts'] });
|
|
60
|
-
expect(leaked.failures).toEqual([expect.objectContaining({ gate: 'security-patterns', line: 2, severity: 'critical', message: 'Stripe API key detected in code' })]);
|
|
61
|
-
const fine = await runHookChecker({ cwd: testDir, files: ['public.ts'] });
|
|
62
|
-
expect(fine.failures.filter(f => f.gate === 'security-patterns')).toEqual([]);
|
|
63
|
-
});
|
|
64
|
-
it('should detect file size violations', async () => {
|
|
65
|
-
const filePath = path.join(testDir, 'big.ts');
|
|
66
|
-
const lines = Array.from({ length: 100 }, (_, i) => `export const v${i} = ${i};`);
|
|
67
|
-
fs.writeFileSync(filePath, lines.join('\n'));
|
|
68
|
-
const result = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
69
|
-
expect(result.status).toBe('fail');
|
|
70
|
-
expect(result.failures.some(f => f.gate === 'file-size')).toBe(true);
|
|
71
|
-
});
|
|
72
|
-
it('should detect hardcoded secrets', async () => {
|
|
73
|
-
const filePath = path.join(testDir, 'auth.ts');
|
|
74
|
-
fs.writeFileSync(filePath, `
|
|
75
|
-
const api_key = "abcdefghijklmnopqrstuvwxyz123456";
|
|
76
|
-
`);
|
|
77
|
-
const result = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
78
|
-
expect(result.status).toBe('fail');
|
|
79
|
-
expect(result.failures.some(f => f.gate === 'security-patterns')).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
it('should detect command injection patterns', async () => {
|
|
82
|
-
const filePath = path.join(testDir, 'cmd.ts');
|
|
83
|
-
fs.writeFileSync(filePath, `
|
|
84
|
-
import { exec } from 'child_process';
|
|
85
|
-
exec(\`rm -rf \${userInput}\`);
|
|
86
|
-
`);
|
|
87
|
-
const result = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
88
|
-
expect(result.status).toBe('fail');
|
|
89
|
-
expect(result.failures.some(f => f.gate === 'security-patterns' && f.message.includes('command injection'))).toBe(true);
|
|
90
|
-
});
|
|
91
|
-
it('should detect JSON.parse without try/catch', async () => {
|
|
92
|
-
const filePath = path.join(testDir, 'parse.ts');
|
|
93
|
-
fs.writeFileSync(filePath, `
|
|
94
|
-
const data = JSON.parse(input);
|
|
95
|
-
console.log(data);
|
|
96
|
-
`);
|
|
97
|
-
const result = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
98
|
-
expect(result.status).toBe('fail');
|
|
99
|
-
expect(result.failures.some(f => f.gate === 'promise-safety')).toBe(true);
|
|
100
|
-
});
|
|
101
|
-
it('should skip non-existent files gracefully', async () => {
|
|
102
|
-
const result = await runHookChecker({
|
|
103
|
-
cwd: testDir,
|
|
104
|
-
files: ['/does/not/exist.ts'],
|
|
105
|
-
});
|
|
106
|
-
expect(result.status).toBe('pass');
|
|
107
|
-
expect(result.failures).toHaveLength(0);
|
|
108
|
-
});
|
|
109
|
-
it('should handle multiple files', async () => {
|
|
110
|
-
const cleanFile = path.join(testDir, 'clean.ts');
|
|
111
|
-
fs.writeFileSync(cleanFile, 'export const x = 1;\n');
|
|
112
|
-
const badFile = path.join(testDir, 'bad.ts');
|
|
113
|
-
fs.writeFileSync(badFile, `const password = "supersecretpassword123456";`);
|
|
114
|
-
const result = await runHookChecker({
|
|
115
|
-
cwd: testDir,
|
|
116
|
-
files: [cleanFile, badFile],
|
|
117
|
-
});
|
|
118
|
-
expect(result.status).toBe('fail');
|
|
119
|
-
expect(result.failures.length).toBeGreaterThan(0);
|
|
120
|
-
});
|
|
121
|
-
it('should handle missing config gracefully', async () => {
|
|
122
|
-
// Remove rigour.yml
|
|
123
|
-
fs.unlinkSync(path.join(testDir, 'rigour.yml'));
|
|
124
|
-
const filePath = path.join(testDir, 'test.ts');
|
|
125
|
-
fs.writeFileSync(filePath, 'export const x = 1;\n');
|
|
126
|
-
const result = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
127
|
-
expect(result.status).toBe('pass');
|
|
128
|
-
});
|
|
129
|
-
it('should complete within timeout', async () => {
|
|
130
|
-
const filePath = path.join(testDir, 'test.ts');
|
|
131
|
-
fs.writeFileSync(filePath, 'export const x = 1;\n');
|
|
132
|
-
const result = await runHookChecker({
|
|
133
|
-
cwd: testDir,
|
|
134
|
-
files: [filePath],
|
|
135
|
-
timeout_ms: 5000,
|
|
136
|
-
});
|
|
137
|
-
expect(result.duration_ms).toBeLessThan(5000);
|
|
138
|
-
});
|
|
139
|
-
it('should detect hallucinated relative imports', async () => {
|
|
140
|
-
const filePath = path.join(testDir, 'app.ts');
|
|
141
|
-
fs.writeFileSync(filePath, `
|
|
142
|
-
import { helper } from './nonexistent-module';
|
|
143
|
-
`);
|
|
144
|
-
const result = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
145
|
-
expect(result.status).toBe('fail');
|
|
146
|
-
expect(result.failures.some(f => f.gate === 'hallucinated-imports')).toBe(true);
|
|
147
|
-
});
|
|
148
|
-
it('should not flag existing relative imports', async () => {
|
|
149
|
-
const helperPath = path.join(testDir, 'helper.ts');
|
|
150
|
-
fs.writeFileSync(helperPath, 'export const help = true;\n');
|
|
151
|
-
const filePath = path.join(testDir, 'app.ts');
|
|
152
|
-
fs.writeFileSync(filePath, `
|
|
153
|
-
import { help } from './helper';
|
|
154
|
-
`);
|
|
155
|
-
const result = await runHookChecker({ cwd: testDir, files: [filePath] });
|
|
156
|
-
const importFailures = result.failures.filter(f => f.gate === 'hallucinated-imports');
|
|
157
|
-
expect(importFailures).toHaveLength(0);
|
|
158
|
-
});
|
|
159
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { createDLPAuditEntry, formatDLPAlert, scanInputForCredentials, } from './input-validator.js';
|
|
3
|
-
describe('DLP confidence engine', () => {
|
|
4
|
-
it('allows explicit example password assignments', () => {
|
|
5
|
-
const result = scanInputForCredentials('password = "examplepassword"');
|
|
6
|
-
expect(result.status).toBe('clean');
|
|
7
|
-
expect(result.allowed_detections?.[0].decision).toBe('allow');
|
|
8
|
-
});
|
|
9
|
-
it('warns on high-entropy values even with api_key label', () => {
|
|
10
|
-
const result = scanInputForCredentials('api_key: "abcdefZ9y8X7w6V5u4T3s2R1q0P9o8N7m6"');
|
|
11
|
-
expect(result.status).toBe('warning');
|
|
12
|
-
expect(result.detections[0].decision).toBe('warn');
|
|
13
|
-
});
|
|
14
|
-
it('allows localhost database URLs with placeholder credentials', () => {
|
|
15
|
-
const result = scanInputForCredentials('DATABASE_URL=postgresql://user:password@localhost:5432/db');
|
|
16
|
-
expect(result.status).toBe('clean');
|
|
17
|
-
});
|
|
18
|
-
it('warns for live Stripe publishable keys', () => {
|
|
19
|
-
const result = scanInputForCredentials('STRIPE_PUBLIC_KEY=pk_live_123456789012345678901234');
|
|
20
|
-
expect(result.status).toBe('warning');
|
|
21
|
-
expect(result.detections[0].decision).toBe('warn');
|
|
22
|
-
expect(result.detections[0].reason_codes).toContain('public_live_key');
|
|
23
|
-
});
|
|
24
|
-
it('allows provider keys in comments (reduced false positives)', () => {
|
|
25
|
-
const result = scanInputForCredentials('// AWS_ACCESS_KEY_ID=AKIAZ9Y8X7W6V5U4T3Q2');
|
|
26
|
-
expect(result.status).toBe('clean');
|
|
27
|
-
});
|
|
28
|
-
it('allows GitHub tokens in comments', () => {
|
|
29
|
-
const result = scanInputForCredentials('// ghp_Z9Y8X7W6V5U4T3S2R1Q0P9O8N7M6B5C4A3D2');
|
|
30
|
-
expect(result.status).toBe('clean');
|
|
31
|
-
});
|
|
32
|
-
it('blocks JWT tokens in comments', () => {
|
|
33
|
-
const jwt = '// token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJwcm9kLXVzZXIiLCJpc3MiOiJhdXRoLXNlcnZpY2UifQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
|
|
34
|
-
const result = scanInputForCredentials(jwt);
|
|
35
|
-
expect(result.status).toBe('blocked');
|
|
36
|
-
expect(result.detections.some(d => d.type === 'jwt_token')).toBe(true);
|
|
37
|
-
});
|
|
38
|
-
it('shows allowed safe values in clean output', () => {
|
|
39
|
-
const result = scanInputForCredentials('api_key: "abcdefghijklmnopqrstuvwxyz"');
|
|
40
|
-
const alert = formatDLPAlert(result);
|
|
41
|
-
expect(alert).toContain('allowed 1 sample or safe credential-like value');
|
|
42
|
-
});
|
|
43
|
-
it('includes allowed detections without raw values in audit log', () => {
|
|
44
|
-
const result = scanInputForCredentials('api_key: "abcdefghijklmnopqrstuvwxyz"');
|
|
45
|
-
const entry = createDLPAuditEntry(result, { agent: 'claude' });
|
|
46
|
-
const allowed = entry.allowed_detections;
|
|
47
|
-
expect(allowed).toHaveLength(1);
|
|
48
|
-
expect(allowed[0].decision).toBe('allow');
|
|
49
|
-
expect(allowed[0].match).toBeUndefined();
|
|
50
|
-
});
|
|
51
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import os from 'os';
|
|
4
|
-
import fs from 'fs-extra';
|
|
5
|
-
import { recordDLPFeedback, feedbackFingerprint, loadDLPFeedbackStoreSync, isLearnedAllowSync, writeDLPBlockManifest, allowLastDLPBlock, } from './dlp-feedback.js';
|
|
6
|
-
import { scanInputForCredentials } from './input-validator.js';
|
|
7
|
-
import { generateDLPHookFiles } from './dlp-templates.js';
|
|
8
|
-
describe('DLP feedback learning', () => {
|
|
9
|
-
const testCwd = path.join(os.tmpdir(), `rigour-dlp-fb-${Date.now()}`);
|
|
10
|
-
beforeEach(async () => {
|
|
11
|
-
await fs.ensureDir(path.join(testCwd, '.rigour'));
|
|
12
|
-
});
|
|
13
|
-
afterEach(async () => {
|
|
14
|
-
await fs.remove(testCwd);
|
|
15
|
-
});
|
|
16
|
-
it('produces stable fingerprints for same shape', () => {
|
|
17
|
-
const a = feedbackFingerprint('password_assignment', 'api_key = "your-key-here"');
|
|
18
|
-
const b = feedbackFingerprint('password_assignment', 'api_key = "your-key-here"');
|
|
19
|
-
expect(a).toBe(b);
|
|
20
|
-
});
|
|
21
|
-
it('records and applies learned false positives', async () => {
|
|
22
|
-
const match = 'api_key = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"';
|
|
23
|
-
await recordDLPFeedback(testCwd, {
|
|
24
|
-
type: 'password_assignment',
|
|
25
|
-
match,
|
|
26
|
-
confidence: 55,
|
|
27
|
-
source: 'hook',
|
|
28
|
-
});
|
|
29
|
-
const store = loadDLPFeedbackStoreSync(testCwd);
|
|
30
|
-
expect(isLearnedAllowSync(store, 'password_assignment', match)).toBe(true);
|
|
31
|
-
const result = scanInputForCredentials(match, { cwd: testCwd });
|
|
32
|
-
expect(result.status).toBe('clean');
|
|
33
|
-
expect(result.allowed_detections?.[0].reason_codes).toContain('learned_false_positive');
|
|
34
|
-
});
|
|
35
|
-
it('allowLastDLPBlock learns from manifest', async () => {
|
|
36
|
-
const text = 'api_key = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"';
|
|
37
|
-
const blocked = scanInputForCredentials(text, { cwd: testCwd, block_on_detection: true });
|
|
38
|
-
expect(blocked.status).toBe('warning');
|
|
39
|
-
await writeDLPBlockManifest(testCwd, blocked.detections, text);
|
|
40
|
-
const learned = await allowLastDLPBlock(testCwd, 'hook');
|
|
41
|
-
expect(learned).toBeGreaterThan(0);
|
|
42
|
-
const retry = scanInputForCredentials(text, { cwd: testCwd });
|
|
43
|
-
expect(retry.status).toBe('clean');
|
|
44
|
-
});
|
|
45
|
-
it('never learns provider or high-confidence detections', async () => {
|
|
46
|
-
const provider = await recordDLPFeedback(testCwd, {
|
|
47
|
-
type: 'openai_key',
|
|
48
|
-
match: 'sk-proj-Z9Y8X7W6V5U4T3S2R1Q0P9O8N7M6',
|
|
49
|
-
confidence: 92,
|
|
50
|
-
});
|
|
51
|
-
const highConfidence = await recordDLPFeedback(testCwd, {
|
|
52
|
-
type: 'password_assignment',
|
|
53
|
-
match: 'password = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"',
|
|
54
|
-
confidence: 95,
|
|
55
|
-
});
|
|
56
|
-
expect(provider).toBeNull();
|
|
57
|
-
expect(highConfidence).toBeNull();
|
|
58
|
-
expect(loadDLPFeedbackStoreSync(testCwd).entries).toHaveLength(0);
|
|
59
|
-
});
|
|
60
|
-
it('does not retain raw credential fragments in manifests', async () => {
|
|
61
|
-
const text = 'api_key = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"';
|
|
62
|
-
const result = scanInputForCredentials(text);
|
|
63
|
-
expect(result.detections[0].match).toBe(result.detections[0].redacted);
|
|
64
|
-
expect(result.detections[0].match).not.toContain('Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4');
|
|
65
|
-
await writeDLPBlockManifest(testCwd, result.detections, text);
|
|
66
|
-
const manifest = fs.readFileSync(path.join(testCwd, '.rigour', 'dlp-last-block.json'), 'utf-8');
|
|
67
|
-
expect(manifest).not.toContain('Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4');
|
|
68
|
-
expect(manifest).not.toContain('match');
|
|
69
|
-
expect(manifest).not.toContain('shape');
|
|
70
|
-
});
|
|
71
|
-
it('rejects and consumes expired manifests', async () => {
|
|
72
|
-
const text = 'api_key = "Z9y8X7w6V5u4T3s2R1q0P9o8N7m6B5c4"';
|
|
73
|
-
const result = scanInputForCredentials(text);
|
|
74
|
-
await writeDLPBlockManifest(testCwd, result.detections, text);
|
|
75
|
-
const manifestPath = path.join(testCwd, '.rigour', 'dlp-last-block.json');
|
|
76
|
-
const manifest = fs.readJsonSync(manifestPath);
|
|
77
|
-
manifest.timestamp = '2020-01-01T00:00:00.000Z';
|
|
78
|
-
fs.writeJsonSync(manifestPath, manifest);
|
|
79
|
-
expect(await allowLastDLPBlock(testCwd, 'hook')).toBe(0);
|
|
80
|
-
expect(fs.existsSync(manifestPath)).toBe(false);
|
|
81
|
-
});
|
|
82
|
-
it('rejects and consumes malformed manifests', async () => {
|
|
83
|
-
const manifestPath = path.join(testCwd, '.rigour', 'dlp-last-block.json');
|
|
84
|
-
fs.writeFileSync(manifestPath, '{not-json');
|
|
85
|
-
expect(await allowLastDLPBlock(testCwd, 'hook')).toBe(0);
|
|
86
|
-
expect(fs.existsSync(manifestPath)).toBe(false);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
describe('DLP scanner URL boundaries', () => {
|
|
90
|
-
it('detects genuine HTTP basic-auth credentials', () => {
|
|
91
|
-
const result = scanInputForCredentials('https://alice:S3cr3t-Prod-9842@example.com/v1');
|
|
92
|
-
expect(result.status).toBe('warning');
|
|
93
|
-
expect(result.detections.some(d => d.type === 'credentials_in_url')).toBe(true);
|
|
94
|
-
});
|
|
95
|
-
it('allows signed GCS URLs without URL user-info', () => {
|
|
96
|
-
const url = 'https://storage.googleapis.com/example/archive.zip'
|
|
97
|
-
+ '?X-Goog-Credential=service%40example.invalid&X-Goog-Signature=redacted';
|
|
98
|
-
expect(scanInputForCredentials(url).status).toBe('clean');
|
|
99
|
-
});
|
|
100
|
-
it('does not cross multiline JSON boundaries while scanning URLs', () => {
|
|
101
|
-
const input = `{
|
|
102
|
-
"task_archive_url": "https://storage.googleapis.com/example/archive.zip",
|
|
103
|
-
"provider": { "npm": "@ai-sdk/openai-compatible" }
|
|
104
|
-
}`;
|
|
105
|
-
expect(scanInputForCredentials(input).status).toBe('clean');
|
|
106
|
-
});
|
|
107
|
-
it('allows nested OpenCode configuration with scoped npm packages', () => {
|
|
108
|
-
const config = JSON.stringify({
|
|
109
|
-
$schema: 'https://opencode.ai/config.json',
|
|
110
|
-
provider: {
|
|
111
|
-
moonshot: {
|
|
112
|
-
npm: '@ai-sdk/openai-compatible',
|
|
113
|
-
options: {
|
|
114
|
-
baseURL: 'https://api.moonshot.ai/v1',
|
|
115
|
-
apiKey: '{env:OPENAI_API_KEY}',
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
}, null, 2);
|
|
120
|
-
expect(scanInputForCredentials(config).status).toBe('clean');
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
describe('DLP hook warning templates', () => {
|
|
124
|
-
it.each(['cursor', 'cline', 'windsurf'])('generates non-blocking %s warnings', (tool) => {
|
|
125
|
-
const content = generateDLPHookFiles(tool, 'rigour hooks check')
|
|
126
|
-
.map(file => file.content)
|
|
127
|
-
.join('\n');
|
|
128
|
-
expect(content).toContain('possible credential');
|
|
129
|
-
expect(content).not.toContain('process.exit(2)');
|
|
130
|
-
});
|
|
131
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|