@jigyasudham/veto 0.8.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/.claude/settings.local.json +9 -0
- package/README.md +190 -0
- package/dist/adapters/claude.js +57 -0
- package/dist/adapters/codex.js +58 -0
- package/dist/adapters/gemini.js +58 -0
- package/dist/adapters/index.js +156 -0
- package/dist/agents/development/api.js +116 -0
- package/dist/agents/development/backend.js +82 -0
- package/dist/agents/development/coder.js +207 -0
- package/dist/agents/development/database.js +81 -0
- package/dist/agents/development/debugger.js +234 -0
- package/dist/agents/development/devops.js +84 -0
- package/dist/agents/development/frontend.js +83 -0
- package/dist/agents/development/migration.js +141 -0
- package/dist/agents/development/performance.js +142 -0
- package/dist/agents/development/refactor.js +85 -0
- package/dist/agents/development/reviewer.js +260 -0
- package/dist/agents/development/tester.js +143 -0
- package/dist/agents/executor.js +144 -0
- package/dist/agents/memory/context-manager.js +167 -0
- package/dist/agents/memory/decision-logger.js +157 -0
- package/dist/agents/memory/knowledge-base.js +120 -0
- package/dist/agents/memory/pattern-learner.js +140 -0
- package/dist/agents/memory/project-mapper.js +114 -0
- package/dist/agents/quality/accessibility.js +89 -0
- package/dist/agents/quality/code-quality.js +109 -0
- package/dist/agents/quality/compatibility.js +55 -0
- package/dist/agents/quality/documentation.js +95 -0
- package/dist/agents/quality/error-handling.js +87 -0
- package/dist/agents/research/competitor-analyzer.js +44 -0
- package/dist/agents/research/cost-analyzer.js +51 -0
- package/dist/agents/research/estimator.js +57 -0
- package/dist/agents/research/ethics-bias.js +111 -0
- package/dist/agents/research/researcher.js +112 -0
- package/dist/agents/research/risk-assessor.js +61 -0
- package/dist/agents/research/tech-advisor.js +52 -0
- package/dist/agents/security/auth.js +269 -0
- package/dist/agents/security/dependency-audit.js +273 -0
- package/dist/agents/security/penetration.js +245 -0
- package/dist/agents/security/privacy.js +259 -0
- package/dist/agents/security/scanner.js +288 -0
- package/dist/agents/security/secrets.js +212 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/workflow/automation.js +56 -0
- package/dist/agents/workflow/file-manager.js +49 -0
- package/dist/agents/workflow/git-agent.js +52 -0
- package/dist/agents/workflow/reporter.js +48 -0
- package/dist/agents/workflow/search-agent.js +39 -0
- package/dist/agents/workflow/task-coordinator.js +40 -0
- package/dist/agents/workflow/task-planner.js +46 -0
- package/dist/cli.js +132 -0
- package/dist/council/decision-engine.js +136 -0
- package/dist/council/devil-advocate.js +106 -0
- package/dist/council/index.js +37 -0
- package/dist/council/lead-developer.js +108 -0
- package/dist/council/legal-compliance.js +142 -0
- package/dist/council/product-manager.js +92 -0
- package/dist/council/security.js +162 -0
- package/dist/council/system-architect.js +122 -0
- package/dist/council/types.js +2 -0
- package/dist/council/ux-designer.js +109 -0
- package/dist/memory/local.js +182 -0
- package/dist/memory/schema.js +116 -0
- package/dist/memory/sync.js +199 -0
- package/dist/router/complexity-scorer.js +78 -0
- package/dist/router/context-compressor.js +58 -0
- package/dist/router/index.js +29 -0
- package/dist/router/learning-updater.js +186 -0
- package/dist/router/model-selector.js +51 -0
- package/dist/router/rate-monitor.js +73 -0
- package/dist/server.js +949 -0
- package/dist/skills/development/skill-api-design.js +313 -0
- package/dist/skills/development/skill-auth.js +255 -0
- package/dist/skills/development/skill-ci-cd.js +2 -0
- package/dist/skills/development/skill-crud.js +193 -0
- package/dist/skills/development/skill-db-schema.js +2 -0
- package/dist/skills/development/skill-docker.js +2 -0
- package/dist/skills/development/skill-env-setup.js +2 -0
- package/dist/skills/development/skill-scaffold.js +299 -0
- package/dist/skills/intelligence/skill-complexity-score.js +66 -0
- package/dist/skills/intelligence/skill-cost-track.js +36 -0
- package/dist/skills/intelligence/skill-learning-loop.js +66 -0
- package/dist/skills/intelligence/skill-pattern-detect.js +35 -0
- package/dist/skills/intelligence/skill-rate-watch.js +58 -0
- package/dist/skills/memory/skill-context-compress.js +82 -0
- package/dist/skills/memory/skill-cross-sync.js +88 -0
- package/dist/skills/memory/skill-decision-log.js +103 -0
- package/dist/skills/memory/skill-session-restore.js +44 -0
- package/dist/skills/memory/skill-session-save.js +78 -0
- package/dist/skills/quality/skill-accessibility.js +2 -0
- package/dist/skills/quality/skill-code-review.js +60 -0
- package/dist/skills/quality/skill-docs-gen.js +2 -0
- package/dist/skills/quality/skill-perf-audit.js +2 -0
- package/dist/skills/quality/skill-security-scan.js +67 -0
- package/dist/skills/quality/skill-test-suite.js +274 -0
- package/dist/skills/workflow/skill-deploy.js +2 -0
- package/dist/skills/workflow/skill-git-workflow.js +2 -0
- package/dist/skills/workflow/skill-rollback.js +2 -0
- package/dist/skills/workflow/skill-task-breakdown.js +2 -0
- package/package.json +30 -0
- package/src/adapters/claude.ts +70 -0
- package/src/adapters/codex.ts +71 -0
- package/src/adapters/gemini.ts +71 -0
- package/src/adapters/index.ts +217 -0
- package/src/agents/development/api.ts +120 -0
- package/src/agents/development/backend.ts +85 -0
- package/src/agents/development/coder.ts +213 -0
- package/src/agents/development/database.ts +83 -0
- package/src/agents/development/debugger.ts +238 -0
- package/src/agents/development/devops.ts +86 -0
- package/src/agents/development/frontend.ts +85 -0
- package/src/agents/development/migration.ts +144 -0
- package/src/agents/development/performance.ts +144 -0
- package/src/agents/development/refactor.ts +86 -0
- package/src/agents/development/reviewer.ts +268 -0
- package/src/agents/development/tester.ts +151 -0
- package/src/agents/executor.ts +158 -0
- package/src/agents/memory/context-manager.ts +171 -0
- package/src/agents/memory/decision-logger.ts +160 -0
- package/src/agents/memory/knowledge-base.ts +124 -0
- package/src/agents/memory/pattern-learner.ts +143 -0
- package/src/agents/memory/project-mapper.ts +118 -0
- package/src/agents/quality/accessibility.ts +99 -0
- package/src/agents/quality/code-quality.ts +115 -0
- package/src/agents/quality/compatibility.ts +58 -0
- package/src/agents/quality/documentation.ts +105 -0
- package/src/agents/quality/error-handling.ts +96 -0
- package/src/agents/research/competitor-analyzer.ts +45 -0
- package/src/agents/research/cost-analyzer.ts +54 -0
- package/src/agents/research/estimator.ts +60 -0
- package/src/agents/research/ethics-bias.ts +113 -0
- package/src/agents/research/researcher.ts +114 -0
- package/src/agents/research/risk-assessor.ts +63 -0
- package/src/agents/research/tech-advisor.ts +55 -0
- package/src/agents/security/auth.ts +287 -0
- package/src/agents/security/dependency-audit.ts +337 -0
- package/src/agents/security/penetration.ts +262 -0
- package/src/agents/security/privacy.ts +285 -0
- package/src/agents/security/scanner.ts +322 -0
- package/src/agents/security/secrets.ts +249 -0
- package/src/agents/types.ts +66 -0
- package/src/agents/workflow/automation.ts +59 -0
- package/src/agents/workflow/file-manager.ts +52 -0
- package/src/agents/workflow/git-agent.ts +55 -0
- package/src/agents/workflow/reporter.ts +51 -0
- package/src/agents/workflow/search-agent.ts +40 -0
- package/src/agents/workflow/task-coordinator.ts +41 -0
- package/src/agents/workflow/task-planner.ts +47 -0
- package/src/cli.ts +143 -0
- package/src/council/decision-engine.ts +171 -0
- package/src/council/devil-advocate.ts +116 -0
- package/src/council/index.ts +44 -0
- package/src/council/lead-developer.ts +118 -0
- package/src/council/legal-compliance.ts +152 -0
- package/src/council/product-manager.ts +102 -0
- package/src/council/security.ts +172 -0
- package/src/council/system-architect.ts +132 -0
- package/src/council/types.ts +33 -0
- package/src/council/ux-designer.ts +121 -0
- package/src/memory/local.ts +305 -0
- package/src/memory/schema.ts +174 -0
- package/src/memory/sync.ts +274 -0
- package/src/router/complexity-scorer.ts +96 -0
- package/src/router/context-compressor.ts +74 -0
- package/src/router/index.ts +60 -0
- package/src/router/learning-updater.ts +271 -0
- package/src/router/model-selector.ts +83 -0
- package/src/router/rate-monitor.ts +103 -0
- package/src/server.ts +1038 -0
- package/src/skills/development/skill-api-design.ts +329 -0
- package/src/skills/development/skill-auth.ts +271 -0
- package/src/skills/development/skill-ci-cd.ts +0 -0
- package/src/skills/development/skill-crud.ts +209 -0
- package/src/skills/development/skill-db-schema.ts +0 -0
- package/src/skills/development/skill-docker.ts +0 -0
- package/src/skills/development/skill-env-setup.ts +0 -0
- package/src/skills/development/skill-scaffold.ts +323 -0
- package/src/skills/intelligence/skill-complexity-score.ts +69 -0
- package/src/skills/intelligence/skill-cost-track.ts +39 -0
- package/src/skills/intelligence/skill-learning-loop.ts +69 -0
- package/src/skills/intelligence/skill-pattern-detect.ts +38 -0
- package/src/skills/intelligence/skill-rate-watch.ts +61 -0
- package/src/skills/memory/skill-context-compress.ts +98 -0
- package/src/skills/memory/skill-cross-sync.ts +104 -0
- package/src/skills/memory/skill-decision-log.ts +119 -0
- package/src/skills/memory/skill-session-restore.ts +59 -0
- package/src/skills/memory/skill-session-save.ts +94 -0
- package/src/skills/quality/skill-accessibility.ts +0 -0
- package/src/skills/quality/skill-code-review.ts +84 -0
- package/src/skills/quality/skill-docs-gen.ts +0 -0
- package/src/skills/quality/skill-perf-audit.ts +0 -0
- package/src/skills/quality/skill-security-scan.ts +91 -0
- package/src/skills/quality/skill-test-suite.ts +290 -0
- package/src/skills/workflow/skill-deploy.ts +0 -0
- package/src/skills/workflow/skill-git-workflow.ts +0 -0
- package/src/skills/workflow/skill-rollback.ts +0 -0
- package/src/skills/workflow/skill-task-breakdown.ts +0 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
const BLOCK_RULES = [
|
|
2
|
+
{
|
|
3
|
+
pattern: /\bmd5\b/i,
|
|
4
|
+
reason: 'MD5 is cryptographically broken since 2008. Rainbow tables crack it instantly.',
|
|
5
|
+
recommendation: 'Use bcrypt (cost 12) for passwords. Use SHA-256 for checksums only.',
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
pattern: /\bsha-?1\b/i,
|
|
9
|
+
reason: 'SHA-1 collision attacks are practical since 2017. Deprecated for all security use.',
|
|
10
|
+
recommendation: 'Use SHA-256 or SHA-3. For passwords use bcrypt/argon2.',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
pattern: /\b(des|3des|triple.?des)\b/i,
|
|
14
|
+
reason: 'DES/3DES is broken. Brute-forceable in hours.',
|
|
15
|
+
recommendation: 'Use AES-256-GCM for symmetric encryption.',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
pattern: /\brc4\b/i,
|
|
19
|
+
reason: 'RC4 is broken — biased keystream, practical attacks exist.',
|
|
20
|
+
recommendation: 'Use ChaCha20-Poly1305 or AES-256-GCM.',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
pattern: /\beval\s*\(/i,
|
|
24
|
+
reason: 'eval() enables arbitrary code execution from user input.',
|
|
25
|
+
recommendation: 'Remove eval(). Use JSON.parse() for data, redesign for logic.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: /\bnew\s+Function\s*\(/i,
|
|
29
|
+
reason: 'new Function() is eval() in disguise. Same arbitrary execution risk.',
|
|
30
|
+
recommendation: 'Never construct functions from strings. Redesign the logic.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
pattern: /hardcod.{0,20}(password|secret|key|token|credential)/i,
|
|
34
|
+
reason: 'Hardcoded credentials ship to version control and get leaked.',
|
|
35
|
+
recommendation: 'Move to environment variables. Use dotenv locally, vault in prod.',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
pattern: /(password|secret|api.?key|token).{0,20}hardcod/i,
|
|
39
|
+
reason: 'Hardcoded credentials in source is a critical vulnerability.',
|
|
40
|
+
recommendation: 'Use process.env.VAR_NAME. Never commit secrets.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
pattern: /disable.{0,15}(ssl|tls|cert(?:ificate)?(?:.?verif)?)/i,
|
|
44
|
+
reason: 'Disabling SSL/TLS validation exposes all traffic to MITM attacks.',
|
|
45
|
+
recommendation: 'Fix the certificate properly. Never disable validation in production.',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
pattern: /cors.{0,15}['"]\s*\*\s*['"]/i,
|
|
49
|
+
reason: 'CORS wildcard (*) allows any origin to read API responses.',
|
|
50
|
+
recommendation: 'Specify exact allowed origins: ["https://yourdomain.com"].',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
pattern: /innerHTML\s*=\s*.*(req\b|input\b|param|user|body)/i,
|
|
54
|
+
reason: 'Setting innerHTML from user data enables stored XSS attacks.',
|
|
55
|
+
recommendation: 'Use textContent for text. Sanitize with DOMPurify if HTML is needed.',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
pattern: /no.{0,10}input.{0,10}(valid|sanitiz)/i,
|
|
59
|
+
reason: 'Explicitly skipping input validation is the root cause of most injections.',
|
|
60
|
+
recommendation: 'Validate all external input at the boundary with zod/joi schemas.',
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
const WARN_RULES = [
|
|
64
|
+
{ pattern: /\bjquery\b/i, concern: 'jQuery in 2025 adds 30KB for what native DOM provides for free.' },
|
|
65
|
+
{ pattern: /\bvar\s+[a-zA-Z_$]/i, concern: 'var has function-scope hoisting. Use const (default) or let.' },
|
|
66
|
+
{ pattern: /catch\s*\([^)]*\)\s*\{\s*(\/\/[^\n]*)?\s*\}/i, concern: 'Empty catch silently swallows errors.' },
|
|
67
|
+
{ pattern: /console\.(log|debug)\b/i, concern: 'console.log in production leaks internal state. Use structured logging.' },
|
|
68
|
+
{ pattern: /\/\/\s*(todo|fixme|hack|xxx)\b/i, concern: 'Unresolved TODO/FIXME — resolve before shipping.' },
|
|
69
|
+
{ pattern: /:\s*any\b/i, concern: 'TypeScript any disables type safety. Use unknown or a proper type.' },
|
|
70
|
+
{ pattern: /\b(xdescribe|xit|xtest|\.skip)\b/i, concern: 'Skipped tests hide regressions. Fix or delete them.' },
|
|
71
|
+
{ pattern: /Math\.random\(\)/i, concern: 'Math.random() is not cryptographically secure. Use crypto.randomBytes().' },
|
|
72
|
+
];
|
|
73
|
+
const TRIVIAL = /^(rename|fix typo|reorder|reformat|format code|update comment|add comment)\b/i;
|
|
74
|
+
export function analyze(task) {
|
|
75
|
+
if (TRIVIAL.test(task.trim())) {
|
|
76
|
+
return { verdict: 'approve', reason: 'Trivial change — no security or quality concerns.', concerns: [] };
|
|
77
|
+
}
|
|
78
|
+
const blocks = [];
|
|
79
|
+
const concerns = [];
|
|
80
|
+
for (const rule of BLOCK_RULES) {
|
|
81
|
+
if (rule.pattern.test(task)) {
|
|
82
|
+
blocks.push({ reason: rule.reason, recommendation: rule.recommendation });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (const rule of WARN_RULES) {
|
|
86
|
+
if (rule.pattern.test(task)) {
|
|
87
|
+
concerns.push(rule.concern);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (blocks.length > 0) {
|
|
91
|
+
return {
|
|
92
|
+
verdict: 'block',
|
|
93
|
+
reason: blocks[0].reason,
|
|
94
|
+
concerns: [...blocks.slice(1).map(b => b.reason), ...concerns],
|
|
95
|
+
recommendation: blocks.map(b => b.recommendation).join(' | '),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (concerns.length > 0) {
|
|
99
|
+
return {
|
|
100
|
+
verdict: 'warn',
|
|
101
|
+
reason: `${concerns.length} code quality issue${concerns.length > 1 ? 's' : ''} detected.`,
|
|
102
|
+
concerns,
|
|
103
|
+
recommendation: 'Address quality concerns before shipping to production.',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return { verdict: 'approve', reason: 'No security or quality violations detected.', concerns: [] };
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=lead-developer.js.map
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const BLOCK_RULES = [
|
|
2
|
+
{
|
|
3
|
+
pattern: /\b(gpl|gnu.?general.?public.?license)\b/i,
|
|
4
|
+
reason: 'GPL code in a non-GPL project creates license contamination — entire project must become GPL.',
|
|
5
|
+
recommendation: 'Audit all dependencies with license-checker. Replace GPL deps with MIT/Apache/BSD alternatives.',
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
pattern: /\bagpl\b/i,
|
|
9
|
+
reason: 'AGPL requires open-sourcing any server code users interact with over a network.',
|
|
10
|
+
recommendation: 'Either make your code AGPL, obtain a commercial license, or replace the AGPL dependency.',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
pattern: /collect.{0,40}(personal|pii|email|phone|address).{0,40}no.{0,20}consent/i,
|
|
14
|
+
reason: 'Collecting personal data without consent violates GDPR Article 6 and CCPA — fines up to 4% global revenue.',
|
|
15
|
+
recommendation: 'Add explicit consent collection before gathering PII. Document legal basis (contract, consent, legitimate interest).',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
pattern: /\b(hipaa|phi|protected.?health|health.?record)\b/i,
|
|
19
|
+
reason: 'Health data (PHI) requires HIPAA-compliant infrastructure, signed BAAs, and mandatory audit logging.',
|
|
20
|
+
recommendation: 'Use a HIPAA-compliant cloud provider. Sign Business Associate Agreements. Encrypt PHI at rest and in transit.',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
pattern: /collect.{0,30}(children|child|minor|under.{0,5}1[23])/i,
|
|
24
|
+
reason: 'Collecting data from under-13s without verifiable parental consent violates COPPA (US) and GDPR.',
|
|
25
|
+
recommendation: 'Add age gate. Obtain verifiable parental consent. Consult legal counsel before proceeding.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: /store.{0,30}(credit.?card|card.?number|\bpan\b|\bcvv\b|\bcvc\b)/i,
|
|
29
|
+
reason: 'Storing raw card data requires PCI-DSS Level 1 compliance — years of audits and millions in infrastructure.',
|
|
30
|
+
recommendation: "Never store raw card data. Use Stripe/Braintree tokenization. Your PCI scope drops to SAQ-A.",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
pattern: /scrape.{0,30}(facebook|twitter|linkedin|instagram|google|youtube|amazon)/i,
|
|
34
|
+
reason: 'Scraping major platforms violates their ToS and has led to multi-million dollar lawsuits (hiQ v. LinkedIn).',
|
|
35
|
+
recommendation: 'Use official APIs only. Review ToS data-use clauses. Seek legal opinion if data has commercial value.',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
pattern: /train.{0,40}(model|ai|ml|llm).{0,40}(user.?data|customer.?data|without.{0,15}consent)/i,
|
|
39
|
+
reason: 'Training AI/ML on user data without consent violates GDPR and the ToS of most data platforms.',
|
|
40
|
+
recommendation: 'Obtain explicit opt-in consent for ML training use. Provide opt-out. Document data flows in privacy policy.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
pattern: /\b(biometric|facial.?recogni|fingerprint).{0,30}(store|collect|process)\b/i,
|
|
44
|
+
reason: 'Biometric data has strict consent laws: BIPA (Illinois), GDPR Article 9, TX/WA state laws.',
|
|
45
|
+
recommendation: 'Obtain explicit written consent. Check state/country-specific laws. Consider if biometrics are necessary at all.',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
pattern: /\bccpa\b.{0,30}(ignore|skip|bypass|not.{0,10}(apply|need))/i,
|
|
49
|
+
reason: 'CCPA applies to any business serving California residents above certain thresholds — not opt-in.',
|
|
50
|
+
recommendation: 'Add "Do Not Sell My Personal Information" link. Honor opt-out requests within 15 days.',
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
const WARN_RULES = [
|
|
54
|
+
{
|
|
55
|
+
pattern: /no.{0,25}privacy.?policy/i,
|
|
56
|
+
concern: 'Collecting any user data without a privacy policy violates GDPR, CCPA, and most app store guidelines.',
|
|
57
|
+
recommendation: 'Draft a privacy policy covering: what you collect, why, how long, who you share with, user rights.',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
pattern: /log.{0,25}(email|ip.?address|phone|full.?name|ssn)|(email|phone|full.?name|ssn).{0,25}(log|plaintext|plain.?text)/i,
|
|
61
|
+
concern: 'Logging PII creates data retention liability and complicates right-to-erasure compliance.',
|
|
62
|
+
recommendation: 'Pseudonymize PII in logs (hash emails, truncate IPs). Set log retention to 30-90 days maximum.',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
pattern: /no.{0,20}(delete|erasure|right.?to.?delete|data.?removal|forget)/i,
|
|
66
|
+
concern: 'GDPR Article 17 mandates honoring right-to-erasure requests within 30 days.',
|
|
67
|
+
recommendation: 'Build user data deletion endpoint. Cascade to backups. Document deletion confirmation process.',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
pattern: /open.?source|npm.{0,20}install|pip.{0,20}install|composer|cargo.{0,20}add/i,
|
|
71
|
+
concern: 'New dependencies may carry GPL/AGPL licenses that contaminate your project license.',
|
|
72
|
+
recommendation: 'Run license-checker or FOSSA after adding deps. Block GPL/AGPL in CI for proprietary projects.',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
pattern: /cookie|tracking|analytics|pixel|beacon/i,
|
|
76
|
+
concern: 'Cookies and tracking pixels require consent banners for EU/UK users (ePrivacy Directive + GDPR).',
|
|
77
|
+
recommendation: 'Integrate consent management platform (Cookiebot, OneTrust) for EU users.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
pattern: /third.?party.{0,30}(share|send|forward|transmit).{0,30}(user|personal|customer)/i,
|
|
81
|
+
concern: 'Sharing personal data with third parties requires disclosure in privacy policy and may need consent.',
|
|
82
|
+
recommendation: 'List all third-party data recipients in privacy policy. Sign Data Processing Agreements (DPAs).',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
pattern: /retain.{0,30}(forever|indefinitely|no.?limit|no.?expiry)|store.{0,30}forever/i,
|
|
86
|
+
concern: 'Retaining personal data indefinitely violates GDPR storage limitation principle (Article 5(1)(e)).',
|
|
87
|
+
recommendation: 'Define retention periods per data type. Auto-delete or anonymize after the period expires.',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
pattern: /\b(trademark|patent|copyright)\b/i,
|
|
91
|
+
concern: 'IP risk flagged — verify you have rights to use and distribute this.',
|
|
92
|
+
recommendation: 'Confirm licensing rights. Consult an IP attorney if building on patented methods or using third-party branding.',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
pattern: /\b(gdpr|data.?protection)\b.{0,30}(ignore|bypass|skip|not.{0,10}(apply|worry))/i,
|
|
96
|
+
concern: "GDPR applies to any service used by EU residents regardless of where you're based.",
|
|
97
|
+
recommendation: 'Conduct a GDPR compliance review. Appoint a Data Protection Officer if required.',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
pattern: /export.{0,20}(encryption|crypto|cipher).{0,20}(us|usa|america|international)/i,
|
|
101
|
+
concern: 'Exporting encryption software may require US export license (EAR/ECCN classification).',
|
|
102
|
+
recommendation: 'Check ECCN classification for your encryption strength. File annual self-classification if needed.',
|
|
103
|
+
},
|
|
104
|
+
];
|
|
105
|
+
const TRIVIAL = /^(rename|fix typo|reorder|reformat|format|update comment|add comment)\b/i;
|
|
106
|
+
export function analyze(task) {
|
|
107
|
+
if (TRIVIAL.test(task.trim())) {
|
|
108
|
+
return { verdict: 'approve', reason: 'Trivial change — no legal concerns.', concerns: [] };
|
|
109
|
+
}
|
|
110
|
+
const blocks = [];
|
|
111
|
+
const concerns = [];
|
|
112
|
+
const recommendations = [];
|
|
113
|
+
for (const rule of BLOCK_RULES) {
|
|
114
|
+
if (rule.pattern.test(task)) {
|
|
115
|
+
blocks.push({ reason: rule.reason, recommendation: rule.recommendation });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
for (const rule of WARN_RULES) {
|
|
119
|
+
if (rule.pattern.test(task)) {
|
|
120
|
+
concerns.push(rule.concern);
|
|
121
|
+
recommendations.push(rule.recommendation);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (blocks.length > 0) {
|
|
125
|
+
return {
|
|
126
|
+
verdict: 'block',
|
|
127
|
+
reason: blocks[0].reason,
|
|
128
|
+
concerns: blocks.slice(1).map(b => b.reason),
|
|
129
|
+
recommendation: blocks.map(b => b.recommendation).join(' | '),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (concerns.length > 0) {
|
|
133
|
+
return {
|
|
134
|
+
verdict: 'warn',
|
|
135
|
+
reason: `${concerns.length} legal or compliance concern${concerns.length > 1 ? 's' : ''} — review before shipping.`,
|
|
136
|
+
concerns,
|
|
137
|
+
recommendation: recommendations[0],
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return { verdict: 'approve', reason: 'No legal or compliance issues detected.', concerns: [] };
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=legal-compliance.js.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
const BLOCK_RULES = [
|
|
2
|
+
{
|
|
3
|
+
pattern: /rewrite.{0,20}from.{0,10}scratch/i,
|
|
4
|
+
reason: 'Rewriting from scratch abandons working code and delays users by months.',
|
|
5
|
+
recommendation: 'Incremental refactor using Strangler Fig. Split only when bottleneck is proven.',
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
pattern: /build.{0,20}(our own|custom).{0,20}(framework|orm|database|auth.?system|message.?queue)/i,
|
|
9
|
+
reason: 'Building custom infrastructure has a 12+ month cost before it provides value.',
|
|
10
|
+
recommendation: 'Use battle-tested existing solutions. Build what differentiates you, not plumbing.',
|
|
11
|
+
},
|
|
12
|
+
];
|
|
13
|
+
const WARN_RULES = [
|
|
14
|
+
{
|
|
15
|
+
pattern: /\bmicroservice/i,
|
|
16
|
+
concern: 'Microservices add 10x operational complexity. Justified only at Netflix/Amazon scale.',
|
|
17
|
+
recommendation: 'Start modular monolith. Extract services only when a specific bottleneck demands it.',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
pattern: /enterprise.{0,20}(grade|pattern|architecture|solution)/i,
|
|
21
|
+
concern: 'Enterprise patterns optimize for 10,000-person orgs, not fast-moving products.',
|
|
22
|
+
recommendation: 'Ship the simple version. Add enterprise complexity when customers pay for it.',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
pattern: /future.{0,20}proof|build.{0,20}for.{0,20}(scale|growth|million)/i,
|
|
26
|
+
concern: 'Optimizing for imaginary future scale delays value to users you have today.',
|
|
27
|
+
recommendation: "YAGNI. Build for 10x current scale, not 1000x. You'll know when you need more.",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
pattern: /\bperfect\b|\bflawless\b|fully.{0,10}generic|completely.{0,10}flexible/i,
|
|
31
|
+
concern: 'Perfect is the enemy of shipped. What is the minimum version that solves the problem?',
|
|
32
|
+
recommendation: 'Define a specific "done" criterion. Timebox perfection work to 20% of total.',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
pattern: /build.{0,20}(framework|platform|engine|layer|system)\b.{0,20}first/i,
|
|
36
|
+
concern: 'Building infrastructure before product delays user value. Products fund platforms.',
|
|
37
|
+
recommendation: 'Build product features. Extract the framework only when the pattern is proven.',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
pattern: /abstrac|generic.{0,20}(solution|framework|wrapper|handler)/i,
|
|
41
|
+
concern: 'Premature abstraction bets on requirements that may never come.',
|
|
42
|
+
recommendation: 'Three concrete implementations before extracting an abstraction.',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
pattern: /add.{0,20}feature.{0,30}(not.{0,10}ask|nobody.{0,10}request|just.{0,10}in.{0,10}case)/i,
|
|
46
|
+
concern: 'Building unrequested features is scope creep. Validate demand first.',
|
|
47
|
+
recommendation: 'Ship what was asked. Add features after user feedback confirms demand.',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
pattern: /v2|v3|version\s+[23]/i,
|
|
51
|
+
concern: 'Designing v2/v3 before v1 ships is a classic focus trap.',
|
|
52
|
+
recommendation: 'Ship v1. Learn from real users. Then plan v2 with real data.',
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
const TRIVIAL = /^(rename|fix typo|reorder|reformat|format|update comment|add comment)\b/i;
|
|
56
|
+
export function analyze(task) {
|
|
57
|
+
if (TRIVIAL.test(task.trim())) {
|
|
58
|
+
return { verdict: 'approve', reason: 'Trivial change — no product concerns.', concerns: [] };
|
|
59
|
+
}
|
|
60
|
+
const blocks = [];
|
|
61
|
+
const concerns = [];
|
|
62
|
+
const recommendations = [];
|
|
63
|
+
for (const rule of BLOCK_RULES) {
|
|
64
|
+
if (rule.pattern.test(task)) {
|
|
65
|
+
blocks.push({ reason: rule.reason, recommendation: rule.recommendation });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const rule of WARN_RULES) {
|
|
69
|
+
if (rule.pattern.test(task)) {
|
|
70
|
+
concerns.push(rule.concern);
|
|
71
|
+
recommendations.push(rule.recommendation);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (blocks.length > 0) {
|
|
75
|
+
return {
|
|
76
|
+
verdict: 'block',
|
|
77
|
+
reason: blocks[0].reason,
|
|
78
|
+
concerns: blocks.slice(1).map(b => b.reason),
|
|
79
|
+
recommendation: blocks.map(b => b.recommendation).join(' | '),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (concerns.length > 0) {
|
|
83
|
+
return {
|
|
84
|
+
verdict: 'warn',
|
|
85
|
+
reason: `${concerns.length} product risk${concerns.length > 1 ? 's' : ''} — scope or complexity concern.`,
|
|
86
|
+
concerns,
|
|
87
|
+
recommendation: recommendations[0],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return { verdict: 'approve', reason: 'Reasonable scope. Ship it.', concerns: [] };
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=product-manager.js.map
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
const BLOCK_RULES = [
|
|
2
|
+
{
|
|
3
|
+
pattern: /(no.{0,25}rate.?limit|(auth|login|password|signin|otp|2fa|token|reset).{0,50}no.{0,20}rate.?limit|no.{0,25}rate.?limit.{0,50}(auth|login|password|signin|otp|2fa))/i,
|
|
4
|
+
reason: 'Auth endpoint without rate limiting is wide open to brute-force and credential stuffing.',
|
|
5
|
+
recommendation: 'Rate limit: 5 attempts / 15 min / IP. Exponential backoff. Lock account after 10 failures.',
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
pattern: /jwt.{0,35}(no|without|missing).{0,20}expir|token.{0,20}never.{0,15}expir/i,
|
|
9
|
+
reason: 'JWTs without expiry are permanent access tokens — a stolen token never becomes invalid.',
|
|
10
|
+
recommendation: 'Set JWT exp to 15 min. Issue refresh tokens in httpOnly, Secure, SameSite=Strict cookies.',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
pattern: /localStorage.{0,30}(token|jwt|session|auth|secret)|(token|jwt|session|auth|secret).{0,30}localStorage/i,
|
|
14
|
+
reason: 'Tokens in localStorage are readable by any script — XSS vulnerability gives full account takeover.',
|
|
15
|
+
recommendation: 'Store tokens only in httpOnly Secure SameSite=Strict cookies. Never localStorage.',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
pattern: /no.{0,20}csrf|skip.{0,20}csrf|disable.{0,20}csrf|without.{0,20}csrf/i,
|
|
19
|
+
reason: 'Missing CSRF protection enables cross-site request forgery — attackers can act as authenticated users.',
|
|
20
|
+
recommendation: 'Use CSRF tokens for form submissions. Set SameSite=Strict on session cookies as baseline.',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
pattern: /run.{0,20}(as\s+)?root|user\s+root.{0,20}(docker|container|image)/i,
|
|
24
|
+
reason: 'Running containers as root means any exploit has full host access.',
|
|
25
|
+
recommendation: 'Add `USER 1001` in Dockerfile. Use rootless containers. Drop all capabilities.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: /admin.{0,35}(route|endpoint|panel|api).{0,35}(no|without|skip|missing).{0,20}auth/i,
|
|
29
|
+
reason: 'Admin routes without authentication check expose privileged operations to any unauthenticated caller.',
|
|
30
|
+
recommendation: 'Guard all admin routes with both authentication AND role/permission authorization check.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
pattern: /\b(mass.?assign|accept.{0,20}(all|any).{0,20}(field|body|param|input))\b/i,
|
|
34
|
+
reason: 'Mass assignment lets attackers inject internal fields (isAdmin: true) through the request body.',
|
|
35
|
+
recommendation: 'Whitelist allowed fields explicitly. Never spread req.body into DB operations.',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
pattern: /\.\.\/|\.\.\\|path.{0,20}traversal|(file|path).{0,20}(user|input|param).{0,20}(read|open|access)/i,
|
|
39
|
+
reason: 'Path traversal vulnerability — attacker can read arbitrary server files by manipulating path input.',
|
|
40
|
+
recommendation: 'Use path.resolve() and verify result starts with your allowed base directory.',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
pattern: /deserializ.{0,30}(user|external|untrusted|input)/i,
|
|
44
|
+
reason: 'Deserializing untrusted data enables remote code execution via gadget chains.',
|
|
45
|
+
recommendation: 'Never deserialize untrusted data. Use JSON.parse() with schema validation (zod).',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
pattern: /xml.{0,30}(user|input|external).{0,30}(parse|process)/i,
|
|
49
|
+
reason: 'Parsing user-supplied XML without XXE protection enables XML External Entity injection.',
|
|
50
|
+
recommendation: 'Disable external entity processing in your XML parser. Prefer JSON over XML for APIs.',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
pattern: /\bshell\b.{0,30}(user|input|param)|exec\s*\(.{0,30}(req\.|input|param)/i,
|
|
54
|
+
reason: 'Passing user input to shell commands enables OS command injection — full server compromise.',
|
|
55
|
+
recommendation: 'Use execFile() with args as array. Never concatenate user input into shell commands.',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
pattern: /no.{0,20}(auth|authentication|authorization).{0,30}(internal|service.?to.?service|microservice)/i,
|
|
59
|
+
reason: 'Service-to-service calls without auth allows any internal service to impersonate another.',
|
|
60
|
+
recommendation: 'Use mutual TLS or service tokens for internal API calls. Never trust internal network alone.',
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
const WARN_RULES = [
|
|
64
|
+
{
|
|
65
|
+
pattern: /no.{0,25}(content.?security.?policy|\bcsp\b)/i,
|
|
66
|
+
concern: 'Missing Content-Security-Policy header — no browser-level XSS mitigation.',
|
|
67
|
+
recommendation: "Set CSP: default-src 'self'; script-src 'self'. Use helmet.js for Express.",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
pattern: /verbose.{0,20}error|stack.?trace.{0,25}(user|client|return|response|send)/i,
|
|
71
|
+
concern: 'Verbose error messages expose file paths, library versions, and stack traces to attackers.',
|
|
72
|
+
recommendation: 'Log full errors server-side only. Return generic messages to clients.',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
pattern: /no.{0,20}(audit|security).{0,15}log/i,
|
|
76
|
+
concern: 'No security audit log — impossible to detect or investigate breaches after the fact.',
|
|
77
|
+
recommendation: 'Log: auth events, admin actions, data exports, permission denials, with IP + user + timestamp.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
pattern: /no.{0,20}(dependency|package|npm|pip).{0,20}(audit|scan|update)/i,
|
|
81
|
+
concern: 'Unaudited dependencies may contain known CVEs actively exploited in the wild.',
|
|
82
|
+
recommendation: 'Run npm audit / snyk in CI pipeline. Block builds with critical severity CVEs.',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
pattern: /no.{0,20}(payload|body|request).{0,20}(size|limit|max)/i,
|
|
86
|
+
concern: 'No payload size limit — attackers can exhaust server memory with large request bodies.',
|
|
87
|
+
recommendation: 'Set body size limit (1MB JSON, 10MB uploads). Return 413 on excess. Use streaming for large files.',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
pattern: /\bregex\b.{0,30}(user|input|param|untrusted)/i,
|
|
91
|
+
concern: 'Complex regex on user input can cause ReDoS — catastrophic backtracking is a DoS vector.',
|
|
92
|
+
recommendation: 'Test regex with ReDoS checker (vuln-regex-detector). Set match timeout for user input.',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
pattern: /server.?version|x-powered-by|expose.{0,20}(version|framework)/i,
|
|
96
|
+
concern: 'Disclosing server/framework version in headers helps attackers target known CVEs.',
|
|
97
|
+
recommendation: 'Remove X-Powered-By. Set Server: header to empty string. Use helmet.js.',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
pattern: /upload.{0,30}(any|all|every).{0,20}(type|extension|format|file)/i,
|
|
101
|
+
concern: 'Accepting any file type enables upload of malicious executables or web shells.',
|
|
102
|
+
recommendation: 'Whitelist allowed MIME types. Validate magic bytes (not extension). Scan with ClamAV.',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
pattern: /\bidor\b|direct.{0,20}object.{0,20}ref|user.?id.{0,20}(param|query|url|path)/i,
|
|
106
|
+
concern: 'Potential IDOR — user can access other users\' resources by changing an ID in the request.',
|
|
107
|
+
recommendation: 'Always verify ownership: resource.userId === req.user.id before returning/mutating.',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
pattern: /compare.{0,20}(secret|token|hash|hmac|signature|password).{0,20}===|===.{0,20}(secret|token|hmac)/i,
|
|
111
|
+
concern: 'String === comparison of secrets is vulnerable to timing attacks.',
|
|
112
|
+
recommendation: 'Use crypto.timingSafeEqual() for all secret and HMAC comparisons.',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
pattern: /no.{0,20}hsts|http.{0,20}(only|no.?https)/i,
|
|
116
|
+
concern: 'Without HSTS, browsers may connect over HTTP — credentials can be intercepted.',
|
|
117
|
+
recommendation: 'Set HSTS: max-age=31536000; includeSubDomains; preload. Redirect all HTTP to HTTPS.',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
pattern: /secret.{0,20}(env|environment|config).{0,20}(log|print|console|output)/i,
|
|
121
|
+
concern: 'Logging secrets or config values leaks credentials to anyone with log access.',
|
|
122
|
+
recommendation: 'Never log secrets. Redact sensitive fields in structured logs. Audit log pipelines.',
|
|
123
|
+
},
|
|
124
|
+
];
|
|
125
|
+
const TRIVIAL = /^(rename|fix typo|reorder|reformat|format|update comment|add comment)\b/i;
|
|
126
|
+
export function analyze(task) {
|
|
127
|
+
if (TRIVIAL.test(task.trim())) {
|
|
128
|
+
return { verdict: 'approve', reason: 'Trivial change — no security concerns.', concerns: [] };
|
|
129
|
+
}
|
|
130
|
+
const blocks = [];
|
|
131
|
+
const concerns = [];
|
|
132
|
+
const recommendations = [];
|
|
133
|
+
for (const rule of BLOCK_RULES) {
|
|
134
|
+
if (rule.pattern.test(task)) {
|
|
135
|
+
blocks.push({ reason: rule.reason, recommendation: rule.recommendation });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
for (const rule of WARN_RULES) {
|
|
139
|
+
if (rule.pattern.test(task)) {
|
|
140
|
+
concerns.push(rule.concern);
|
|
141
|
+
recommendations.push(rule.recommendation);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (blocks.length > 0) {
|
|
145
|
+
return {
|
|
146
|
+
verdict: 'block',
|
|
147
|
+
reason: blocks[0].reason,
|
|
148
|
+
concerns: blocks.slice(1).map(b => b.reason),
|
|
149
|
+
recommendation: blocks.map(b => b.recommendation).join(' | '),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
if (concerns.length > 0) {
|
|
153
|
+
return {
|
|
154
|
+
verdict: 'warn',
|
|
155
|
+
reason: `${concerns.length} security concern${concerns.length > 1 ? 's' : ''} — threat model flagged issues.`,
|
|
156
|
+
concerns,
|
|
157
|
+
recommendation: recommendations[0],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return { verdict: 'approve', reason: 'No security threats identified in threat model.', concerns: [] };
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=security.js.map
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const BLOCK_RULES = [
|
|
2
|
+
{
|
|
3
|
+
pattern: /\bdrop\s+table\b/i,
|
|
4
|
+
reason: 'DROP TABLE is irreversible. No rollback possible after execution.',
|
|
5
|
+
recommendation: 'Write a down-migration. Verify backup. Test on staging. Run in maintenance window.',
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
pattern: /\btruncate\b/i,
|
|
9
|
+
reason: 'TRUNCATE deletes all rows instantly — no transaction, no rollback.',
|
|
10
|
+
recommendation: 'Use DELETE with WHERE in a transaction. Backup first. Verify on staging.',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
pattern: /\bdelete\s+from\b(?!.*where)/i,
|
|
14
|
+
reason: 'DELETE without WHERE clause wipes the entire table.',
|
|
15
|
+
recommendation: 'Always add a WHERE clause. Wrap in transaction. Test on staging.',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
pattern: /sqlite.{0,50}(concurrent|multi.?user|high.?traffic|production|scale)/i,
|
|
19
|
+
reason: 'SQLite serializes writes — breaks at >10 concurrent writers.',
|
|
20
|
+
recommendation: 'Use PostgreSQL for multi-user or high-traffic applications.',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
pattern: /(payment|billing|charge|transfer|transaction).{0,40}no.{0,15}(transaction|rollback|atomic)/i,
|
|
24
|
+
reason: 'Financial operations without database transactions risk data inconsistency.',
|
|
25
|
+
recommendation: 'Wrap all financial mutations in explicit BEGIN/COMMIT/ROLLBACK transactions.',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
pattern: /store.{0,20}(password|credit.?card|ssn|social.?security).{0,20}plain/i,
|
|
29
|
+
reason: 'Storing sensitive data in plaintext is a catastrophic data breach risk.',
|
|
30
|
+
recommendation: 'Hash passwords (bcrypt). Encrypt PII at rest (AES-256). Never store raw card data.',
|
|
31
|
+
},
|
|
32
|
+
];
|
|
33
|
+
const WARN_RULES = [
|
|
34
|
+
{
|
|
35
|
+
pattern: /select\s+\*/i,
|
|
36
|
+
concern: 'SELECT * fetches all columns — wasted memory and network on large tables.',
|
|
37
|
+
recommendation: 'Select only needed columns explicitly.',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
pattern: /\bfor\b.{0,80}(query|select|db\.|\.find|\.get|fetch)/i,
|
|
41
|
+
concern: 'Query inside a loop creates N+1 problem — DB gets hammered at scale.',
|
|
42
|
+
recommendation: 'Batch the query outside the loop using IN clause or JOIN.',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
pattern: /no.{0,15}index\b/i,
|
|
46
|
+
concern: 'Missing index on search/filter columns causes full table scans.',
|
|
47
|
+
recommendation: 'Add indexes on FK columns and any WHERE/ORDER BY columns.',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
pattern: /synchronous|blocking.{0,20}(i\/o|read|write|call)/i,
|
|
51
|
+
concern: 'Synchronous I/O blocks the Node.js event loop under concurrent load.',
|
|
52
|
+
recommendation: 'Use async/await with fs.promises, not fs.readFileSync.',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
pattern: /no.{0,15}cache\b/i,
|
|
56
|
+
concern: 'No caching on repeated reads hammers the database unnecessarily.',
|
|
57
|
+
recommendation: 'Cache hot read paths with Redis or in-memory TTL cache.',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
pattern: /no.{0,15}(timeout|time.?out)\b/i,
|
|
61
|
+
concern: 'External calls without timeout hang indefinitely when the dependency fails.',
|
|
62
|
+
recommendation: 'Set explicit timeouts (3-5s for APIs). Add retry with exponential backoff.',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
pattern: /single.{0,25}(point|server|node|instance).{0,25}(fail|crash|down)/i,
|
|
66
|
+
concern: 'Single point of failure with no redundancy — one crash = full outage.',
|
|
67
|
+
recommendation: 'Add health checks. Consider redundancy or graceful degradation.',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
pattern: /no.{0,15}(migration|schema.?version)/i,
|
|
71
|
+
concern: 'Database changes without versioned migrations cannot be safely rolled back.',
|
|
72
|
+
recommendation: 'Use a migration tool (Knex, Prisma migrate, Flyway).',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
pattern: /global\s+(state|variable|singleton)/i,
|
|
76
|
+
concern: 'Global mutable state causes unpredictable behavior under concurrent requests.',
|
|
77
|
+
recommendation: 'Scope state to request context. Use dependency injection.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
pattern: /\bregex\b.{0,30}(user.?input|unvalidated|untrusted)/i,
|
|
81
|
+
concern: 'Complex regex on untrusted input can cause ReDoS (catastrophic backtracking).',
|
|
82
|
+
recommendation: 'Use simple regex patterns. Set timeout on regex evaluation for user input.',
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
const TRIVIAL = /^(rename|fix typo|reorder|reformat|format|update comment|add comment)\b/i;
|
|
86
|
+
export function analyze(task) {
|
|
87
|
+
if (TRIVIAL.test(task.trim())) {
|
|
88
|
+
return { verdict: 'approve', reason: 'Trivial change — no architectural concerns.', concerns: [] };
|
|
89
|
+
}
|
|
90
|
+
const blocks = [];
|
|
91
|
+
const concerns = [];
|
|
92
|
+
const recommendations = [];
|
|
93
|
+
for (const rule of BLOCK_RULES) {
|
|
94
|
+
if (rule.pattern.test(task)) {
|
|
95
|
+
blocks.push({ reason: rule.reason, recommendation: rule.recommendation });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
for (const rule of WARN_RULES) {
|
|
99
|
+
if (rule.pattern.test(task)) {
|
|
100
|
+
concerns.push(rule.concern);
|
|
101
|
+
recommendations.push(rule.recommendation);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (blocks.length > 0) {
|
|
105
|
+
return {
|
|
106
|
+
verdict: 'block',
|
|
107
|
+
reason: blocks[0].reason,
|
|
108
|
+
concerns: blocks.slice(1).map(b => b.reason),
|
|
109
|
+
recommendation: blocks.map(b => b.recommendation).join(' | '),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (concerns.length > 0) {
|
|
113
|
+
return {
|
|
114
|
+
verdict: 'warn',
|
|
115
|
+
reason: `${concerns.length} structural concern${concerns.length > 1 ? 's' : ''} — review before building.`,
|
|
116
|
+
concerns,
|
|
117
|
+
recommendation: recommendations[0],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return { verdict: 'approve', reason: 'Architecture looks sound. No structural concerns.', concerns: [] };
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=system-architect.js.map
|