guardrail-core 1.0.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.
- package/dist/__tests__/autopilot.test.d.ts +7 -0
- package/dist/__tests__/autopilot.test.d.ts.map +1 -0
- package/dist/__tests__/autopilot.test.js +156 -0
- package/dist/__tests__/tier-config.test.d.ts +9 -0
- package/dist/__tests__/tier-config.test.d.ts.map +1 -0
- package/dist/__tests__/tier-config.test.js +230 -0
- package/dist/__tests__/utils/hash-inline.test.d.ts +2 -0
- package/dist/__tests__/utils/hash-inline.test.d.ts.map +1 -0
- package/dist/__tests__/utils/hash-inline.test.js +62 -0
- package/dist/__tests__/utils/hash.test.d.ts +3 -0
- package/dist/__tests__/utils/hash.test.d.ts.map +1 -0
- package/dist/__tests__/utils/hash.test.js +95 -0
- package/dist/__tests__/utils/simple.test.d.ts +1 -0
- package/dist/__tests__/utils/simple.test.d.ts.map +1 -0
- package/dist/__tests__/utils/simple.test.js +10 -0
- package/dist/__tests__/utils/utils-simple.test.d.ts +1 -0
- package/dist/__tests__/utils/utils-simple.test.d.ts.map +1 -0
- package/dist/__tests__/utils/utils-simple.test.js +6 -0
- package/dist/__tests__/utils/utils.test.d.ts +15 -0
- package/dist/__tests__/utils/utils.test.d.ts.map +1 -0
- package/dist/__tests__/utils/utils.test.js +172 -0
- package/dist/autopilot/autopilot-runner.d.ts +33 -0
- package/dist/autopilot/autopilot-runner.d.ts.map +1 -0
- package/dist/autopilot/autopilot-runner.js +479 -0
- package/dist/autopilot/index.d.ts +6 -0
- package/dist/autopilot/index.d.ts.map +1 -0
- package/dist/autopilot/index.js +25 -0
- package/dist/autopilot/types.d.ts +102 -0
- package/dist/autopilot/types.d.ts.map +1 -0
- package/dist/autopilot/types.js +18 -0
- package/dist/cache/index.d.ts +7 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +22 -0
- package/dist/cache/redis-cache.d.ts +145 -0
- package/dist/cache/redis-cache.d.ts.map +1 -0
- package/dist/cache/redis-cache.js +459 -0
- package/dist/ci/github-actions.d.ts +77 -0
- package/dist/ci/github-actions.d.ts.map +1 -0
- package/dist/ci/github-actions.js +277 -0
- package/dist/ci/index.d.ts +12 -0
- package/dist/ci/index.d.ts.map +1 -0
- package/dist/ci/index.js +27 -0
- package/dist/ci/pre-commit.d.ts +65 -0
- package/dist/ci/pre-commit.d.ts.map +1 -0
- package/dist/ci/pre-commit.js +286 -0
- package/dist/entitlements.d.ts +149 -0
- package/dist/entitlements.d.ts.map +1 -0
- package/dist/entitlements.js +464 -0
- package/dist/env.d.ts +113 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +204 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts +7 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts.map +1 -0
- package/dist/fix-packs/__tests__/generate-fix-packs.test.js +250 -0
- package/dist/fix-packs/generate-fix-packs.d.ts +15 -0
- package/dist/fix-packs/generate-fix-packs.d.ts.map +1 -0
- package/dist/fix-packs/generate-fix-packs.js +505 -0
- package/dist/fix-packs/index.d.ts +8 -0
- package/dist/fix-packs/index.d.ts.map +1 -0
- package/dist/fix-packs/index.js +23 -0
- package/dist/fix-packs/types.d.ts +113 -0
- package/dist/fix-packs/types.d.ts.map +1 -0
- package/dist/fix-packs/types.js +71 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/metrics/prometheus.d.ts +99 -0
- package/dist/metrics/prometheus.d.ts.map +1 -0
- package/dist/metrics/prometheus.js +306 -0
- package/dist/quota-ledger.d.ts +119 -0
- package/dist/quota-ledger.d.ts.map +1 -0
- package/dist/quota-ledger.js +462 -0
- package/dist/rbac/__tests__/permissions.test.d.ts +8 -0
- package/dist/rbac/__tests__/permissions.test.d.ts.map +1 -0
- package/dist/rbac/__tests__/permissions.test.js +350 -0
- package/dist/rbac/index.d.ts +9 -0
- package/dist/rbac/index.d.ts.map +1 -0
- package/dist/rbac/index.js +32 -0
- package/dist/rbac/permissions.d.ts +71 -0
- package/dist/rbac/permissions.d.ts.map +1 -0
- package/dist/rbac/permissions.js +247 -0
- package/dist/rbac/types.d.ts +69 -0
- package/dist/rbac/types.d.ts.map +1 -0
- package/dist/rbac/types.js +213 -0
- package/dist/tier-config.d.ts +203 -0
- package/dist/tier-config.d.ts.map +1 -0
- package/dist/tier-config.js +675 -0
- package/dist/types.d.ts +365 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/utils.d.ts +36 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +127 -0
- package/dist/verified-autofix/__tests__/format-validator.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/format-validator.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/format-validator.test.js +285 -0
- package/dist/verified-autofix/__tests__/pipeline.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/pipeline.test.js +389 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/repo-fingerprint.test.js +236 -0
- package/dist/verified-autofix/__tests__/workspace.test.d.ts +11 -0
- package/dist/verified-autofix/__tests__/workspace.test.d.ts.map +1 -0
- package/dist/verified-autofix/__tests__/workspace.test.js +314 -0
- package/dist/verified-autofix/format-validator.d.ts +101 -0
- package/dist/verified-autofix/format-validator.d.ts.map +1 -0
- package/dist/verified-autofix/format-validator.js +446 -0
- package/dist/verified-autofix/index.d.ts +14 -0
- package/dist/verified-autofix/index.d.ts.map +1 -0
- package/dist/verified-autofix/index.js +39 -0
- package/dist/verified-autofix/pipeline.d.ts +68 -0
- package/dist/verified-autofix/pipeline.d.ts.map +1 -0
- package/dist/verified-autofix/pipeline.js +330 -0
- package/dist/verified-autofix/repo-fingerprint.d.ts +56 -0
- package/dist/verified-autofix/repo-fingerprint.d.ts.map +1 -0
- package/dist/verified-autofix/repo-fingerprint.js +396 -0
- package/dist/verified-autofix/workspace.d.ts +83 -0
- package/dist/verified-autofix/workspace.d.ts.map +1 -0
- package/dist/verified-autofix/workspace.js +454 -0
- package/dist/verified-autofix.d.ts +182 -0
- package/dist/verified-autofix.d.ts.map +1 -0
- package/dist/verified-autofix.js +1021 -0
- package/dist/visualization/dependency-graph.d.ts +79 -0
- package/dist/visualization/dependency-graph.d.ts.map +1 -0
- package/dist/visualization/dependency-graph.js +399 -0
- package/dist/visualization/index.d.ts +5 -0
- package/dist/visualization/index.d.ts.map +1 -0
- package/dist/visualization/index.js +20 -0
- package/package.json +29 -0
- package/src/__tests__/autopilot.test.ts +196 -0
- package/src/__tests__/tier-config.test.ts +289 -0
- package/src/__tests__/utils/hash-inline.test.ts +76 -0
- package/src/__tests__/utils/hash.test.ts +119 -0
- package/src/__tests__/utils/simple.test.ts +10 -0
- package/src/__tests__/utils/utils-simple.test.ts +5 -0
- package/src/__tests__/utils/utils.test.ts +203 -0
- package/src/autopilot/autopilot-runner.ts +503 -0
- package/src/autopilot/index.ts +6 -0
- package/src/autopilot/types.ts +119 -0
- package/src/cache/index.ts +7 -0
- package/src/cache/redis-cache.d.ts +155 -0
- package/src/cache/redis-cache.d.ts.map +1 -0
- package/src/cache/redis-cache.ts +517 -0
- package/src/ci/github-actions.ts +335 -0
- package/src/ci/index.ts +12 -0
- package/src/ci/pre-commit.ts +338 -0
- package/src/db/usage-schema.prisma +114 -0
- package/src/entitlements.ts +570 -0
- package/src/env.d.ts +68 -0
- package/src/env.d.ts.map +1 -0
- package/src/env.ts +247 -0
- package/src/fix-packs/__tests__/generate-fix-packs.test.ts +317 -0
- package/src/fix-packs/generate-fix-packs.ts +577 -0
- package/src/fix-packs/index.ts +8 -0
- package/src/fix-packs/types.ts +206 -0
- package/src/index.d.ts +7 -0
- package/src/index.d.ts.map +1 -0
- package/src/index.ts +12 -0
- package/src/metrics/prometheus.d.ts +104 -0
- package/src/metrics/prometheus.d.ts.map +1 -0
- package/src/metrics/prometheus.ts +446 -0
- package/src/quota-ledger.ts +548 -0
- package/src/rbac/__tests__/permissions.test.ts +446 -0
- package/src/rbac/index.ts +46 -0
- package/src/rbac/permissions.ts +301 -0
- package/src/rbac/types.ts +298 -0
- package/src/tier-config.json +157 -0
- package/src/tier-config.ts +815 -0
- package/src/types.d.ts +365 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.ts +441 -0
- package/src/utils.d.ts +36 -0
- package/src/utils.d.ts.map +1 -0
- package/src/utils.ts +140 -0
- package/src/verified-autofix/__tests__/format-validator.test.ts +335 -0
- package/src/verified-autofix/__tests__/pipeline.test.ts +419 -0
- package/src/verified-autofix/__tests__/repo-fingerprint.test.ts +241 -0
- package/src/verified-autofix/__tests__/workspace.test.ts +373 -0
- package/src/verified-autofix/format-validator.ts +517 -0
- package/src/verified-autofix/index.ts +63 -0
- package/src/verified-autofix/pipeline.ts +403 -0
- package/src/verified-autofix/repo-fingerprint.ts +459 -0
- package/src/verified-autofix/workspace.ts +531 -0
- package/src/verified-autofix.ts +1187 -0
- package/src/visualization/dependency-graph.d.ts +85 -0
- package/src/visualization/dependency-graph.d.ts.map +1 -0
- package/src/visualization/dependency-graph.ts +495 -0
- package/src/visualization/index.ts +5 -0
package/dist/env.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
declare const envSchema: z.ZodObject<{
|
|
3
|
+
NODE_ENV: z.ZodDefault<z.ZodEnum<["development", "production", "test", "staging"]>>;
|
|
4
|
+
PORT: z.ZodDefault<z.ZodEffects<z.ZodString, number, string>>;
|
|
5
|
+
HOST: z.ZodDefault<z.ZodString>;
|
|
6
|
+
DATABASE_URL: z.ZodString;
|
|
7
|
+
JWT_SECRET: z.ZodString;
|
|
8
|
+
JWT_REFRESH_SECRET: z.ZodOptional<z.ZodString>;
|
|
9
|
+
JWT_EXPIRES_IN: z.ZodDefault<z.ZodString>;
|
|
10
|
+
JWT_REFRESH_EXPIRES_IN: z.ZodDefault<z.ZodString>;
|
|
11
|
+
GITHUB_CLIENT_ID: z.ZodOptional<z.ZodString>;
|
|
12
|
+
GITHUB_CLIENT_SECRET: z.ZodOptional<z.ZodString>;
|
|
13
|
+
GITHUB_CALLBACK_URL: z.ZodOptional<z.ZodString>;
|
|
14
|
+
GITHUB_WEBHOOK_SECRET: z.ZodOptional<z.ZodString>;
|
|
15
|
+
STRIPE_SECRET_KEY: z.ZodOptional<z.ZodString>;
|
|
16
|
+
STRIPE_PUBLISHABLE_KEY: z.ZodOptional<z.ZodString>;
|
|
17
|
+
STRIPE_WEBHOOK_SECRET: z.ZodOptional<z.ZodString>;
|
|
18
|
+
STRIPE_PRICE_ID_STARTER: z.ZodOptional<z.ZodString>;
|
|
19
|
+
STRIPE_PRICE_ID_PRO: z.ZodOptional<z.ZodString>;
|
|
20
|
+
STRIPE_PRICE_ID_ENTERPRISE: z.ZodOptional<z.ZodString>;
|
|
21
|
+
API_BASE_URL: z.ZodOptional<z.ZodString>;
|
|
22
|
+
NEXT_PUBLIC_API_URL: z.ZodOptional<z.ZodString>;
|
|
23
|
+
NEXT_PUBLIC_APP_URL: z.ZodOptional<z.ZodString>;
|
|
24
|
+
OPENAI_API_KEY: z.ZodOptional<z.ZodString>;
|
|
25
|
+
REDIS_URL: z.ZodOptional<z.ZodString>;
|
|
26
|
+
CORS_ORIGIN: z.ZodDefault<z.ZodString>;
|
|
27
|
+
RATE_LIMIT_WINDOW_MS: z.ZodDefault<z.ZodEffects<z.ZodString, number, string>>;
|
|
28
|
+
RATE_LIMIT_MAX_REQUESTS: z.ZodDefault<z.ZodEffects<z.ZodString, number, string>>;
|
|
29
|
+
SENTRY_DSN: z.ZodOptional<z.ZodString>;
|
|
30
|
+
SENTRY_ORG: z.ZodOptional<z.ZodString>;
|
|
31
|
+
SENTRY_PROJECT: z.ZodOptional<z.ZodString>;
|
|
32
|
+
ENABLE_METRICS: z.ZodDefault<z.ZodEffects<z.ZodString, boolean, string>>;
|
|
33
|
+
ENABLE_AI_FEATURES: z.ZodDefault<z.ZodEffects<z.ZodString, boolean, string>>;
|
|
34
|
+
Guardrail_DEMO_MODE: z.ZodDefault<z.ZodEffects<z.ZodString, boolean, string>>;
|
|
35
|
+
Guardrail_POLICY_STRICT: z.ZodDefault<z.ZodEffects<z.ZodString, boolean, string>>;
|
|
36
|
+
}, "strip", z.ZodTypeAny, {
|
|
37
|
+
NODE_ENV: "development" | "production" | "test" | "staging";
|
|
38
|
+
PORT: number;
|
|
39
|
+
HOST: string;
|
|
40
|
+
DATABASE_URL: string;
|
|
41
|
+
JWT_SECRET: string;
|
|
42
|
+
JWT_EXPIRES_IN: string;
|
|
43
|
+
JWT_REFRESH_EXPIRES_IN: string;
|
|
44
|
+
CORS_ORIGIN: string;
|
|
45
|
+
RATE_LIMIT_WINDOW_MS: number;
|
|
46
|
+
RATE_LIMIT_MAX_REQUESTS: number;
|
|
47
|
+
ENABLE_METRICS: boolean;
|
|
48
|
+
ENABLE_AI_FEATURES: boolean;
|
|
49
|
+
Guardrail_DEMO_MODE: boolean;
|
|
50
|
+
Guardrail_POLICY_STRICT: boolean;
|
|
51
|
+
JWT_REFRESH_SECRET?: string | undefined;
|
|
52
|
+
GITHUB_CLIENT_ID?: string | undefined;
|
|
53
|
+
GITHUB_CLIENT_SECRET?: string | undefined;
|
|
54
|
+
GITHUB_CALLBACK_URL?: string | undefined;
|
|
55
|
+
GITHUB_WEBHOOK_SECRET?: string | undefined;
|
|
56
|
+
STRIPE_SECRET_KEY?: string | undefined;
|
|
57
|
+
STRIPE_PUBLISHABLE_KEY?: string | undefined;
|
|
58
|
+
STRIPE_WEBHOOK_SECRET?: string | undefined;
|
|
59
|
+
STRIPE_PRICE_ID_STARTER?: string | undefined;
|
|
60
|
+
STRIPE_PRICE_ID_PRO?: string | undefined;
|
|
61
|
+
STRIPE_PRICE_ID_ENTERPRISE?: string | undefined;
|
|
62
|
+
API_BASE_URL?: string | undefined;
|
|
63
|
+
NEXT_PUBLIC_API_URL?: string | undefined;
|
|
64
|
+
NEXT_PUBLIC_APP_URL?: string | undefined;
|
|
65
|
+
OPENAI_API_KEY?: string | undefined;
|
|
66
|
+
REDIS_URL?: string | undefined;
|
|
67
|
+
SENTRY_DSN?: string | undefined;
|
|
68
|
+
SENTRY_ORG?: string | undefined;
|
|
69
|
+
SENTRY_PROJECT?: string | undefined;
|
|
70
|
+
}, {
|
|
71
|
+
DATABASE_URL: string;
|
|
72
|
+
JWT_SECRET: string;
|
|
73
|
+
NODE_ENV?: "development" | "production" | "test" | "staging" | undefined;
|
|
74
|
+
PORT?: string | undefined;
|
|
75
|
+
HOST?: string | undefined;
|
|
76
|
+
JWT_REFRESH_SECRET?: string | undefined;
|
|
77
|
+
JWT_EXPIRES_IN?: string | undefined;
|
|
78
|
+
JWT_REFRESH_EXPIRES_IN?: string | undefined;
|
|
79
|
+
GITHUB_CLIENT_ID?: string | undefined;
|
|
80
|
+
GITHUB_CLIENT_SECRET?: string | undefined;
|
|
81
|
+
GITHUB_CALLBACK_URL?: string | undefined;
|
|
82
|
+
GITHUB_WEBHOOK_SECRET?: string | undefined;
|
|
83
|
+
STRIPE_SECRET_KEY?: string | undefined;
|
|
84
|
+
STRIPE_PUBLISHABLE_KEY?: string | undefined;
|
|
85
|
+
STRIPE_WEBHOOK_SECRET?: string | undefined;
|
|
86
|
+
STRIPE_PRICE_ID_STARTER?: string | undefined;
|
|
87
|
+
STRIPE_PRICE_ID_PRO?: string | undefined;
|
|
88
|
+
STRIPE_PRICE_ID_ENTERPRISE?: string | undefined;
|
|
89
|
+
API_BASE_URL?: string | undefined;
|
|
90
|
+
NEXT_PUBLIC_API_URL?: string | undefined;
|
|
91
|
+
NEXT_PUBLIC_APP_URL?: string | undefined;
|
|
92
|
+
OPENAI_API_KEY?: string | undefined;
|
|
93
|
+
REDIS_URL?: string | undefined;
|
|
94
|
+
CORS_ORIGIN?: string | undefined;
|
|
95
|
+
RATE_LIMIT_WINDOW_MS?: string | undefined;
|
|
96
|
+
RATE_LIMIT_MAX_REQUESTS?: string | undefined;
|
|
97
|
+
SENTRY_DSN?: string | undefined;
|
|
98
|
+
SENTRY_ORG?: string | undefined;
|
|
99
|
+
SENTRY_PROJECT?: string | undefined;
|
|
100
|
+
ENABLE_METRICS?: string | undefined;
|
|
101
|
+
ENABLE_AI_FEATURES?: string | undefined;
|
|
102
|
+
Guardrail_DEMO_MODE?: string | undefined;
|
|
103
|
+
Guardrail_POLICY_STRICT?: string | undefined;
|
|
104
|
+
}>;
|
|
105
|
+
export type Env = z.infer<typeof envSchema>;
|
|
106
|
+
export declare function validateEnv(): Env;
|
|
107
|
+
export declare function getEnv(): Env;
|
|
108
|
+
export declare function checkRequiredEnv(): void;
|
|
109
|
+
export declare function isDevelopment(): boolean;
|
|
110
|
+
export declare function isProduction(): boolean;
|
|
111
|
+
export declare function isTest(): boolean;
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA8BxB,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2Db,CAAC;AAGH,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC;AAG5C,wBAAgB,WAAW,IAAI,GAAG,CA0GjC;AAID,wBAAgB,MAAM,IAAI,GAAG,CAK5B;AAGD,wBAAgB,gBAAgB,IAAI,IAAI,CAoBvC;AAGD,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,wBAAgB,MAAM,IAAI,OAAO,CAEhC"}
|
package/dist/env.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateEnv = validateEnv;
|
|
4
|
+
exports.getEnv = getEnv;
|
|
5
|
+
exports.checkRequiredEnv = checkRequiredEnv;
|
|
6
|
+
exports.isDevelopment = isDevelopment;
|
|
7
|
+
exports.isProduction = isProduction;
|
|
8
|
+
exports.isTest = isTest;
|
|
9
|
+
const zod_1 = require("zod");
|
|
10
|
+
// Build DATABASE_URL from individual PG* variables if DATABASE_URL is invalid
|
|
11
|
+
function getDatabaseUrl() {
|
|
12
|
+
const dbUrl = process.env['DATABASE_URL'];
|
|
13
|
+
// Check if DATABASE_URL is valid (starts with postgresql:// or postgres://)
|
|
14
|
+
if (dbUrl && (dbUrl.startsWith('postgresql://') || dbUrl.startsWith('postgres://'))) {
|
|
15
|
+
return dbUrl;
|
|
16
|
+
}
|
|
17
|
+
// Fallback: Build from individual PG* variables (Replit provides these)
|
|
18
|
+
const pgHost = process.env['PGHOST'];
|
|
19
|
+
const pgPort = process.env['PGPORT'] || '5432';
|
|
20
|
+
const pgUser = process.env['PGUSER'] || 'postgres';
|
|
21
|
+
const pgPassword = process.env['PGPASSWORD'] || 'password';
|
|
22
|
+
const pgDatabase = process.env['PGDATABASE'];
|
|
23
|
+
if (pgHost && pgDatabase) {
|
|
24
|
+
const constructedUrl = `postgresql://${pgUser}:${pgPassword}@${pgHost}:${pgPort}/${pgDatabase}`;
|
|
25
|
+
// Update process.env so other parts of the app can use it
|
|
26
|
+
process.env['DATABASE_URL'] = constructedUrl;
|
|
27
|
+
return constructedUrl;
|
|
28
|
+
}
|
|
29
|
+
// Return original (will fail validation but with helpful error)
|
|
30
|
+
return dbUrl || '';
|
|
31
|
+
}
|
|
32
|
+
// Environment variable schema
|
|
33
|
+
const envSchema = zod_1.z.object({
|
|
34
|
+
// Node environment
|
|
35
|
+
NODE_ENV: zod_1.z.enum(['development', 'production', 'test', 'staging']).default('development'),
|
|
36
|
+
// Server configuration
|
|
37
|
+
PORT: zod_1.z.string().transform(Number).default('3000'),
|
|
38
|
+
HOST: zod_1.z.string().default('localhost'),
|
|
39
|
+
// Database - use custom getter that falls back to PG* variables
|
|
40
|
+
DATABASE_URL: zod_1.z.string().url('Invalid database URL format'),
|
|
41
|
+
// Authentication
|
|
42
|
+
JWT_SECRET: zod_1.z.string().min(32, 'JWT secret must be at least 32 characters'),
|
|
43
|
+
JWT_REFRESH_SECRET: zod_1.z.string().optional(),
|
|
44
|
+
JWT_EXPIRES_IN: zod_1.z.string().default('15m'),
|
|
45
|
+
JWT_REFRESH_EXPIRES_IN: zod_1.z.string().default('7d'),
|
|
46
|
+
// GitHub OAuth (required in production)
|
|
47
|
+
GITHUB_CLIENT_ID: zod_1.z.string().optional(),
|
|
48
|
+
GITHUB_CLIENT_SECRET: zod_1.z.string().optional(),
|
|
49
|
+
GITHUB_CALLBACK_URL: zod_1.z.string().url().optional(),
|
|
50
|
+
GITHUB_WEBHOOK_SECRET: zod_1.z.string().optional(),
|
|
51
|
+
// Stripe (required for billing)
|
|
52
|
+
STRIPE_SECRET_KEY: zod_1.z.string().optional(),
|
|
53
|
+
STRIPE_PUBLISHABLE_KEY: zod_1.z.string().optional(),
|
|
54
|
+
STRIPE_WEBHOOK_SECRET: zod_1.z.string().optional(),
|
|
55
|
+
STRIPE_PRICE_ID_STARTER: zod_1.z.string().optional(),
|
|
56
|
+
STRIPE_PRICE_ID_PRO: zod_1.z.string().optional(),
|
|
57
|
+
STRIPE_PRICE_ID_ENTERPRISE: zod_1.z.string().optional(),
|
|
58
|
+
// API URLs
|
|
59
|
+
API_BASE_URL: zod_1.z.string().url().optional(),
|
|
60
|
+
NEXT_PUBLIC_API_URL: zod_1.z.string().url().optional(),
|
|
61
|
+
NEXT_PUBLIC_APP_URL: zod_1.z.string().url().optional(),
|
|
62
|
+
// OpenAI (optional for development)
|
|
63
|
+
OPENAI_API_KEY: zod_1.z.string().optional(),
|
|
64
|
+
// Redis (optional)
|
|
65
|
+
REDIS_URL: zod_1.z.string().optional(),
|
|
66
|
+
// CORS
|
|
67
|
+
CORS_ORIGIN: zod_1.z.string().default('http://localhost:3000'),
|
|
68
|
+
// API Rate Limiting
|
|
69
|
+
RATE_LIMIT_WINDOW_MS: zod_1.z.string().transform(Number).default('900000'),
|
|
70
|
+
RATE_LIMIT_MAX_REQUESTS: zod_1.z.string().transform(Number).default('100'),
|
|
71
|
+
// Monitoring
|
|
72
|
+
SENTRY_DSN: zod_1.z.string().optional(),
|
|
73
|
+
SENTRY_ORG: zod_1.z.string().optional(),
|
|
74
|
+
SENTRY_PROJECT: zod_1.z.string().optional(),
|
|
75
|
+
// Feature flags
|
|
76
|
+
ENABLE_METRICS: zod_1.z.string().transform(val => val === 'true').default('false'),
|
|
77
|
+
ENABLE_AI_FEATURES: zod_1.z.string().transform(val => val === 'true').default('true'),
|
|
78
|
+
Guardrail_DEMO_MODE: zod_1.z.string().transform(val => val === 'true').default('false'),
|
|
79
|
+
Guardrail_POLICY_STRICT: zod_1.z.string().transform(val => val === 'true').default('false'),
|
|
80
|
+
});
|
|
81
|
+
// Validate and parse environment variables
|
|
82
|
+
function validateEnv() {
|
|
83
|
+
try {
|
|
84
|
+
// Fix DATABASE_URL before validation if needed
|
|
85
|
+
getDatabaseUrl();
|
|
86
|
+
const env = envSchema.parse(process.env);
|
|
87
|
+
// Additional production/staging checks
|
|
88
|
+
const isProdLike = env.NODE_ENV === 'production' || env.NODE_ENV === 'staging';
|
|
89
|
+
if (isProdLike) {
|
|
90
|
+
const productionErrors = [];
|
|
91
|
+
const productionWarnings = [];
|
|
92
|
+
// =======================================================================
|
|
93
|
+
// CRITICAL: Required for production
|
|
94
|
+
// =======================================================================
|
|
95
|
+
// GitHub OAuth is optional for now
|
|
96
|
+
// if (!process.env['GITHUB_CLIENT_ID']) {
|
|
97
|
+
// productionErrors.push('GITHUB_CLIENT_ID is required in production');
|
|
98
|
+
// }
|
|
99
|
+
// if (!process.env['GITHUB_CLIENT_SECRET']) {
|
|
100
|
+
// productionErrors.push('GITHUB_CLIENT_SECRET is required in production');
|
|
101
|
+
// }
|
|
102
|
+
// API URL must be configured
|
|
103
|
+
if (!process.env['API_BASE_URL'] && !process.env['NEXT_PUBLIC_API_URL']) {
|
|
104
|
+
productionErrors.push('API_BASE_URL or NEXT_PUBLIC_API_URL is required in production');
|
|
105
|
+
}
|
|
106
|
+
// =======================================================================
|
|
107
|
+
// SECURITY: No localhost in production
|
|
108
|
+
// =======================================================================
|
|
109
|
+
if (env.CORS_ORIGIN.includes('localhost')) {
|
|
110
|
+
productionErrors.push('CORS_ORIGIN should not include localhost in production');
|
|
111
|
+
}
|
|
112
|
+
if (env.DATABASE_URL.includes('localhost')) {
|
|
113
|
+
productionErrors.push('DATABASE_URL should not use localhost in production');
|
|
114
|
+
}
|
|
115
|
+
if (env.HOST === 'localhost') {
|
|
116
|
+
productionErrors.push('HOST should not be localhost in production (use 0.0.0.0)');
|
|
117
|
+
}
|
|
118
|
+
// Check callback URLs don't use localhost
|
|
119
|
+
if (process.env['GITHUB_CALLBACK_URL']?.includes('localhost')) {
|
|
120
|
+
productionErrors.push('GITHUB_CALLBACK_URL should not use localhost in production');
|
|
121
|
+
}
|
|
122
|
+
// =======================================================================
|
|
123
|
+
// WARNINGS: Recommended but not blocking
|
|
124
|
+
// =======================================================================
|
|
125
|
+
// Stripe is needed for billing
|
|
126
|
+
if (!process.env['STRIPE_SECRET_KEY']) {
|
|
127
|
+
productionWarnings.push('STRIPE_SECRET_KEY not set - billing features will be disabled');
|
|
128
|
+
}
|
|
129
|
+
if (!process.env['STRIPE_WEBHOOK_SECRET']) {
|
|
130
|
+
productionWarnings.push('STRIPE_WEBHOOK_SECRET not set - webhook verification disabled');
|
|
131
|
+
}
|
|
132
|
+
// Monitoring - disabled silently
|
|
133
|
+
// if (!process.env['SENTRY_DSN']) {
|
|
134
|
+
// productionWarnings.push('SENTRY_DSN not set - error monitoring disabled');
|
|
135
|
+
// }
|
|
136
|
+
// Redis for caching/sessions - disabled silently
|
|
137
|
+
// if (!process.env['REDIS_URL']) {
|
|
138
|
+
// productionWarnings.push('REDIS_URL not set - using in-memory caching');
|
|
139
|
+
// }
|
|
140
|
+
// Output warnings
|
|
141
|
+
if (productionWarnings.length > 0) {
|
|
142
|
+
console.warn('\n⚠️ Production warnings:');
|
|
143
|
+
productionWarnings.forEach(warning => console.warn(` - ${warning}`));
|
|
144
|
+
console.warn('');
|
|
145
|
+
}
|
|
146
|
+
// Exit on errors
|
|
147
|
+
if (productionErrors.length > 0) {
|
|
148
|
+
console.error('\n❌ Production environment validation failed:');
|
|
149
|
+
productionErrors.forEach(error => console.error(` - ${error}`));
|
|
150
|
+
console.error('\n🚨 Application will exit due to invalid production configuration.\n');
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return env;
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
158
|
+
console.error('❌ Invalid environment variables:');
|
|
159
|
+
error.errors.forEach(err => {
|
|
160
|
+
console.error(` - ${err.path.join('.')}: ${err.message}`);
|
|
161
|
+
});
|
|
162
|
+
// Always exit on validation errors
|
|
163
|
+
console.error('\n🚨 Application will exit due to invalid configuration.\n');
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Get validated environment (cached)
|
|
170
|
+
let cachedEnv = null;
|
|
171
|
+
function getEnv() {
|
|
172
|
+
if (!cachedEnv) {
|
|
173
|
+
cachedEnv = validateEnv();
|
|
174
|
+
}
|
|
175
|
+
return cachedEnv;
|
|
176
|
+
}
|
|
177
|
+
// Check if required environment variables are set
|
|
178
|
+
function checkRequiredEnv() {
|
|
179
|
+
const isProd = process.env['NODE_ENV'] === 'production';
|
|
180
|
+
const required = ['DATABASE_URL', 'JWT_SECRET'];
|
|
181
|
+
// Additional requirements in production
|
|
182
|
+
if (isProd) {
|
|
183
|
+
required.push('GITHUB_CLIENT_ID', 'GITHUB_CLIENT_SECRET');
|
|
184
|
+
}
|
|
185
|
+
const missing = required.filter(key => !process.env[key]);
|
|
186
|
+
if (missing.length > 0) {
|
|
187
|
+
console.error('❌ Missing required environment variables:');
|
|
188
|
+
missing.forEach(key => console.error(` - ${key}`));
|
|
189
|
+
if (isProd) {
|
|
190
|
+
console.error('\n🚨 Production deployment requires all environment variables to be set.\n');
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Development environment check
|
|
196
|
+
function isDevelopment() {
|
|
197
|
+
return getEnv().NODE_ENV === 'development';
|
|
198
|
+
}
|
|
199
|
+
function isProduction() {
|
|
200
|
+
return getEnv().NODE_ENV === 'production';
|
|
201
|
+
}
|
|
202
|
+
function isTest() {
|
|
203
|
+
return getEnv().NODE_ENV === 'test';
|
|
204
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-fix-packs.test.d.ts","sourceRoot":"","sources":["../../../src/fix-packs/__tests__/generate-fix-packs.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Fix Packs Generator Tests
|
|
4
|
+
*
|
|
5
|
+
* Tests for deterministic grouping and fix pack generation.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const generate_fix_packs_1 = require("../generate-fix-packs");
|
|
9
|
+
const types_1 = require("../types");
|
|
10
|
+
describe('generateFixPacks', () => {
|
|
11
|
+
const mockRepoFingerprint = {
|
|
12
|
+
id: 'repo-abc123',
|
|
13
|
+
name: 'test-repo',
|
|
14
|
+
hasTypeScript: true,
|
|
15
|
+
hasTests: true,
|
|
16
|
+
packageManager: 'pnpm',
|
|
17
|
+
hash: 'abc123def456',
|
|
18
|
+
};
|
|
19
|
+
const createFinding = (id, category, severity, file) => ({
|
|
20
|
+
id,
|
|
21
|
+
category,
|
|
22
|
+
severity,
|
|
23
|
+
title: `Test finding ${id}`,
|
|
24
|
+
description: `Description for ${id}`,
|
|
25
|
+
file,
|
|
26
|
+
line: 10,
|
|
27
|
+
});
|
|
28
|
+
describe('deterministic grouping', () => {
|
|
29
|
+
it('should produce identical output for identical input', () => {
|
|
30
|
+
const findings = [
|
|
31
|
+
createFinding('f1', 'secrets', 'critical', 'src/config.ts'),
|
|
32
|
+
createFinding('f2', 'secrets', 'high', 'src/auth.ts'),
|
|
33
|
+
createFinding('f3', 'routes', 'medium', 'src/routes/api.ts'),
|
|
34
|
+
];
|
|
35
|
+
const result1 = (0, generate_fix_packs_1.generateFixPacks)({ findings, repoFingerprint: mockRepoFingerprint });
|
|
36
|
+
const result2 = (0, generate_fix_packs_1.generateFixPacks)({ findings, repoFingerprint: mockRepoFingerprint });
|
|
37
|
+
expect(result1.packs.length).toBe(result2.packs.length);
|
|
38
|
+
expect(result1.packs.map(p => p.id)).toEqual(result2.packs.map(p => p.id));
|
|
39
|
+
});
|
|
40
|
+
it('should produce stable pack IDs across runs', () => {
|
|
41
|
+
const findings = [
|
|
42
|
+
createFinding('f1', 'mocks', 'medium', 'src/test/mock.ts'),
|
|
43
|
+
createFinding('f2', 'mocks', 'medium', 'src/test/fixture.ts'),
|
|
44
|
+
];
|
|
45
|
+
const result1 = (0, generate_fix_packs_1.generateFixPacks)({ findings, repoFingerprint: mockRepoFingerprint });
|
|
46
|
+
const result2 = (0, generate_fix_packs_1.generateFixPacks)({ findings, repoFingerprint: mockRepoFingerprint });
|
|
47
|
+
expect(result1.packs[0].id).toBe(result2.packs[0].id);
|
|
48
|
+
});
|
|
49
|
+
it('should maintain order independence for same findings', () => {
|
|
50
|
+
const findings1 = [
|
|
51
|
+
createFinding('f1', 'secrets', 'critical', 'src/a.ts'),
|
|
52
|
+
createFinding('f2', 'secrets', 'high', 'src/b.ts'),
|
|
53
|
+
];
|
|
54
|
+
const findings2 = [
|
|
55
|
+
createFinding('f2', 'secrets', 'high', 'src/b.ts'),
|
|
56
|
+
createFinding('f1', 'secrets', 'critical', 'src/a.ts'),
|
|
57
|
+
];
|
|
58
|
+
const result1 = (0, generate_fix_packs_1.generateFixPacks)({ findings: findings1, repoFingerprint: mockRepoFingerprint });
|
|
59
|
+
const result2 = (0, generate_fix_packs_1.generateFixPacks)({ findings: findings2, repoFingerprint: mockRepoFingerprint });
|
|
60
|
+
expect(result1.packs.length).toBe(result2.packs.length);
|
|
61
|
+
expect(result1.packs[0].findings.length).toBe(result2.packs[0].findings.length);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('category grouping', () => {
|
|
65
|
+
it('should group findings by category', () => {
|
|
66
|
+
const findings = [
|
|
67
|
+
createFinding('f1', 'secrets', 'critical', 'src/a.ts'),
|
|
68
|
+
createFinding('f2', 'routes', 'medium', 'src/b.ts'),
|
|
69
|
+
createFinding('f3', 'secrets', 'high', 'src/c.ts'),
|
|
70
|
+
];
|
|
71
|
+
const result = (0, generate_fix_packs_1.generateFixPacks)({
|
|
72
|
+
findings,
|
|
73
|
+
repoFingerprint: mockRepoFingerprint,
|
|
74
|
+
groupByCategory: true,
|
|
75
|
+
});
|
|
76
|
+
const secretsPack = result.packs.find(p => p.category === 'secrets');
|
|
77
|
+
const routesPack = result.packs.find(p => p.category === 'routes');
|
|
78
|
+
expect(secretsPack).toBeDefined();
|
|
79
|
+
expect(routesPack).toBeDefined();
|
|
80
|
+
expect(secretsPack.findings.length).toBe(2);
|
|
81
|
+
expect(routesPack.findings.length).toBe(1);
|
|
82
|
+
});
|
|
83
|
+
it('should prioritize categories correctly', () => {
|
|
84
|
+
const findings = [
|
|
85
|
+
createFinding('f1', 'placeholders', 'medium', 'src/a.ts'),
|
|
86
|
+
createFinding('f2', 'secrets', 'critical', 'src/b.ts'),
|
|
87
|
+
createFinding('f3', 'auth', 'high', 'src/c.ts'),
|
|
88
|
+
];
|
|
89
|
+
const result = (0, generate_fix_packs_1.generateFixPacks)({ findings, repoFingerprint: mockRepoFingerprint });
|
|
90
|
+
expect(result.packs[0].category).toBe('secrets');
|
|
91
|
+
expect(result.packs[1].category).toBe('auth');
|
|
92
|
+
expect(result.packs[2].category).toBe('placeholders');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe('severity sorting', () => {
|
|
96
|
+
it('should sort packs by severity (highest first)', () => {
|
|
97
|
+
const findings = [
|
|
98
|
+
createFinding('f1', 'routes', 'low', 'src/a.ts'),
|
|
99
|
+
createFinding('f2', 'mocks', 'critical', 'src/b.ts'),
|
|
100
|
+
createFinding('f3', 'deps', 'medium', 'src/c.ts'),
|
|
101
|
+
];
|
|
102
|
+
const result = (0, generate_fix_packs_1.generateFixPacks)({ findings, repoFingerprint: mockRepoFingerprint });
|
|
103
|
+
expect(result.packs[0].severity).toBe('critical');
|
|
104
|
+
});
|
|
105
|
+
it('should assign pack severity based on highest finding severity', () => {
|
|
106
|
+
const findings = [
|
|
107
|
+
createFinding('f1', 'secrets', 'low', 'src/a.ts'),
|
|
108
|
+
createFinding('f2', 'secrets', 'critical', 'src/b.ts'),
|
|
109
|
+
createFinding('f3', 'secrets', 'medium', 'src/c.ts'),
|
|
110
|
+
];
|
|
111
|
+
const result = (0, generate_fix_packs_1.generateFixPacks)({ findings, repoFingerprint: mockRepoFingerprint });
|
|
112
|
+
const secretsPack = result.packs.find(p => p.category === 'secrets');
|
|
113
|
+
expect(secretsPack.severity).toBe('critical');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('pack size limits', () => {
|
|
117
|
+
it('should respect maxPackSize', () => {
|
|
118
|
+
const findings = Array.from({ length: 25 }, (_, i) => createFinding(`f${i}`, 'secrets', 'medium', `src/file${i}.ts`));
|
|
119
|
+
const result = (0, generate_fix_packs_1.generateFixPacks)({
|
|
120
|
+
findings,
|
|
121
|
+
repoFingerprint: mockRepoFingerprint,
|
|
122
|
+
maxPackSize: 10,
|
|
123
|
+
});
|
|
124
|
+
result.packs.forEach(pack => {
|
|
125
|
+
expect(pack.findings.length).toBeLessThanOrEqual(10);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
it('should respect minPackSize', () => {
|
|
129
|
+
const findings = [
|
|
130
|
+
createFinding('f1', 'secrets', 'medium', 'src/a.ts'),
|
|
131
|
+
];
|
|
132
|
+
const result = (0, generate_fix_packs_1.generateFixPacks)({
|
|
133
|
+
findings,
|
|
134
|
+
repoFingerprint: mockRepoFingerprint,
|
|
135
|
+
minPackSize: 2,
|
|
136
|
+
});
|
|
137
|
+
expect(result.ungrouped.length).toBe(1);
|
|
138
|
+
expect(result.packs.length).toBe(0);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe('empty input', () => {
|
|
142
|
+
it('should handle empty findings array', () => {
|
|
143
|
+
const result = (0, generate_fix_packs_1.generateFixPacks)({
|
|
144
|
+
findings: [],
|
|
145
|
+
repoFingerprint: mockRepoFingerprint,
|
|
146
|
+
});
|
|
147
|
+
expect(result.packs).toEqual([]);
|
|
148
|
+
expect(result.ungrouped).toEqual([]);
|
|
149
|
+
expect(result.stats.totalFindings).toBe(0);
|
|
150
|
+
expect(result.stats.totalPacks).toBe(0);
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
describe('stats calculation', () => {
|
|
154
|
+
it('should calculate correct stats', () => {
|
|
155
|
+
const findings = [
|
|
156
|
+
createFinding('f1', 'secrets', 'critical', 'src/a.ts'),
|
|
157
|
+
createFinding('f2', 'secrets', 'high', 'src/b.ts'),
|
|
158
|
+
createFinding('f3', 'routes', 'medium', 'src/c.ts'),
|
|
159
|
+
createFinding('f4', 'mocks', 'low', 'src/d.ts'),
|
|
160
|
+
];
|
|
161
|
+
const result = (0, generate_fix_packs_1.generateFixPacks)({ findings, repoFingerprint: mockRepoFingerprint });
|
|
162
|
+
expect(result.stats.totalFindings).toBe(4);
|
|
163
|
+
expect(result.stats.byCategory.secrets).toBe(2);
|
|
164
|
+
expect(result.stats.byCategory.routes).toBe(1);
|
|
165
|
+
expect(result.stats.byCategory.mocks).toBe(1);
|
|
166
|
+
expect(result.stats.bySeverity.critical).toBe(1);
|
|
167
|
+
expect(result.stats.bySeverity.high).toBe(1);
|
|
168
|
+
expect(result.stats.bySeverity.medium).toBe(1);
|
|
169
|
+
expect(result.stats.bySeverity.low).toBe(1);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
describe('helper functions', () => {
|
|
174
|
+
describe('compareSeverity', () => {
|
|
175
|
+
it('should order critical < high < medium < low < info', () => {
|
|
176
|
+
expect((0, types_1.compareSeverity)('critical', 'high')).toBeLessThan(0);
|
|
177
|
+
expect((0, types_1.compareSeverity)('high', 'medium')).toBeLessThan(0);
|
|
178
|
+
expect((0, types_1.compareSeverity)('medium', 'low')).toBeLessThan(0);
|
|
179
|
+
expect((0, types_1.compareSeverity)('low', 'info')).toBeLessThan(0);
|
|
180
|
+
});
|
|
181
|
+
it('should return 0 for equal severities', () => {
|
|
182
|
+
expect((0, types_1.compareSeverity)('critical', 'critical')).toBe(0);
|
|
183
|
+
expect((0, types_1.compareSeverity)('medium', 'medium')).toBe(0);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
describe('generatePackId', () => {
|
|
187
|
+
it('should generate stable IDs', () => {
|
|
188
|
+
const id1 = (0, types_1.generatePackId)('secrets', 1, 'abc123');
|
|
189
|
+
const id2 = (0, types_1.generatePackId)('secrets', 1, 'abc123');
|
|
190
|
+
expect(id1).toBe(id2);
|
|
191
|
+
});
|
|
192
|
+
it('should include category prefix', () => {
|
|
193
|
+
const id = (0, types_1.generatePackId)('secrets', 0, 'abc123');
|
|
194
|
+
expect(id).toMatch(/^FP-SEC-/);
|
|
195
|
+
});
|
|
196
|
+
it('should include index', () => {
|
|
197
|
+
const id1 = (0, types_1.generatePackId)('routes', 0, 'abc123');
|
|
198
|
+
const id2 = (0, types_1.generatePackId)('routes', 1, 'abc123');
|
|
199
|
+
expect(id1).toContain('-000-');
|
|
200
|
+
expect(id2).toContain('-001-');
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
describe('sortPacksBySeverity', () => {
|
|
204
|
+
it('should sort packs by severity', () => {
|
|
205
|
+
const packs = [
|
|
206
|
+
{ severity: 'low' },
|
|
207
|
+
{ severity: 'critical' },
|
|
208
|
+
{ severity: 'medium' },
|
|
209
|
+
];
|
|
210
|
+
const sorted = (0, types_1.sortPacksBySeverity)(packs);
|
|
211
|
+
expect(sorted[0].severity).toBe('critical');
|
|
212
|
+
expect(sorted[1].severity).toBe('medium');
|
|
213
|
+
expect(sorted[2].severity).toBe('low');
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
describe('parseFindingsFromScanOutput', () => {
|
|
218
|
+
it('should parse JSON array format', () => {
|
|
219
|
+
const input = JSON.stringify([
|
|
220
|
+
{ id: 'f1', category: 'secrets', severity: 'high', title: 'Test', file: 'a.ts' },
|
|
221
|
+
]);
|
|
222
|
+
const findings = (0, generate_fix_packs_1.parseFindingsFromScanOutput)(input);
|
|
223
|
+
expect(findings.length).toBe(1);
|
|
224
|
+
expect(findings[0].category).toBe('secrets');
|
|
225
|
+
});
|
|
226
|
+
it('should parse findings object format', () => {
|
|
227
|
+
const input = JSON.stringify({
|
|
228
|
+
findings: [
|
|
229
|
+
{ id: 'f1', category: 'mocks', severity: 'medium', message: 'Mock detected', filePath: 'b.ts' },
|
|
230
|
+
],
|
|
231
|
+
});
|
|
232
|
+
const findings = (0, generate_fix_packs_1.parseFindingsFromScanOutput)(input);
|
|
233
|
+
expect(findings.length).toBe(1);
|
|
234
|
+
expect(findings[0].category).toBe('mocks');
|
|
235
|
+
});
|
|
236
|
+
it('should normalize category names', () => {
|
|
237
|
+
const input = JSON.stringify([
|
|
238
|
+
{ id: 'f1', type: 'credential', severity: 'high', title: 'API key', file: 'c.ts' },
|
|
239
|
+
]);
|
|
240
|
+
const findings = (0, generate_fix_packs_1.parseFindingsFromScanOutput)(input);
|
|
241
|
+
expect(findings[0].category).toBe('secrets');
|
|
242
|
+
});
|
|
243
|
+
it('should normalize severity levels', () => {
|
|
244
|
+
const input = JSON.stringify([
|
|
245
|
+
{ id: 'f1', category: 'security', level: 'error', title: 'XSS', file: 'd.ts' },
|
|
246
|
+
]);
|
|
247
|
+
const findings = (0, generate_fix_packs_1.parseFindingsFromScanOutput)(input);
|
|
248
|
+
expect(findings[0].severity).toBe('high');
|
|
249
|
+
});
|
|
250
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fix Packs Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates deterministic Fix Packs from findings and repo fingerprint.
|
|
5
|
+
* Groups findings by category, file proximity, and risk level.
|
|
6
|
+
*/
|
|
7
|
+
import { Finding, RepoFingerprint, GenerateFixPacksOptions, GenerateFixPacksResult } from './types';
|
|
8
|
+
export declare function generateFixPacks(options: GenerateFixPacksOptions): GenerateFixPacksResult;
|
|
9
|
+
export declare function generateRepoFingerprint(projectPath: string, options?: {
|
|
10
|
+
name?: string;
|
|
11
|
+
framework?: string;
|
|
12
|
+
language?: string;
|
|
13
|
+
}): RepoFingerprint;
|
|
14
|
+
export declare function parseFindingsFromScanOutput(scanOutput: string): Finding[];
|
|
15
|
+
//# sourceMappingURL=generate-fix-packs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-fix-packs.d.ts","sourceRoot":"","sources":["../../src/fix-packs/generate-fix-packs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,OAAO,EAIP,eAAe,EACf,uBAAuB,EACvB,sBAAsB,EAOvB,MAAM,SAAS,CAAC;AAqDjB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,sBAAsB,CAmEzF;AA0OD,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,eAAe,CAoDjB;AAMD,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,EAAE,CAmBzE"}
|