db-scalability-guardian 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 (62) hide show
  1. package/README.md +165 -0
  2. package/dist/analyzers/postgres/migrations.d.ts +4 -0
  3. package/dist/analyzers/postgres/migrations.d.ts.map +1 -0
  4. package/dist/analyzers/postgres/migrations.js +96 -0
  5. package/dist/analyzers/postgres/migrations.js.map +1 -0
  6. package/dist/cli/index.d.ts +3 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +125 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/collectors/git.d.ts +6 -0
  11. package/dist/collectors/git.d.ts.map +1 -0
  12. package/dist/collectors/git.js +51 -0
  13. package/dist/collectors/git.js.map +1 -0
  14. package/dist/collectors/prisma.d.ts +8 -0
  15. package/dist/collectors/prisma.d.ts.map +1 -0
  16. package/dist/collectors/prisma.js +29 -0
  17. package/dist/collectors/prisma.js.map +1 -0
  18. package/dist/config/defaults.d.ts +24 -0
  19. package/dist/config/defaults.d.ts.map +1 -0
  20. package/dist/config/defaults.js +56 -0
  21. package/dist/config/defaults.js.map +1 -0
  22. package/dist/config/loader.d.ts +3 -0
  23. package/dist/config/loader.d.ts.map +1 -0
  24. package/dist/config/loader.js +69 -0
  25. package/dist/config/loader.js.map +1 -0
  26. package/dist/config/schema.d.ts +3 -0
  27. package/dist/config/schema.d.ts.map +1 -0
  28. package/dist/config/schema.js +51 -0
  29. package/dist/config/schema.js.map +1 -0
  30. package/dist/gate/gate.d.ts +6 -0
  31. package/dist/gate/gate.d.ts.map +1 -0
  32. package/dist/gate/gate.js +11 -0
  33. package/dist/gate/gate.js.map +1 -0
  34. package/dist/index.d.ts +12 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +40 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/llm/mistral.d.ts +6 -0
  39. package/dist/llm/mistral.d.ts.map +1 -0
  40. package/dist/llm/mistral.js +34 -0
  41. package/dist/llm/mistral.js.map +1 -0
  42. package/dist/llm/prompts.d.ts +6 -0
  43. package/dist/llm/prompts.d.ts.map +1 -0
  44. package/dist/llm/prompts.js +50 -0
  45. package/dist/llm/prompts.js.map +1 -0
  46. package/dist/reporters/json.d.ts +3 -0
  47. package/dist/reporters/json.d.ts.map +1 -0
  48. package/dist/reporters/json.js +7 -0
  49. package/dist/reporters/json.js.map +1 -0
  50. package/dist/reporters/markdown.d.ts +3 -0
  51. package/dist/reporters/markdown.d.ts.map +1 -0
  52. package/dist/reporters/markdown.js +38 -0
  53. package/dist/reporters/markdown.js.map +1 -0
  54. package/dist/types/config.d.ts +21 -0
  55. package/dist/types/config.d.ts.map +1 -0
  56. package/dist/types/config.js +3 -0
  57. package/dist/types/config.js.map +1 -0
  58. package/dist/types/report.d.ts +37 -0
  59. package/dist/types/report.d.ts.map +1 -0
  60. package/dist/types/report.js +3 -0
  61. package/dist/types/report.js.map +1 -0
  62. package/package.json +41 -0
