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.
Files changed (189) hide show
  1. package/dist/__tests__/autopilot.test.d.ts +7 -0
  2. package/dist/__tests__/autopilot.test.d.ts.map +1 -0
  3. package/dist/__tests__/autopilot.test.js +156 -0
  4. package/dist/__tests__/tier-config.test.d.ts +9 -0
  5. package/dist/__tests__/tier-config.test.d.ts.map +1 -0
  6. package/dist/__tests__/tier-config.test.js +230 -0
  7. package/dist/__tests__/utils/hash-inline.test.d.ts +2 -0
  8. package/dist/__tests__/utils/hash-inline.test.d.ts.map +1 -0
  9. package/dist/__tests__/utils/hash-inline.test.js +62 -0
  10. package/dist/__tests__/utils/hash.test.d.ts +3 -0
  11. package/dist/__tests__/utils/hash.test.d.ts.map +1 -0
  12. package/dist/__tests__/utils/hash.test.js +95 -0
  13. package/dist/__tests__/utils/simple.test.d.ts +1 -0
  14. package/dist/__tests__/utils/simple.test.d.ts.map +1 -0
  15. package/dist/__tests__/utils/simple.test.js +10 -0
  16. package/dist/__tests__/utils/utils-simple.test.d.ts +1 -0
  17. package/dist/__tests__/utils/utils-simple.test.d.ts.map +1 -0
  18. package/dist/__tests__/utils/utils-simple.test.js +6 -0
  19. package/dist/__tests__/utils/utils.test.d.ts +15 -0
  20. package/dist/__tests__/utils/utils.test.d.ts.map +1 -0
  21. package/dist/__tests__/utils/utils.test.js +172 -0
  22. package/dist/autopilot/autopilot-runner.d.ts +33 -0
  23. package/dist/autopilot/autopilot-runner.d.ts.map +1 -0
  24. package/dist/autopilot/autopilot-runner.js +479 -0
  25. package/dist/autopilot/index.d.ts +6 -0
  26. package/dist/autopilot/index.d.ts.map +1 -0
  27. package/dist/autopilot/index.js +25 -0
  28. package/dist/autopilot/types.d.ts +102 -0
  29. package/dist/autopilot/types.d.ts.map +1 -0
  30. package/dist/autopilot/types.js +18 -0
  31. package/dist/cache/index.d.ts +7 -0
  32. package/dist/cache/index.d.ts.map +1 -0
  33. package/dist/cache/index.js +22 -0
  34. package/dist/cache/redis-cache.d.ts +145 -0
  35. package/dist/cache/redis-cache.d.ts.map +1 -0
  36. package/dist/cache/redis-cache.js +459 -0
  37. package/dist/ci/github-actions.d.ts +77 -0
  38. package/dist/ci/github-actions.d.ts.map +1 -0
  39. package/dist/ci/github-actions.js +277 -0
  40. package/dist/ci/index.d.ts +12 -0
  41. package/dist/ci/index.d.ts.map +1 -0
  42. package/dist/ci/index.js +27 -0
  43. package/dist/ci/pre-commit.d.ts +65 -0
  44. package/dist/ci/pre-commit.d.ts.map +1 -0
  45. package/dist/ci/pre-commit.js +286 -0
  46. package/dist/entitlements.d.ts +149 -0
  47. package/dist/entitlements.d.ts.map +1 -0
  48. package/dist/entitlements.js +464 -0
  49. package/dist/env.d.ts +113 -0
  50. package/dist/env.d.ts.map +1 -0
  51. package/dist/env.js +204 -0
  52. package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts +7 -0
  53. package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts.map +1 -0
  54. package/dist/fix-packs/__tests__/generate-fix-packs.test.js +250 -0
  55. package/dist/fix-packs/generate-fix-packs.d.ts +15 -0
  56. package/dist/fix-packs/generate-fix-packs.d.ts.map +1 -0
  57. package/dist/fix-packs/generate-fix-packs.js +505 -0
  58. package/dist/fix-packs/index.d.ts +8 -0
  59. package/dist/fix-packs/index.d.ts.map +1 -0
  60. package/dist/fix-packs/index.js +23 -0
  61. package/dist/fix-packs/types.d.ts +113 -0
  62. package/dist/fix-packs/types.d.ts.map +1 -0
  63. package/dist/fix-packs/types.js +71 -0
  64. package/dist/index.d.ts +13 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +28 -0
  67. package/dist/metrics/prometheus.d.ts +99 -0
  68. package/dist/metrics/prometheus.d.ts.map +1 -0
  69. package/dist/metrics/prometheus.js +306 -0
  70. package/dist/quota-ledger.d.ts +119 -0
  71. package/dist/quota-ledger.d.ts.map +1 -0
  72. package/dist/quota-ledger.js +462 -0
  73. package/dist/rbac/__tests__/permissions.test.d.ts +8 -0
  74. package/dist/rbac/__tests__/permissions.test.d.ts.map +1 -0
  75. package/dist/rbac/__tests__/permissions.test.js +350 -0
  76. package/dist/rbac/index.d.ts +9 -0
  77. package/dist/rbac/index.d.ts.map +1 -0
  78. package/dist/rbac/index.js +32 -0
  79. package/dist/rbac/permissions.d.ts +71 -0
  80. package/dist/rbac/permissions.d.ts.map +1 -0
  81. package/dist/rbac/permissions.js +247 -0
  82. package/dist/rbac/types.d.ts +69 -0
  83. package/dist/rbac/types.d.ts.map +1 -0
  84. package/dist/rbac/types.js +213 -0
  85. package/dist/tier-config.d.ts +203 -0
  86. package/dist/tier-config.d.ts.map +1 -0
  87. package/dist/tier-config.js +675 -0
  88. package/dist/types.d.ts +365 -0
  89. package/dist/types.d.ts.map +1 -0
  90. package/dist/types.js +5 -0
  91. package/dist/utils.d.ts +36 -0
  92. package/dist/utils.d.ts.map +1 -0
  93. package/dist/utils.js +127 -0
  94. package/dist/verified-autofix/__tests__/format-validator.test.d.ts +11 -0
  95. package/dist/verified-autofix/__tests__/format-validator.test.d.ts.map +1 -0
  96. package/dist/verified-autofix/__tests__/format-validator.test.js +285 -0
  97. package/dist/verified-autofix/__tests__/pipeline.test.d.ts +11 -0
  98. package/dist/verified-autofix/__tests__/pipeline.test.d.ts.map +1 -0
  99. package/dist/verified-autofix/__tests__/pipeline.test.js +389 -0
  100. package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts +11 -0
  101. package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts.map +1 -0
  102. package/dist/verified-autofix/__tests__/repo-fingerprint.test.js +236 -0
  103. package/dist/verified-autofix/__tests__/workspace.test.d.ts +11 -0
  104. package/dist/verified-autofix/__tests__/workspace.test.d.ts.map +1 -0
  105. package/dist/verified-autofix/__tests__/workspace.test.js +314 -0
  106. package/dist/verified-autofix/format-validator.d.ts +101 -0
  107. package/dist/verified-autofix/format-validator.d.ts.map +1 -0
  108. package/dist/verified-autofix/format-validator.js +446 -0
  109. package/dist/verified-autofix/index.d.ts +14 -0
  110. package/dist/verified-autofix/index.d.ts.map +1 -0
  111. package/dist/verified-autofix/index.js +39 -0
  112. package/dist/verified-autofix/pipeline.d.ts +68 -0
  113. package/dist/verified-autofix/pipeline.d.ts.map +1 -0
  114. package/dist/verified-autofix/pipeline.js +330 -0
  115. package/dist/verified-autofix/repo-fingerprint.d.ts +56 -0
  116. package/dist/verified-autofix/repo-fingerprint.d.ts.map +1 -0
  117. package/dist/verified-autofix/repo-fingerprint.js +396 -0
  118. package/dist/verified-autofix/workspace.d.ts +83 -0
  119. package/dist/verified-autofix/workspace.d.ts.map +1 -0
  120. package/dist/verified-autofix/workspace.js +454 -0
  121. package/dist/verified-autofix.d.ts +182 -0
  122. package/dist/verified-autofix.d.ts.map +1 -0
  123. package/dist/verified-autofix.js +1021 -0
  124. package/dist/visualization/dependency-graph.d.ts +79 -0
  125. package/dist/visualization/dependency-graph.d.ts.map +1 -0
  126. package/dist/visualization/dependency-graph.js +399 -0
  127. package/dist/visualization/index.d.ts +5 -0
  128. package/dist/visualization/index.d.ts.map +1 -0
  129. package/dist/visualization/index.js +20 -0
  130. package/package.json +29 -0
  131. package/src/__tests__/autopilot.test.ts +196 -0
  132. package/src/__tests__/tier-config.test.ts +289 -0
  133. package/src/__tests__/utils/hash-inline.test.ts +76 -0
  134. package/src/__tests__/utils/hash.test.ts +119 -0
  135. package/src/__tests__/utils/simple.test.ts +10 -0
  136. package/src/__tests__/utils/utils-simple.test.ts +5 -0
  137. package/src/__tests__/utils/utils.test.ts +203 -0
  138. package/src/autopilot/autopilot-runner.ts +503 -0
  139. package/src/autopilot/index.ts +6 -0
  140. package/src/autopilot/types.ts +119 -0
  141. package/src/cache/index.ts +7 -0
  142. package/src/cache/redis-cache.d.ts +155 -0
  143. package/src/cache/redis-cache.d.ts.map +1 -0
  144. package/src/cache/redis-cache.ts +517 -0
  145. package/src/ci/github-actions.ts +335 -0
  146. package/src/ci/index.ts +12 -0
  147. package/src/ci/pre-commit.ts +338 -0
  148. package/src/db/usage-schema.prisma +114 -0
  149. package/src/entitlements.ts +570 -0
  150. package/src/env.d.ts +68 -0
  151. package/src/env.d.ts.map +1 -0
  152. package/src/env.ts +247 -0
  153. package/src/fix-packs/__tests__/generate-fix-packs.test.ts +317 -0
  154. package/src/fix-packs/generate-fix-packs.ts +577 -0
  155. package/src/fix-packs/index.ts +8 -0
  156. package/src/fix-packs/types.ts +206 -0
  157. package/src/index.d.ts +7 -0
  158. package/src/index.d.ts.map +1 -0
  159. package/src/index.ts +12 -0
  160. package/src/metrics/prometheus.d.ts +104 -0
  161. package/src/metrics/prometheus.d.ts.map +1 -0
  162. package/src/metrics/prometheus.ts +446 -0
  163. package/src/quota-ledger.ts +548 -0
  164. package/src/rbac/__tests__/permissions.test.ts +446 -0
  165. package/src/rbac/index.ts +46 -0
  166. package/src/rbac/permissions.ts +301 -0
  167. package/src/rbac/types.ts +298 -0
  168. package/src/tier-config.json +157 -0
  169. package/src/tier-config.ts +815 -0
  170. package/src/types.d.ts +365 -0
  171. package/src/types.d.ts.map +1 -0
  172. package/src/types.ts +441 -0
  173. package/src/utils.d.ts +36 -0
  174. package/src/utils.d.ts.map +1 -0
  175. package/src/utils.ts +140 -0
  176. package/src/verified-autofix/__tests__/format-validator.test.ts +335 -0
  177. package/src/verified-autofix/__tests__/pipeline.test.ts +419 -0
  178. package/src/verified-autofix/__tests__/repo-fingerprint.test.ts +241 -0
  179. package/src/verified-autofix/__tests__/workspace.test.ts +373 -0
  180. package/src/verified-autofix/format-validator.ts +517 -0
  181. package/src/verified-autofix/index.ts +63 -0
  182. package/src/verified-autofix/pipeline.ts +403 -0
  183. package/src/verified-autofix/repo-fingerprint.ts +459 -0
  184. package/src/verified-autofix/workspace.ts +531 -0
  185. package/src/verified-autofix.ts +1187 -0
  186. package/src/visualization/dependency-graph.d.ts +85 -0
  187. package/src/visualization/dependency-graph.d.ts.map +1 -0
  188. package/src/visualization/dependency-graph.ts +495 -0
  189. 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,7 @@
1
+ /**
2
+ * Fix Packs Generator Tests
3
+ *
4
+ * Tests for deterministic grouping and fix pack generation.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=generate-fix-packs.test.d.ts.map
@@ -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"}