@brett.buskirk/agent-gate 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +196 -0
  3. package/action.yml +30 -0
  4. package/bin/agent-gate.js +3 -0
  5. package/lib/action.d.ts +2 -0
  6. package/lib/action.d.ts.map +1 -0
  7. package/lib/action.js +73 -0
  8. package/lib/cli.d.ts +3 -0
  9. package/lib/cli.d.ts.map +1 -0
  10. package/lib/cli.js +36 -0
  11. package/lib/config/load.d.ts +3 -0
  12. package/lib/config/load.d.ts.map +1 -0
  13. package/lib/config/load.js +14 -0
  14. package/lib/config/schema.d.ts +236 -0
  15. package/lib/config/schema.d.ts.map +1 -0
  16. package/lib/config/schema.js +66 -0
  17. package/lib/diff/git.d.ts +9 -0
  18. package/lib/diff/git.d.ts.map +1 -0
  19. package/lib/diff/git.js +20 -0
  20. package/lib/diff/github.d.ts +11 -0
  21. package/lib/diff/github.d.ts.map +1 -0
  22. package/lib/diff/github.js +33 -0
  23. package/lib/diff/parse.d.ts +24 -0
  24. package/lib/diff/parse.d.ts.map +1 -0
  25. package/lib/diff/parse.js +65 -0
  26. package/lib/diff/provider.d.ts +5 -0
  27. package/lib/diff/provider.d.ts.map +1 -0
  28. package/lib/diff/provider.js +2 -0
  29. package/lib/engine.d.ts +15 -0
  30. package/lib/engine.d.ts.map +1 -0
  31. package/lib/engine.js +22 -0
  32. package/lib/report/checkRun.d.ts +3 -0
  33. package/lib/report/checkRun.d.ts.map +1 -0
  34. package/lib/report/checkRun.js +51 -0
  35. package/lib/report/comment.d.ts +4 -0
  36. package/lib/report/comment.d.ts.map +1 -0
  37. package/lib/report/comment.js +71 -0
  38. package/lib/report/json.d.ts +4 -0
  39. package/lib/report/json.d.ts.map +1 -0
  40. package/lib/report/json.js +50 -0
  41. package/lib/report/summary.d.ts +4 -0
  42. package/lib/report/summary.d.ts.map +1 -0
  43. package/lib/report/summary.js +56 -0
  44. package/lib/rules/dangerousPatterns.d.ts +3 -0
  45. package/lib/rules/dangerousPatterns.d.ts.map +1 -0
  46. package/lib/rules/dangerousPatterns.js +42 -0
  47. package/lib/rules/dependencies.d.ts +3 -0
  48. package/lib/rules/dependencies.d.ts.map +1 -0
  49. package/lib/rules/dependencies.js +26 -0
  50. package/lib/rules/diffSize.d.ts +3 -0
  51. package/lib/rules/diffSize.d.ts.map +1 -0
  52. package/lib/rules/diffSize.js +31 -0
  53. package/lib/rules/index.d.ts +4 -0
  54. package/lib/rules/index.d.ts.map +1 -0
  55. package/lib/rules/index.js +17 -0
  56. package/lib/rules/scope.d.ts +3 -0
  57. package/lib/rules/scope.d.ts.map +1 -0
  58. package/lib/rules/scope.js +37 -0
  59. package/lib/rules/secrets.d.ts +3 -0
  60. package/lib/rules/secrets.d.ts.map +1 -0
  61. package/lib/rules/secrets.js +60 -0
  62. package/lib/rules/testsRequired.d.ts +3 -0
  63. package/lib/rules/testsRequired.d.ts.map +1 -0
  64. package/lib/rules/testsRequired.js +26 -0
  65. package/lib/rules/types.d.ts +18 -0
  66. package/lib/rules/types.d.ts.map +1 -0
  67. package/lib/rules/types.js +2 -0
  68. package/lib/utils/glob.d.ts +3 -0
  69. package/lib/utils/glob.d.ts.map +1 -0
  70. package/lib/utils/glob.js +42 -0
  71. package/package.json +66 -0
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfigSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ const SeveritySchema = zod_1.z.enum(['error', 'warning', 'info']);
6
+ exports.ConfigSchema = zod_1.z.object({
7
+ version: zod_1.z.literal(1),
8
+ fail_on: zod_1.z.enum(['error', 'warning', 'never']).default('error'),
9
+ comment: zod_1.z.boolean().default(true),
10
+ rules: zod_1.z
11
+ .object({
12
+ secrets: zod_1.z
13
+ .object({
14
+ enabled: zod_1.z.boolean().default(true),
15
+ severity: SeveritySchema.default('error'),
16
+ })
17
+ .default({}),
18
+ scope: zod_1.z
19
+ .object({
20
+ enabled: zod_1.z.boolean().default(true),
21
+ severity: SeveritySchema.default('error'),
22
+ allow: zod_1.z.array(zod_1.z.string()).optional(),
23
+ deny: zod_1.z
24
+ .array(zod_1.z.string())
25
+ .default(['.github/workflows/**', 'infra/**', '**/*.lock', 'package-lock.json']),
26
+ })
27
+ .default({}),
28
+ diff_size: zod_1.z
29
+ .object({
30
+ enabled: zod_1.z.boolean().default(true),
31
+ severity: SeveritySchema.default('warning'),
32
+ max_files: zod_1.z.number().int().positive().default(30),
33
+ max_lines: zod_1.z.number().int().positive().default(800),
34
+ })
35
+ .default({}),
36
+ tests_required: zod_1.z
37
+ .object({
38
+ enabled: zod_1.z.boolean().default(true),
39
+ severity: SeveritySchema.default('warning'),
40
+ src_globs: zod_1.z.array(zod_1.z.string()).default(['src/**']),
41
+ test_globs: zod_1.z
42
+ .array(zod_1.z.string())
43
+ .default(['**/*.test.*', '**/*.spec.*', 'tests/**']),
44
+ })
45
+ .default({}),
46
+ dependencies: zod_1.z
47
+ .object({
48
+ enabled: zod_1.z.boolean().default(true),
49
+ severity: SeveritySchema.default('warning'),
50
+ manifests: zod_1.z
51
+ .array(zod_1.z.string())
52
+ .default(['package.json', 'requirements.txt', 'go.mod', 'Gemfile', 'Cargo.toml']),
53
+ })
54
+ .default({}),
55
+ dangerous_patterns: zod_1.z
56
+ .object({
57
+ enabled: zod_1.z.boolean().default(true),
58
+ severity: SeveritySchema.default('error'),
59
+ patterns: zod_1.z
60
+ .array(zod_1.z.string())
61
+ .default(['eval\\(', '--no-verify', 'child_process\\.exec\\(']),
62
+ })
63
+ .default({}),
64
+ })
65
+ .default({}),
66
+ });
@@ -0,0 +1,9 @@
1
+ import type { DiffProvider } from './provider';
2
+ import type { DiffModel } from './parse';
3
+ export declare class GitDiffProvider implements DiffProvider {
4
+ private base;
5
+ private cwd;
6
+ constructor(base: string, cwd?: string);
7
+ getDiff(): Promise<DiffModel>;
8
+ }
9
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/diff/git.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,qBAAa,eAAgB,YAAW,YAAY;IAEhD,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,GAAG;gBADH,IAAI,EAAE,MAAM,EACZ,GAAG,SAAgB;IAGvB,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;CAQpC"}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitDiffProvider = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const parse_1 = require("./parse");
6
+ class GitDiffProvider {
7
+ constructor(base, cwd = process.cwd()) {
8
+ this.base = base;
9
+ this.cwd = cwd;
10
+ }
11
+ async getDiff() {
12
+ const patch = (0, child_process_1.execSync)(`git diff "${this.base}"...HEAD`, {
13
+ cwd: this.cwd,
14
+ encoding: 'utf8',
15
+ maxBuffer: 50 * 1024 * 1024,
16
+ });
17
+ return (0, parse_1.parsePatch)(patch);
18
+ }
19
+ }
20
+ exports.GitDiffProvider = GitDiffProvider;
@@ -0,0 +1,11 @@
1
+ import type { DiffProvider } from './provider';
2
+ import type { DiffModel } from './parse';
3
+ export declare class GitHubDiffProvider implements DiffProvider {
4
+ private token;
5
+ private owner;
6
+ private repo;
7
+ private pullNumber;
8
+ constructor(token: string, owner: string, repo: string, pullNumber: number);
9
+ getDiff(): Promise<DiffModel>;
10
+ }
11
+ //# sourceMappingURL=github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/diff/github.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,qBAAa,kBAAmB,YAAW,YAAY;IAEnD,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,UAAU;gBAHV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM;IAGtB,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC;CAuBpC"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GitHubDiffProvider = void 0;
4
+ const github_1 = require("@actions/github");
5
+ const parse_1 = require("./parse");
6
+ class GitHubDiffProvider {
7
+ constructor(token, owner, repo, pullNumber) {
8
+ this.token = token;
9
+ this.owner = owner;
10
+ this.repo = repo;
11
+ this.pullNumber = pullNumber;
12
+ }
13
+ async getDiff() {
14
+ const octokit = (0, github_1.getOctokit)(this.token);
15
+ const files = await octokit.paginate(octokit.rest.pulls.listFiles, {
16
+ owner: this.owner,
17
+ repo: this.repo,
18
+ pull_number: this.pullNumber,
19
+ per_page: 100,
20
+ });
21
+ const patches = files
22
+ .filter((f) => f.patch)
23
+ .map((f) => [
24
+ `diff --git a/${f.filename} b/${f.filename}`,
25
+ `--- a/${f.filename}`,
26
+ `+++ b/${f.filename}`,
27
+ f.patch,
28
+ ].join('\n'))
29
+ .join('\n');
30
+ return (0, parse_1.parsePatch)(patches);
31
+ }
32
+ }
33
+ exports.GitHubDiffProvider = GitHubDiffProvider;
@@ -0,0 +1,24 @@
1
+ export interface DiffLine {
2
+ type: 'add' | 'del' | 'normal';
3
+ content: string;
4
+ lineNumber?: number;
5
+ }
6
+ export interface DiffChunk {
7
+ lines: DiffLine[];
8
+ }
9
+ export interface DiffFile {
10
+ path: string;
11
+ oldPath: string | null;
12
+ added: number;
13
+ deleted: number;
14
+ isNew: boolean;
15
+ isDeleted: boolean;
16
+ chunks: DiffChunk[];
17
+ }
18
+ export interface DiffModel {
19
+ files: DiffFile[];
20
+ totalAdded: number;
21
+ totalDeleted: number;
22
+ }
23
+ export declare function parsePatch(patch: string): DiffModel;
24
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/diff/parse.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAID,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAmDnD"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parsePatch = parsePatch;
4
+ const HUNK_HEADER = /^@@ -\d+(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
5
+ function parsePatch(patch) {
6
+ const files = [];
7
+ let current = null;
8
+ let currentChunk = null;
9
+ let lineNum = 0;
10
+ for (const line of patch.split('\n')) {
11
+ if (line.startsWith('diff --git ')) {
12
+ if (current)
13
+ files.push(current);
14
+ current = { path: '', oldPath: null, added: 0, deleted: 0, isNew: false, isDeleted: false, chunks: [] };
15
+ currentChunk = null;
16
+ }
17
+ else if (line.startsWith('--- ')) {
18
+ if (!current)
19
+ continue;
20
+ const p = line.slice(4);
21
+ current.oldPath = p === '/dev/null' ? null : p.replace(/^a\//, '');
22
+ if (p === '/dev/null')
23
+ current.isNew = true;
24
+ }
25
+ else if (line.startsWith('+++ ')) {
26
+ if (!current)
27
+ continue;
28
+ const p = line.slice(4);
29
+ if (p === '/dev/null') {
30
+ current.isDeleted = true;
31
+ }
32
+ else {
33
+ current.path = p.replace(/^b\//, '');
34
+ }
35
+ }
36
+ else if (HUNK_HEADER.test(line)) {
37
+ if (!current)
38
+ continue;
39
+ const match = HUNK_HEADER.exec(line);
40
+ lineNum = parseInt(match[1], 10) - 1;
41
+ currentChunk = { lines: [] };
42
+ current.chunks.push(currentChunk);
43
+ }
44
+ else if (currentChunk && current) {
45
+ if (line.startsWith('+')) {
46
+ lineNum++;
47
+ currentChunk.lines.push({ type: 'add', content: line.slice(1), lineNumber: lineNum });
48
+ current.added++;
49
+ }
50
+ else if (line.startsWith('-')) {
51
+ currentChunk.lines.push({ type: 'del', content: line.slice(1) });
52
+ current.deleted++;
53
+ }
54
+ else if (line.startsWith(' ')) {
55
+ lineNum++;
56
+ currentChunk.lines.push({ type: 'normal', content: line.slice(1), lineNumber: lineNum });
57
+ }
58
+ }
59
+ }
60
+ if (current)
61
+ files.push(current);
62
+ const totalAdded = files.reduce((a, f) => a + f.added, 0);
63
+ const totalDeleted = files.reduce((a, f) => a + f.deleted, 0);
64
+ return { files, totalAdded, totalDeleted };
65
+ }
@@ -0,0 +1,5 @@
1
+ import type { DiffModel } from './parse';
2
+ export interface DiffProvider {
3
+ getDiff(): Promise<DiffModel>;
4
+ }
5
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/diff/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,WAAW,YAAY;IAC3B,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;CAC/B"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,15 @@
1
+ import type { Config } from './config/schema';
2
+ import type { DiffModel } from './diff/parse';
3
+ import type { Finding } from './rules/types';
4
+ export type Verdict = 'pass' | 'warn' | 'fail';
5
+ export interface EngineResult {
6
+ findings: Finding[];
7
+ verdict: Verdict;
8
+ counts: {
9
+ error: number;
10
+ warning: number;
11
+ info: number;
12
+ };
13
+ }
14
+ export declare function runEngine(diff: DiffModel, config: Config): EngineResult;
15
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,eAAe,CAAC;AAEvD,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAE/C,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1D;AAYD,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAcvE"}
package/lib/engine.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runEngine = runEngine;
4
+ const rules_1 = require("./rules");
5
+ function computeVerdict(counts, failOn) {
6
+ if (failOn === 'error' && counts.error > 0)
7
+ return 'fail';
8
+ if (failOn === 'warning' && (counts.error > 0 || counts.warning > 0))
9
+ return 'fail';
10
+ if (counts.error > 0 || counts.warning > 0)
11
+ return 'warn';
12
+ return 'pass';
13
+ }
14
+ function runEngine(diff, config) {
15
+ const findings = rules_1.rules.flatMap((rule) => rule.run(diff, config));
16
+ const counts = findings.reduce((acc, f) => {
17
+ acc[f.severity]++;
18
+ return acc;
19
+ }, { error: 0, warning: 0, info: 0 });
20
+ const verdict = computeVerdict(counts, config.fail_on);
21
+ return { findings, verdict, counts };
22
+ }
@@ -0,0 +1,3 @@
1
+ import type { EngineResult } from '../engine';
2
+ export declare function setCheckOutput(result: EngineResult): void;
3
+ //# sourceMappingURL=checkRun.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkRun.d.ts","sourceRoot":"","sources":["../../src/report/checkRun.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAE9C,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAezD"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.setCheckOutput = setCheckOutput;
37
+ const core = __importStar(require("@actions/core"));
38
+ function setCheckOutput(result) {
39
+ const { verdict, counts, findings } = result;
40
+ core.setOutput('verdict', verdict);
41
+ core.setOutput('finding-count', String(findings.length));
42
+ if (verdict === 'fail') {
43
+ core.setFailed(`AgentGate blocked: ${counts.error} error(s), ${counts.warning} warning(s) — see PR comment for details`);
44
+ }
45
+ else if (verdict === 'warn') {
46
+ core.warning(`AgentGate: ${counts.warning} warning(s)`);
47
+ }
48
+ else {
49
+ core.info('AgentGate: passed');
50
+ }
51
+ }
@@ -0,0 +1,4 @@
1
+ import type { EngineResult } from '../engine';
2
+ import type { DiffModel } from '../diff/parse';
3
+ export declare function upsertComment(token: string, owner: string, repo: string, pullNumber: number, result: EngineResult, diff: DiffModel): Promise<void>;
4
+ //# sourceMappingURL=comment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment.d.ts","sourceRoot":"","sources":["../../src/report/comment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAiE/C,wBAAsB,aAAa,CACjC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,IAAI,CAAC,CAkBf"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.upsertComment = upsertComment;
4
+ const github_1 = require("@actions/github");
5
+ const MARKER = '<!-- agentgate -->';
6
+ function buildBody(result, diff) {
7
+ const { verdict, findings } = result;
8
+ const header = verdict === 'pass'
9
+ ? '## ✅ AgentGate: Passed'
10
+ : verdict === 'warn'
11
+ ? '## ⚠️ AgentGate: Warnings'
12
+ : '## ❌ AgentGate: Blocked';
13
+ const lines = [
14
+ MARKER,
15
+ header,
16
+ '',
17
+ `**${diff.files.length}** files changed &nbsp;·&nbsp; **+${diff.totalAdded} -${diff.totalDeleted}** lines`,
18
+ '',
19
+ ];
20
+ if (findings.length === 0) {
21
+ lines.push('No issues found.');
22
+ }
23
+ else {
24
+ lines.push('| Rule | Findings | Severity |');
25
+ lines.push('|------|----------|----------|');
26
+ const byRule = new Map();
27
+ for (const f of findings) {
28
+ const entry = byRule.get(f.ruleId) ?? { count: 0, severity: f.severity };
29
+ entry.count++;
30
+ byRule.set(f.ruleId, entry);
31
+ }
32
+ for (const [rule, { count, severity }] of byRule) {
33
+ const icon = severity === 'error' ? '❌' : severity === 'warning' ? '⚠️' : 'ℹ️';
34
+ lines.push(`| \`${rule}\` | ${count} | ${icon} ${severity} |`);
35
+ }
36
+ lines.push('');
37
+ lines.push('<details><summary>View findings</summary>');
38
+ lines.push('');
39
+ for (const [ruleId] of byRule) {
40
+ lines.push(`**${ruleId}**`);
41
+ for (const f of findings.filter((x) => x.ruleId === ruleId)) {
42
+ const loc = f.file ? (f.line ? `\`${f.file}:${f.line}\`` : `\`${f.file}\``) : '';
43
+ lines.push(`- ${loc ? `${loc} — ` : ''}${f.message}`);
44
+ if (f.suggestion)
45
+ lines.push(` > 💡 ${f.suggestion}`);
46
+ }
47
+ lines.push('');
48
+ }
49
+ lines.push('</details>');
50
+ }
51
+ lines.push('');
52
+ lines.push('<sub>Generated by [AgentGate](https://github.com/brett-buskirk/agent-gate)</sub>');
53
+ return lines.join('\n');
54
+ }
55
+ async function upsertComment(token, owner, repo, pullNumber, result, diff) {
56
+ const octokit = (0, github_1.getOctokit)(token);
57
+ const body = buildBody(result, diff);
58
+ const { data: comments } = await octokit.rest.issues.listComments({
59
+ owner,
60
+ repo,
61
+ issue_number: pullNumber,
62
+ per_page: 100,
63
+ });
64
+ const existing = comments.find((c) => c.body?.includes(MARKER));
65
+ if (existing) {
66
+ await octokit.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
67
+ }
68
+ else {
69
+ await octokit.rest.issues.createComment({ owner, repo, issue_number: pullNumber, body });
70
+ }
71
+ }
@@ -0,0 +1,4 @@
1
+ import type { EngineResult } from '../engine';
2
+ import type { DiffModel } from '../diff/parse';
3
+ export declare function reportCli(result: EngineResult, diff: DiffModel, asJson?: boolean): void;
4
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/report/json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAQ/C,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,UAAQ,GAAG,IAAI,CAiDrF"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reportCli = reportCli;
4
+ const SEVERITY_ICON = {
5
+ error: '❌',
6
+ warning: '⚠️ ',
7
+ info: 'ℹ️ ',
8
+ };
9
+ function reportCli(result, diff, asJson = false) {
10
+ if (asJson) {
11
+ process.stdout.write(JSON.stringify({ verdict: result.verdict, counts: result.counts, findings: result.findings }, null, 2) + '\n');
12
+ return;
13
+ }
14
+ const { verdict, findings, counts } = result;
15
+ const verdictLine = verdict === 'pass'
16
+ ? '✅ AgentGate: passed'
17
+ : verdict === 'warn'
18
+ ? '⚠️ AgentGate: warnings'
19
+ : '❌ AgentGate: blocked';
20
+ console.log(`\n${verdictLine}`);
21
+ console.log(` Files: ${diff.files.length} | Lines: +${diff.totalAdded} -${diff.totalDeleted}`);
22
+ if (counts.error > 0)
23
+ console.log(` Errors: ${counts.error}`);
24
+ if (counts.warning > 0)
25
+ console.log(` Warnings: ${counts.warning}`);
26
+ if (counts.info > 0)
27
+ console.log(` Info: ${counts.info}`);
28
+ if (findings.length === 0) {
29
+ console.log('\n No issues found.\n');
30
+ return;
31
+ }
32
+ console.log('');
33
+ const byRule = new Map();
34
+ for (const f of findings) {
35
+ if (!byRule.has(f.ruleId))
36
+ byRule.set(f.ruleId, []);
37
+ byRule.get(f.ruleId).push(f);
38
+ }
39
+ for (const [ruleId, ruleFindings] of byRule) {
40
+ const icon = SEVERITY_ICON[ruleFindings[0].severity] ?? ' ';
41
+ console.log(` ${icon} [${ruleId}]`);
42
+ for (const f of ruleFindings) {
43
+ const loc = f.file ? (f.line ? `${f.file}:${f.line}` : f.file) : '';
44
+ console.log(` ${loc ? `${loc} ` : ''}${f.message}`);
45
+ if (f.suggestion)
46
+ console.log(` → ${f.suggestion}`);
47
+ }
48
+ console.log('');
49
+ }
50
+ }
@@ -0,0 +1,4 @@
1
+ import type { EngineResult } from '../engine';
2
+ import type { DiffModel } from '../diff/parse';
3
+ export declare function writeSummary(result: EngineResult, diff: DiffModel): Promise<void>;
4
+ //# sourceMappingURL=summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/report/summary.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBvF"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.writeSummary = writeSummary;
37
+ const core = __importStar(require("@actions/core"));
38
+ async function writeSummary(result, diff) {
39
+ const { verdict, findings, counts } = result;
40
+ const verdictStr = verdict === 'pass' ? '✅ Passed' : verdict === 'warn' ? '⚠️ Warnings' : '❌ Blocked';
41
+ await core.summary
42
+ .addHeading(`AgentGate: ${verdictStr}`, 2)
43
+ .addTable([
44
+ [
45
+ { data: 'Metric', header: true },
46
+ { data: 'Value', header: true },
47
+ ],
48
+ ['Files changed', String(diff.files.length)],
49
+ ['Lines added', String(diff.totalAdded)],
50
+ ['Lines removed', String(diff.totalDeleted)],
51
+ ['Errors', String(counts.error)],
52
+ ['Warnings', String(counts.warning)],
53
+ ['Total findings', String(findings.length)],
54
+ ])
55
+ .write();
56
+ }
@@ -0,0 +1,3 @@
1
+ import type { Rule } from './types';
2
+ export declare const dangerousPatternsRule: Rule;
3
+ //# sourceMappingURL=dangerousPatterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dangerousPatterns.d.ts","sourceRoot":"","sources":["../../src/rules/dangerousPatterns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAW,MAAM,SAAS,CAAC;AAI7C,eAAO,MAAM,qBAAqB,EAAE,IA4CnC,CAAC"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dangerousPatternsRule = void 0;
4
+ exports.dangerousPatternsRule = {
5
+ id: 'dangerous_patterns',
6
+ description: 'Flag added lines matching a configurable regex denylist',
7
+ run(diff, config) {
8
+ const { enabled, severity, patterns } = config.rules.dangerous_patterns;
9
+ if (!enabled)
10
+ return [];
11
+ let compiled;
12
+ try {
13
+ compiled = patterns.map((p) => ({ regex: new RegExp(p), raw: p }));
14
+ }
15
+ catch (err) {
16
+ throw new Error(`dangerous_patterns: invalid regex pattern — ${err instanceof Error ? err.message : String(err)}`);
17
+ }
18
+ const findings = [];
19
+ for (const file of diff.files) {
20
+ for (const chunk of file.chunks) {
21
+ for (const line of chunk.lines) {
22
+ if (line.type !== 'add')
23
+ continue;
24
+ for (const { regex, raw } of compiled) {
25
+ if (regex.test(line.content)) {
26
+ findings.push({
27
+ ruleId: 'dangerous_patterns',
28
+ severity,
29
+ file: file.path,
30
+ line: line.lineNumber,
31
+ message: `Added line matches dangerous pattern \`${raw}\``,
32
+ suggestion: 'Review this change carefully — it matches a pattern flagged as potentially dangerous.',
33
+ });
34
+ break;
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ return findings;
41
+ },
42
+ };
@@ -0,0 +1,3 @@
1
+ import type { Rule } from './types';
2
+ export declare const dependenciesRule: Rule;
3
+ //# sourceMappingURL=dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/rules/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAW,MAAM,SAAS,CAAC;AAI7C,eAAO,MAAM,gBAAgB,EAAE,IA0B9B,CAAC"}