package/README.md ADDED
@@ -0,0 +1,165 @@
1
+ # DB Scalability Guardian
2
+
3
+ A CLI tool for analyzing database migrations and schema changes for scalability and evolvability risks. Designed for PostgreSQL and Prisma, with optional LLM-powered architectural interpretation.
4
+
5
+ ## Overview
6
+
7
+ DB Scalability Guardian performs deterministic analysis of database migrations to identify potential scalability issues, deployment blockers, and future feature blockers. It can optionally use LLM interpretation to provide architectural insights.
8
+
9
+ ## Features
10
+
11
+ - **Deterministic Migration Analysis**: Detects risky patterns in SQL migrations (NOT NULL additions, type changes, drops, index creation, foreign keys, enums)
12
+ - **Git Integration**: Automatically compares branches to identify changed migrations
13
+ - **Prisma Support**: Works with Prisma migrations and schema files
14
+ - **Configurable Gate Rules**: Fail CI/CD pipelines on HIGH or CRITICAL findings
15
+ - **Optional LLM Interpretation**: Uses Mistral AI for architectural analysis (optional, never required)
16
+ - **Multiple Report Formats**: Generates JSON and Markdown reports
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install --save-dev db-scalability-guardian
22
+ ```
23
+
24
+ Or use directly with npx:
25
+
26
+ ```bash
27
+ npx db-scalability-guardian analyze
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Basic Usage
33
+
34
+ Run the analysis from your repository root:
35
+
36
+ ```bash
37
+ npx db-scalability-guardian analyze
38
+ ```
39
+
40
+ This will:
41
+ 1. Compare `main` → `develop` branches (configurable)
42
+ 2. Analyze changed Prisma migrations
43
+ 3. Generate reports in `guardian-reports/`
44
+ 4. Exit with code 1 if blocking findings are detected
45
+
46
+ ### Configuration
47
+
48
+ Create a `guardian.config.js` or `guardian.config.json` in your repository root:
49
+
50
+ ```javascript
51
+ // guardian.config.js
52
+ module.exports = {
53
+ baseBranch: "main",
54
+ headBranch: "develop",
55
+ database: {
56
+ engine: "postgres",
57
+ orm: "prisma",
58
+ migrationsPath: "prisma/migrations"
59
+ },
60
+ futureConstraints: [
61
+ "Multi-country deployment (currency, taxes, locale)",
62
+ "Machine-specific pricing and configuration"
63
+ ],
64
+ llm: {
65
+ provider: "mistral",
66
+ model: "mistral-medium-2508",
67
+ optional: true,
68
+ apiKey: process.env.MISTRAL_API_KEY
69
+ },
70
+ gate: {
71
+ failOn: ["HIGH", "CRITICAL"]
72
+ }
73
+ };
74
+ ```
75
+
76
+ Or as JSON:
77
+
78
+ ```json
79
+ {
80
+ "baseBranch": "main",
81
+ "headBranch": "develop",
82
+ "database": {
83
+ "engine": "postgres",
84
+ "orm": "prisma",
85
+ "migrationsPath": "prisma/migrations"
86
+ },
87
+ "gate": {
88
+ "failOn": ["HIGH", "CRITICAL"]
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### GitHub Actions Integration
94
+
95
+ ```yaml
96
+ name: DB Scalability Check
97
+
98
+ on:
99
+ pull_request:
100
+ branches: [main]
101
+
102
+ jobs:
103
+ guardian:
104
+ runs-on: ubuntu-latest
105
+ steps:
106
+ - uses: actions/checkout@v3
107
+ with:
108
+ fetch-depth: 0 # Required for git diff
109
+
110
+ - name: Setup Node.js
111
+ uses: actions/setup-node@v3
112
+ with:
113
+ node-version: '18'
114
+
115
+ - name: Run DB Scalability Guardian
116
+ run: npx db-scalability-guardian analyze
117
+ env:
118
+ MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }} # Optional
119
+
120
+ - name: Upload reports
121
+ uses: actions/upload-artifact@v3
122
+ if: always()
123
+ with:
124
+ name: guardian-reports
125
+ path: guardian-reports/
126
+ ```
127
+
128
+ ### LLM Integration (Optional)
129
+
130
+ The tool supports optional LLM interpretation using Mistral AI. To enable:
131
+
132
+ 1. Set `MISTRAL_API_KEY` environment variable, or
133
+ 2. Configure `llm.apiKey` in your config file
134
+
135
+ The LLM analysis is **never required** - the tool works fully without it. When enabled, it generates an additional `guardian-llm-analysis.md` report with architectural insights.
136
+
137
+ ## Report Output
138
+
139
+ The tool generates reports in the `guardian-reports/` directory:
140
+
141
+ - **guardian-report.json**: Machine-readable report with all findings
142
+ - **guardian-report.md**: Human-readable Markdown report
143
+ - **guardian-llm-analysis.md**: LLM-generated architectural analysis (if enabled)
144
+
145
+ ## Exit Codes
146
+
147
+ - `0`: Success, no blocking findings
148
+ - `1`: Blocking findings detected (based on `gate.failOn` configuration)
149
+
150
+ ## Architecture
151
+
152
+ The tool is structured as a modular library:
153
+
154
+ - **Collectors**: Gather context (git diff, Prisma schema)
155
+ - **Analyzers**: Perform deterministic analysis (migration heuristics)
156
+ - **Reporters**: Generate output (JSON, Markdown)
157
+ - **Gate**: Apply severity-based rules
158
+ - **LLM**: Optional architectural interpretation
159
+
160
+ All analysis is deterministic and does not require LLM. The LLM component is purely additive for enhanced insights.
161
+
162
+ ## License
163
+
164
+ ISC
165
+
@@ -0,0 +1,4 @@
1
+ import { Finding } from "../../types/report.js";
2
+ export declare function analyzeMigration(sql: string, file: string): Finding[];
3
+ export declare function analyzeMigrations(migrationFiles: string[]): Finding[];
4
+ //# sourceMappingURL=migrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../../src/analyzers/postgres/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGhD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAmFrE;AAED,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,CAcrE"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.analyzeMigration = analyzeMigration;
4
+ exports.analyzeMigrations = analyzeMigrations;
5
+ const prisma_js_1 = require("../../collectors/prisma.js");
6
+ function analyzeMigration(sql, file) {
7
+ const s = sql.toLowerCase();
8
+ const findings = [];
9
+ // 1) Add NOT NULL column (high risk on existing table)
10
+ if (s.match(/alter\s+table[\s\S]*add\s+column[\s\S]*not\s+null/)) {
11
+ findings.push({
12
+ id: "MIG_NOT_NULL_ADD",
13
+ severity: "HIGH",
14
+ title: "ADD COLUMN ... NOT NULL (risk of failure / blocking on existing data)",
15
+ evidence: "Detected `ALTER TABLE ... ADD COLUMN ... NOT NULL`.",
16
+ impact: "On a table with existing rows, this can fail or require full table rewrite / locks, blocking deployments.",
17
+ mitigation: "Use a safe 3-step approach: (1) add nullable column, (2) backfill in batches, (3) add NOT NULL constraint.",
18
+ file,
19
+ });
20
+ }
21
+ // 2) Alter column type (often locking + risky)
22
+ if (s.match(/alter\s+table[\s\S]*alter\s+column[\s\S]*type/)) {
23
+ findings.push({
24
+ id: "MIG_ALTER_TYPE",
25
+ severity: "HIGH",
26
+ title: "ALTER COLUMN TYPE (often locks / rewrite)",
27
+ evidence: "Detected `ALTER TABLE ... ALTER COLUMN ... TYPE ...`.",
28
+ impact: "May rewrite the table and take long locks depending on the type change and table size.",
29
+ mitigation: "Prefer expand-and-contract migrations: add new column, dual-write, backfill, swap, then drop old column.",
30
+ file,
31
+ });
32
+ }
33
+ // 3) Drop column/table (data loss)
34
+ if (s.match(/drop\s+column/) || s.match(/drop\s+table/)) {
35
+ findings.push({
36
+ id: "MIG_DROP_DATA",
37
+ severity: "CRITICAL",
38
+ title: "DROP COLUMN/TABLE (data loss risk)",
39
+ evidence: "Detected DROP operation.",
40
+ impact: "Irreversible data loss unless you have backups and explicit migration strategy.",
41
+ mitigation: "Use deprecation: stop writes, archive data, keep column/table for at least one release cycle, then remove.",
42
+ file,
43
+ });
44
+ }
45
+ // 4) Create index without concurrently (can lock writes)
46
+ if (s.match(/create\s+index/) && !s.match(/concurrently/)) {
47
+ findings.push({
48
+ id: "MIG_INDEX_NOT_CONCURRENT",
49
+ severity: "MEDIUM",
50
+ title: "CREATE INDEX without CONCURRENTLY (potential write lock)",
51
+ evidence: "Detected CREATE INDEX without CONCURRENTLY.",
52
+ impact: "On large tables, index creation may block writes and extend deployment time.",
53
+ mitigation: "For production large tables, prefer `CREATE INDEX CONCURRENTLY` and run outside transaction if needed.",
54
+ file,
55
+ });
56
+ }
57
+ // 5) Add foreign key constraints (can lock / scan)
58
+ if (s.match(/add\s+constraint[\s\S]*foreign\s+key/)) {
59
+ findings.push({
60
+ id: "MIG_ADD_FK",
61
+ severity: "MEDIUM",
62
+ title: "ADD FOREIGN KEY constraint (locks / full scan)",
63
+ evidence: "Detected ADD CONSTRAINT ... FOREIGN KEY.",
64
+ impact: "Postgres may scan the table and lock rows; risky on large tables.",
65
+ mitigation: "Ensure supporting indexes exist; consider adding constraint as NOT VALID then VALIDATE in a later step.",
66
+ file,
67
+ });
68
+ }
69
+ // 6) Create enum / alter enum (can be tricky)
70
+ if (s.match(/create\s+type[\s\S]*as\s+enum/)) {
71
+ findings.push({
72
+ id: "MIG_ENUM_CREATE",
73
+ severity: "LOW",
74
+ title: "ENUM type created (evolvability considerations)",
75
+ evidence: "Detected CREATE TYPE ... AS ENUM.",
76
+ impact: "Enums are harder to evolve than lookup tables; future changes require careful migrations.",
77
+ mitigation: "Prefer lookup table for frequently changing values; if enum, plan a safe ALTER TYPE strategy.",
78
+ file,
79
+ });
80
+ }
81
+ return findings;
82
+ }
83
+ function analyzeMigrations(migrationFiles) {
84
+ const findings = [];
85
+ for (const mig of migrationFiles) {
86
+ // mig might be folder or file; normalize:
87
+ const isFolder = !mig.endsWith(".sql");
88
+ const sqlFile = isFolder ? `${mig}/migration.sql` : mig;
89
+ const sql = (0, prisma_js_1.loadMigrationSQL)(sqlFile);
90
+ if (!sql)
91
+ continue;
92
+ findings.push(...analyzeMigration(sql, sqlFile));
93
+ }
94
+ return findings;
95
+ }
96
+ //# sourceMappingURL=migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../src/analyzers/postgres/migrations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,125 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const loader_js_1 = require("../config/loader.js");
10
+ const git_js_1 = require("../collectors/git.js");
11
+ const prisma_js_1 = require("../collectors/prisma.js");
12
+ const migrations_js_1 = require("../analyzers/postgres/migrations.js");
13
+ const markdown_js_1 = require("../reporters/markdown.js");
14
+ const json_js_1 = require("../reporters/json.js");
15
+ const gate_js_1 = require("../gate/gate.js");
16
+ const prompts_js_1 = require("../llm/prompts.js");
17
+ const mistral_js_1 = require("../llm/mistral.js");
18
+ async function main() {
19
+ const cwd = process.cwd();
20
+ const config = (0, loader_js_1.loadConfig)(cwd);
21
+ console.log("🔍 DB Scalability Guardian");
22
+ console.log(`Comparing ${config.baseBranch} → ${config.headBranch}\n`);
23
+ // 1. Collect git diff context
24
+ console.log("📊 Collecting git diff...");
25
+ const diffResult = (0, git_js_1.diffFiles)(config.baseBranch, config.headBranch);
26
+ console.log(` Found ${diffResult.files.length} changed files`);
27
+ // 2. Collect Prisma schema + migrations
28
+ console.log("🗄️ Collecting Prisma context...");
29
+ const migrationsPath = config.database.migrationsPath;
30
+ if (!migrationsPath) {
31
+ throw new Error("migrationsPath is required but not configured");
32
+ }
33
+ const prismaContext = (0, prisma_js_1.collectPrismaContext)(migrationsPath, diffResult.files);
34
+ console.log(` Found ${prismaContext.migrationFiles.length} modified migrations`);
35
+ // 3. Build context
36
+ const meta = {
37
+ baseBranch: config.baseBranch,
38
+ headBranch: config.headBranch,
39
+ comparedRange: diffResult.range,
40
+ changedFilesCount: diffResult.files.length,
41
+ generatedAt: new Date().toISOString(),
42
+ };
43
+ const engine = config.database.engine;
44
+ const orm = config.database.orm;
45
+ if (!engine || !orm) {
46
+ throw new Error("database.engine and database.orm are required but not configured");
47
+ }
48
+ const context = {
49
+ meta,
50
+ database: {
51
+ engine,
52
+ orm,
53
+ migrationsPath,
54
+ modifiedMigrations: prismaContext.migrationFiles,
55
+ },
56
+ prisma: {
57
+ schemaPath: prismaContext.schemaPath,
58
+ schema: prismaContext.schema,
59
+ },
60
+ backendHints: diffResult.files.filter((f) => f.startsWith("src/") &&
61
+ (f.includes(".service.") ||
62
+ f.includes(".repository.") ||
63
+ f.includes(".module.") ||
64
+ f.includes(".controller."))),
65
+ changedFiles: diffResult.files,
66
+ };
67
+ // 4. Run Postgres migration analysis
68
+ console.log("🔬 Analyzing migrations...");
69
+ const findings = (0, migrations_js_1.analyzeMigrations)(prismaContext.migrationFiles);
70
+ console.log(` Found ${findings.length} findings`);
71
+ // 5. Generate reports
72
+ console.log("📝 Generating reports...");
73
+ const report = {
74
+ meta,
75
+ findings,
76
+ };
77
+ const reportDir = path_1.default.join(cwd, "guardian-reports");
78
+ fs_1.default.mkdirSync(reportDir, { recursive: true });
79
+ const jsonReport = (0, json_js_1.renderJSON)(report);
80
+ const markdownReport = (0, markdown_js_1.renderMarkdown)(findings, meta);
81
+ fs_1.default.writeFileSync(path_1.default.join(reportDir, "guardian-report.json"), jsonReport);
82
+ fs_1.default.writeFileSync(path_1.default.join(reportDir, "guardian-report.md"), markdownReport);
83
+ console.log(` ✓ guardian-report.json`);
84
+ console.log(` ✓ guardian-report.md`);
85
+ // 6. Optional LLM interpretation
86
+ if (config.llm.optional && config.llm.apiKey) {
87
+ console.log("🤖 Running LLM interpretation...");
88
+ try {
89
+ const prompts = (0, prompts_js_1.buildLLMPrompt)(context, markdownReport);
90
+ const llmOutput = await (0, mistral_js_1.callMistral)({
91
+ apiKey: config.llm.apiKey,
92
+ model: config.llm.model,
93
+ }, prompts.system, prompts.user);
94
+ fs_1.default.writeFileSync(path_1.default.join(reportDir, "guardian-llm-analysis.md"), llmOutput);
95
+ console.log(` ✓ guardian-llm-analysis.md`);
96
+ }
97
+ catch (error) {
98
+ console.warn(" ⚠️ LLM analysis failed:", error instanceof Error ? error.message : String(error));
99
+ }
100
+ }
101
+ else if (config.llm.optional) {
102
+ console.log(" ⏭️ Skipping LLM (no API key provided)");
103
+ }
104
+ // 7. Apply gate rules
105
+ console.log("\n🚦 Checking gate rules...");
106
+ const failOn = config.gate.failOn;
107
+ if (!failOn) {
108
+ throw new Error("gate.failOn is required but not configured");
109
+ }
110
+ const gateResult = (0, gate_js_1.checkGate)(findings, failOn);
111
+ if (!gateResult.passed) {
112
+ console.error(`\n❌ Blocking findings detected (${gateResult.blocking.length}):`);
113
+ for (const finding of gateResult.blocking) {
114
+ console.error(` [${finding.severity}] ${finding.title} (${finding.file || "unknown"})`);
115
+ }
116
+ process.exit(1);
117
+ }
118
+ console.log("✅ No blocking findings");
119
+ process.exit(0);
120
+ }
121
+ main().catch((error) => {
122
+ console.error("Fatal error:", error);
123
+ process.exit(1);
124
+ });
125
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface DiffResult {
2
+ files: string[];
3
+ range: string;
4
+ }
5
+ export declare function diffFiles(base: string, head: string): DiffResult;
6
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/collectors/git.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CA+BhE"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.diffFiles = diffFiles;
4
+ const child_process_1 = require("child_process");
5
+ function sh(cmd) {
6
+ try {
7
+ return (0, child_process_1.execSync)(cmd, { stdio: ["ignore", "pipe", "pipe"] }).toString().trim();
8
+ }
9
+ catch (error) {
10
+ const stderr = error && typeof error === "object" && "stderr" in error
11
+ ? error.stderr.toString()
12
+ : "";
13
+ throw new Error(`Command failed: ${cmd}\n${stderr}`);
14
+ }
15
+ }
16
+ function diffFiles(base, head) {
17
+ // Try to fetch remote refs first
18
+ try {
19
+ sh("git fetch origin --prune");
20
+ }
21
+ catch {
22
+ // Ignore fetch errors
23
+ }
24
+ try {
25
+ // Compare origin/base..origin/head
26
+ const range = `origin/${base}...origin/${head}`;
27
+ const out = sh(`git diff --name-only ${range}`);
28
+ return { files: out.split("\n").filter(Boolean), range };
29
+ }
30
+ catch {
31
+ // Fallback to local branch comparison
32
+ try {
33
+ const range = `${base}...${head}`;
34
+ const out = sh(`git diff --name-only ${range}`);
35
+ return { files: out.split("\n").filter(Boolean), range };
36
+ }
37
+ catch {
38
+ // Last resort: compare current HEAD with base
39
+ try {
40
+ const range = `${base}...HEAD`;
41
+ const out = sh(`git diff --name-only ${range}`);
42
+ return { files: out.split("\n").filter(Boolean), range };
43
+ }
44
+ catch {
45
+ console.warn("Could not determine changed files. Returning empty array.");
46
+ return { files: [], range: "unknown" };
47
+ }
48
+ }
49
+ }
50
+ }
51
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/collectors/git.ts"],"names":[],"mappings":";;AAkBA,8BA+BC;AAjDD,iDAAyC;AAEzC,SAAS,EAAE,CAAC,GAAW;IACrB,IAAI,CAAC;QACH,OAAO,IAAA,wBAAQ,EAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC;IAChF,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK;YACpE,CAAC,CAAE,KAAK,CAAC,MAAiC,CAAC,QAAQ,EAAE;YACrD,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,KAAK,MAAM,EAAE,CAAC,CAAC;IACvD,CAAC;AACH,CAAC;AAOD,SAAgB,SAAS,CAAC,IAAY,EAAE,IAAY;IAClD,iCAAiC;IACjC,IAAI,CAAC;QACH,EAAE,CAAC,0BAA0B,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,sBAAsB;IACxB,CAAC;IAED,IAAI,CAAC;QACH,mCAAmC;QACnC,MAAM,KAAK,GAAG,UAAU,IAAI,aAAa,IAAI,EAAE,CAAC;QAChD,MAAM,GAAG,GAAG,EAAE,CAAC,wBAAwB,KAAK,EAAE,CAAC,CAAC;QAChD,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,sCAAsC;QACtC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,GAAG,IAAI,MAAM,IAAI,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,EAAE,CAAC,wBAAwB,KAAK,EAAE,CAAC,CAAC;YAChD,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;YAC9C,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,GAAG,IAAI,SAAS,CAAC;gBAC/B,MAAM,GAAG,GAAG,EAAE,CAAC,wBAAwB,KAAK,EAAE,CAAC,CAAC;gBAChD,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;YAC3D,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;gBAC1E,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface PrismaContext {
2
+ schemaPath: string;
3
+ schema: string | null;
4
+ migrationFiles: string[];
5
+ }
6
+ export declare function collectPrismaContext(migrationsPath: string, changedFiles: string[]): PrismaContext;
7
+ export declare function loadMigrationSQL(migrationPath: string): string | null;
8
+ //# sourceMappingURL=prisma.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/collectors/prisma.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,oBAAoB,CAClC,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EAAE,GACrB,aAAa,CAWf;AAED,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQrE"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.collectPrismaContext = collectPrismaContext;
7
+ exports.loadMigrationSQL = loadMigrationSQL;
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ function collectPrismaContext(migrationsPath, changedFiles) {
11
+ const schemaPath = "prisma/schema.prisma";
12
+ const schema = fs_1.default.existsSync(schemaPath) ? fs_1.default.readFileSync(schemaPath, "utf-8") : null;
13
+ const migrationFiles = changedFiles.filter((f) => f.startsWith(`${migrationsPath}/`));
14
+ return {
15
+ schemaPath,
16
+ schema,
17
+ migrationFiles,
18
+ };
19
+ }
20
+ function loadMigrationSQL(migrationPath) {
21
+ // If migrationPath is already the sql file, load it; if folder, load migration.sql
22
+ const full = migrationPath.endsWith(".sql")
23
+ ? migrationPath
24
+ : path_1.default.join(migrationPath, "migration.sql");
25
+ if (!fs_1.default.existsSync(full))
26
+ return null;
27
+ return fs_1.default.readFileSync(full, "utf-8");
28
+ }
29
+ //# sourceMappingURL=prisma.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prisma.js","sourceRoot":"","sources":["../../src/collectors/prisma.ts"],"names":[],"mappings":";;;;;AASA,oDAcC;AAED,4CAQC;AAjCD,4CAAoB;AACpB,gDAAwB;AAQxB,SAAgB,oBAAoB,CAClC,cAAsB,EACtB,YAAsB;IAEtB,MAAM,UAAU,GAAG,sBAAsB,CAAC;IAC1C,MAAM,MAAM,GAAG,YAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAEvF,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,cAAc,GAAG,CAAC,CAAC,CAAC;IAEtF,OAAO;QACL,UAAU;QACV,MAAM;QACN,cAAc;KACf,CAAC;AACJ,CAAC;AAED,SAAgB,gBAAgB,CAAC,aAAqB;IACpD,mFAAmF;IACnF,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,MAAM,CAAC;QACzC,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,cAAI,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;IAE9C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,YAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,24 @@
1
+ export declare const DEFAULT_CONFIG: {
2
+ baseBranch: string;
3
+ headBranch: string;
4
+ database: {
5
+ engine: string;
6
+ orm: string;
7
+ migrationsPath: string;
8
+ };
9
+ futureConstraints: never[];
10
+ llm: {
11
+ provider: string;
12
+ model: string;
13
+ optional: boolean;
14
+ apiKey: undefined;
15
+ };
16
+ gate: {
17
+ failOn: string[];
18
+ };
19
+ };
20
+ export declare const DEFAULT_DB_RULES = "DB Architecture Rules (baseline):\n1. No migration adds a NOT NULL column on an existing table without a safe backfill strategy.\n2. High-cardinality tables must have appropriate indexes for expected access patterns.\n3. Foreign keys must not prevent soft delete or archival strategies.\n4. Pricing/config/business rules must not be hardcoded at entity level; must be contextual (tenant/machine/country).\n5. Entities that represent business concepts should support future versioning (history, effective dates).\n6. Avoid blocking DDL on large tables (Postgres: rewrite/locks).\n7. Many-to-many relations must be extensible (join table supports metadata).\n8. JSON/JSONB usage must be justified and versioned (schema evolution plan).";
21
+ export declare const DEFAULT_FUTURE_CONSTRAINTS = "Known future directions:\n- Multi-country deployment (currency, taxes, locale)\n- Machine-specific pricing and configuration\n- Feature flags per tenant / per machine\n- Audit history and long-term retention\n- Potential white-label / multi-tenant clients";
22
+ export declare const DEFAULT_SYSTEM_PROMPT = "You are a senior database and backend architect.\nYou audit schemas, migrations and backend code for scalability and evolvability risks.\nYou do not modify code. You only report risks and mitigations.\nYou must be conservative: if unsure, raise a warning.\nYou must output a structured report with severities: LOW, MEDIUM, HIGH, CRITICAL.\nFocus on: migration safety, future feature blockers, indexing, coupling, data model rigidity.";
23
+ export declare const DEFAULT_ANALYSIS_PROMPT = "Analyze the repository context provided below.\n\nTasks:\n1) Review migrations for risks: locking, table rewrites, irreversible changes, data loss, unsafe NOT NULL.\n2) Review schema/ORM model for scalability & evolvability: indexes, cardinalities, versioning, soft delete, multitenancy.\n3) Identify \"future feature blockers\" based on future-constraints.md.\n4) Output a report in Markdown with:\n - Executive summary\n - Detected issues (with severity)\n - Evidence (file + snippet or explanation)\n - Impact (what feature becomes hard)\n - Mitigation (safe path)";
24
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;CAkB1B,CAAC;AAEF,eAAO,MAAM,gBAAgB,kuBAQgD,CAAC;AAE9E,eAAO,MAAM,0BAA0B,oQAKQ,CAAC;AAEhD,eAAO,MAAM,qBAAqB,sbAK4D,CAAC;AAE/F,eAAO,MAAM,uBAAuB,skBAWR,CAAC"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_ANALYSIS_PROMPT = exports.DEFAULT_SYSTEM_PROMPT = exports.DEFAULT_FUTURE_CONSTRAINTS = exports.DEFAULT_DB_RULES = exports.DEFAULT_CONFIG = void 0;
4
+ exports.DEFAULT_CONFIG = {
5
+ baseBranch: "main",
6
+ headBranch: "develop",
7
+ database: {
8
+ engine: "postgres",
9
+ orm: "prisma",
10
+ migrationsPath: "prisma/migrations",
11
+ },
12
+ futureConstraints: [],
13
+ llm: {
14
+ provider: "mistral",
15
+ model: "mistral-medium-2508",
16
+ optional: true,
17
+ apiKey: undefined,
18
+ },
19
+ gate: {
20
+ failOn: ["HIGH", "CRITICAL"],
21
+ },
22
+ };
23
+ exports.DEFAULT_DB_RULES = `DB Architecture Rules (baseline):
24
+ 1. No migration adds a NOT NULL column on an existing table without a safe backfill strategy.
25
+ 2. High-cardinality tables must have appropriate indexes for expected access patterns.
26
+ 3. Foreign keys must not prevent soft delete or archival strategies.
27
+ 4. Pricing/config/business rules must not be hardcoded at entity level; must be contextual (tenant/machine/country).
28
+ 5. Entities that represent business concepts should support future versioning (history, effective dates).
29
+ 6. Avoid blocking DDL on large tables (Postgres: rewrite/locks).
30
+ 7. Many-to-many relations must be extensible (join table supports metadata).
31
+ 8. JSON/JSONB usage must be justified and versioned (schema evolution plan).`;
32
+ exports.DEFAULT_FUTURE_CONSTRAINTS = `Known future directions:
33
+ - Multi-country deployment (currency, taxes, locale)
34
+ - Machine-specific pricing and configuration
35
+ - Feature flags per tenant / per machine
36
+ - Audit history and long-term retention
37
+ - Potential white-label / multi-tenant clients`;
38
+ exports.DEFAULT_SYSTEM_PROMPT = `You are a senior database and backend architect.
39
+ You audit schemas, migrations and backend code for scalability and evolvability risks.
40
+ You do not modify code. You only report risks and mitigations.
41
+ You must be conservative: if unsure, raise a warning.
42
+ You must output a structured report with severities: LOW, MEDIUM, HIGH, CRITICAL.
43
+ Focus on: migration safety, future feature blockers, indexing, coupling, data model rigidity.`;
44
+ exports.DEFAULT_ANALYSIS_PROMPT = `Analyze the repository context provided below.
45
+
46
+ Tasks:
47
+ 1) Review migrations for risks: locking, table rewrites, irreversible changes, data loss, unsafe NOT NULL.
48
+ 2) Review schema/ORM model for scalability & evolvability: indexes, cardinalities, versioning, soft delete, multitenancy.
49
+ 3) Identify "future feature blockers" based on future-constraints.md.
50
+ 4) Output a report in Markdown with:
51
+ - Executive summary
52
+ - Detected issues (with severity)
53
+ - Evidence (file + snippet or explanation)
54
+ - Impact (what feature becomes hard)
55
+ - Mitigation (safe path)`;
56
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":";;;AAGa,QAAA,cAAc,GAAG;IAC5B,UAAU,EAAE,MAAM;IAClB,UAAU,EAAE,SAAS;IACrB,QAAQ,EAAE;QACR,MAAM,EAAE,UAAU;QAClB,GAAG,EAAE,QAAQ;QACb,cAAc,EAAE,mBAAmB;KACpC;IACD,iBAAiB,EAAE,EAAE;IACrB,GAAG,EAAE;QACH,QAAQ,EAAE,SAAS;QACnB,KAAK,EAAE,qBAAqB;QAC5B,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,SAAS;KAClB;IACD,IAAI,EAAE;QACJ,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC;KAC7B;CACF,CAAC;AAEW,QAAA,gBAAgB,GAAG;;;;;;;;6EAQ6C,CAAC;AAEjE,QAAA,0BAA0B,GAAG;;;;;+CAKK,CAAC;AAEnC,QAAA,qBAAqB,GAAG;;;;;8FAKyD,CAAC;AAElF,QAAA,uBAAuB,GAAG;;;;;;;;;;;4BAWX,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { GuardianConfig } from "../types/config.js";
2
+ export declare function loadConfig(cwd?: string): Required<GuardianConfig>;
3
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,QAAQ,CAAC,cAAc,CAAC,CA2DhF"}