tlc-claude-code 1.4.9 → 1.5.2

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 (122) hide show
  1. package/CLAUDE.md +23 -0
  2. package/CODING-STANDARDS.md +408 -0
  3. package/bin/install.js +2 -0
  4. package/dashboard/dist/components/QualityGatePane.d.ts +38 -0
  5. package/dashboard/dist/components/QualityGatePane.js +31 -0
  6. package/dashboard/dist/components/QualityGatePane.test.d.ts +1 -0
  7. package/dashboard/dist/components/QualityGatePane.test.js +147 -0
  8. package/dashboard/dist/components/orchestration/AgentCard.d.ts +26 -0
  9. package/dashboard/dist/components/orchestration/AgentCard.js +60 -0
  10. package/dashboard/dist/components/orchestration/AgentCard.test.d.ts +1 -0
  11. package/dashboard/dist/components/orchestration/AgentCard.test.js +63 -0
  12. package/dashboard/dist/components/orchestration/AgentControls.d.ts +11 -0
  13. package/dashboard/dist/components/orchestration/AgentControls.js +20 -0
  14. package/dashboard/dist/components/orchestration/AgentControls.test.d.ts +1 -0
  15. package/dashboard/dist/components/orchestration/AgentControls.test.js +52 -0
  16. package/dashboard/dist/components/orchestration/AgentDetail.d.ts +35 -0
  17. package/dashboard/dist/components/orchestration/AgentDetail.js +37 -0
  18. package/dashboard/dist/components/orchestration/AgentDetail.test.d.ts +1 -0
  19. package/dashboard/dist/components/orchestration/AgentDetail.test.js +79 -0
  20. package/dashboard/dist/components/orchestration/AgentList.d.ts +31 -0
  21. package/dashboard/dist/components/orchestration/AgentList.js +47 -0
  22. package/dashboard/dist/components/orchestration/AgentList.test.d.ts +1 -0
  23. package/dashboard/dist/components/orchestration/AgentList.test.js +64 -0
  24. package/dashboard/dist/components/orchestration/CostMeter.d.ts +11 -0
  25. package/dashboard/dist/components/orchestration/CostMeter.js +28 -0
  26. package/dashboard/dist/components/orchestration/CostMeter.test.d.ts +1 -0
  27. package/dashboard/dist/components/orchestration/CostMeter.test.js +50 -0
  28. package/dashboard/dist/components/orchestration/ModelSelector.d.ts +20 -0
  29. package/dashboard/dist/components/orchestration/ModelSelector.js +12 -0
  30. package/dashboard/dist/components/orchestration/ModelSelector.test.d.ts +1 -0
  31. package/dashboard/dist/components/orchestration/ModelSelector.test.js +56 -0
  32. package/dashboard/dist/components/orchestration/OrchestrationDashboard.d.ts +28 -0
  33. package/dashboard/dist/components/orchestration/OrchestrationDashboard.js +28 -0
  34. package/dashboard/dist/components/orchestration/OrchestrationDashboard.test.d.ts +1 -0
  35. package/dashboard/dist/components/orchestration/OrchestrationDashboard.test.js +56 -0
  36. package/dashboard/dist/components/orchestration/QualityIndicator.d.ts +11 -0
  37. package/dashboard/dist/components/orchestration/QualityIndicator.js +37 -0
  38. package/dashboard/dist/components/orchestration/QualityIndicator.test.d.ts +1 -0
  39. package/dashboard/dist/components/orchestration/QualityIndicator.test.js +52 -0
  40. package/dashboard/dist/components/orchestration/index.d.ts +8 -0
  41. package/dashboard/dist/components/orchestration/index.js +8 -0
  42. package/package.json +1 -1
  43. package/server/lib/access-control.js +352 -0
  44. package/server/lib/access-control.test.js +322 -0
  45. package/server/lib/agents-cancel-command.js +139 -0
  46. package/server/lib/agents-cancel-command.test.js +180 -0
  47. package/server/lib/agents-get-command.js +159 -0
  48. package/server/lib/agents-get-command.test.js +167 -0
  49. package/server/lib/agents-list-command.js +150 -0
  50. package/server/lib/agents-list-command.test.js +149 -0
  51. package/server/lib/agents-logs-command.js +126 -0
  52. package/server/lib/agents-logs-command.test.js +198 -0
  53. package/server/lib/agents-retry-command.js +117 -0
  54. package/server/lib/agents-retry-command.test.js +192 -0
  55. package/server/lib/budget-limits.js +222 -0
  56. package/server/lib/budget-limits.test.js +214 -0
  57. package/server/lib/code-generator.js +291 -0
  58. package/server/lib/code-generator.test.js +307 -0
  59. package/server/lib/cost-command.js +290 -0
  60. package/server/lib/cost-command.test.js +202 -0
  61. package/server/lib/cost-optimizer.js +404 -0
  62. package/server/lib/cost-optimizer.test.js +232 -0
  63. package/server/lib/cost-projections.js +302 -0
  64. package/server/lib/cost-projections.test.js +217 -0
  65. package/server/lib/cost-reports.js +277 -0
  66. package/server/lib/cost-reports.test.js +254 -0
  67. package/server/lib/cost-tracker.js +216 -0
  68. package/server/lib/cost-tracker.test.js +302 -0
  69. package/server/lib/crypto-patterns.js +433 -0
  70. package/server/lib/crypto-patterns.test.js +346 -0
  71. package/server/lib/design-command.js +385 -0
  72. package/server/lib/design-command.test.js +249 -0
  73. package/server/lib/design-parser.js +237 -0
  74. package/server/lib/design-parser.test.js +290 -0
  75. package/server/lib/gemini-vision.js +377 -0
  76. package/server/lib/gemini-vision.test.js +282 -0
  77. package/server/lib/input-validator.js +360 -0
  78. package/server/lib/input-validator.test.js +295 -0
  79. package/server/lib/litellm-client.js +232 -0
  80. package/server/lib/litellm-client.test.js +267 -0
  81. package/server/lib/litellm-command.js +291 -0
  82. package/server/lib/litellm-command.test.js +260 -0
  83. package/server/lib/litellm-config.js +273 -0
  84. package/server/lib/litellm-config.test.js +212 -0
  85. package/server/lib/model-pricing.js +189 -0
  86. package/server/lib/model-pricing.test.js +178 -0
  87. package/server/lib/models-command.js +223 -0
  88. package/server/lib/models-command.test.js +193 -0
  89. package/server/lib/optimize-command.js +197 -0
  90. package/server/lib/optimize-command.test.js +193 -0
  91. package/server/lib/orchestration-integration.js +206 -0
  92. package/server/lib/orchestration-integration.test.js +235 -0
  93. package/server/lib/output-encoder.js +308 -0
  94. package/server/lib/output-encoder.test.js +312 -0
  95. package/server/lib/quality-evaluator.js +396 -0
  96. package/server/lib/quality-evaluator.test.js +337 -0
  97. package/server/lib/quality-gate-command.js +340 -0
  98. package/server/lib/quality-gate-command.test.js +321 -0
  99. package/server/lib/quality-gate-scorer.js +378 -0
  100. package/server/lib/quality-gate-scorer.test.js +376 -0
  101. package/server/lib/quality-history.js +265 -0
  102. package/server/lib/quality-history.test.js +359 -0
  103. package/server/lib/quality-presets.js +288 -0
  104. package/server/lib/quality-presets.test.js +269 -0
  105. package/server/lib/quality-retry.js +323 -0
  106. package/server/lib/quality-retry.test.js +325 -0
  107. package/server/lib/quality-thresholds.js +255 -0
  108. package/server/lib/quality-thresholds.test.js +237 -0
  109. package/server/lib/secure-auth.js +333 -0
  110. package/server/lib/secure-auth.test.js +288 -0
  111. package/server/lib/secure-code-command.js +540 -0
  112. package/server/lib/secure-code-command.test.js +309 -0
  113. package/server/lib/secure-errors.js +521 -0
  114. package/server/lib/secure-errors.test.js +298 -0
  115. package/server/lib/vision-command.js +372 -0
  116. package/server/lib/vision-command.test.js +255 -0
  117. package/server/lib/visual-command.js +350 -0
  118. package/server/lib/visual-command.test.js +256 -0
  119. package/server/lib/visual-testing.js +315 -0
  120. package/server/lib/visual-testing.test.js +357 -0
  121. package/server/package-lock.json +2 -2
  122. package/server/package.json +1 -1
@@ -0,0 +1,237 @@
1
+ /**
2
+ * Quality Thresholds Tests
3
+ *
4
+ * Tests for configurable quality thresholds per operation
5
+ */
6
+
7
+ const { describe, it, beforeEach } = require('node:test');
8
+ const assert = require('node:assert');
9
+
10
+ const {
11
+ createThresholds,
12
+ getThreshold,
13
+ getDimensionThreshold,
14
+ checkThreshold,
15
+ applyPreset,
16
+ saveThresholds,
17
+ loadThresholds,
18
+ PRESET_FAST,
19
+ PRESET_BALANCED,
20
+ PRESET_THOROUGH,
21
+ } = require('./quality-thresholds.js');
22
+
23
+ describe('Quality Thresholds', () => {
24
+ describe('createThresholds', () => {
25
+ it('creates thresholds with defaults', () => {
26
+ const thresholds = createThresholds();
27
+ assert.ok(thresholds);
28
+ assert.ok(thresholds.default >= 0);
29
+ });
30
+
31
+ it('accepts custom default threshold', () => {
32
+ const thresholds = createThresholds({ default: 80 });
33
+ assert.strictEqual(thresholds.default, 80);
34
+ });
35
+
36
+ it('accepts per-operation thresholds', () => {
37
+ const thresholds = createThresholds({
38
+ operations: {
39
+ 'code-gen': 85,
40
+ review: 90,
41
+ },
42
+ });
43
+ assert.strictEqual(thresholds.operations['code-gen'], 85);
44
+ assert.strictEqual(thresholds.operations.review, 90);
45
+ });
46
+ });
47
+
48
+ describe('getThreshold', () => {
49
+ it('returns operation threshold when set', () => {
50
+ const thresholds = createThresholds({
51
+ default: 70,
52
+ operations: { 'code-gen': 85 },
53
+ });
54
+ const threshold = getThreshold(thresholds, 'code-gen');
55
+ assert.strictEqual(threshold, 85);
56
+ });
57
+
58
+ it('falls back to default threshold', () => {
59
+ const thresholds = createThresholds({ default: 70 });
60
+ const threshold = getThreshold(thresholds, 'unknown-operation');
61
+ assert.strictEqual(threshold, 70);
62
+ });
63
+
64
+ it('returns default for null operation', () => {
65
+ const thresholds = createThresholds({ default: 75 });
66
+ const threshold = getThreshold(thresholds, null);
67
+ assert.strictEqual(threshold, 75);
68
+ });
69
+ });
70
+
71
+ describe('getDimensionThreshold', () => {
72
+ it('returns per-dimension threshold when set', () => {
73
+ const thresholds = createThresholds({
74
+ dimensions: {
75
+ style: 90,
76
+ correctness: 100,
77
+ },
78
+ });
79
+ const threshold = getDimensionThreshold(thresholds, 'style');
80
+ assert.strictEqual(threshold, 90);
81
+ });
82
+
83
+ it('falls back to default when dimension not set', () => {
84
+ const thresholds = createThresholds({ default: 70 });
85
+ const threshold = getDimensionThreshold(thresholds, 'documentation');
86
+ assert.strictEqual(threshold, 70);
87
+ });
88
+
89
+ it('returns operation-specific dimension threshold', () => {
90
+ const thresholds = createThresholds({
91
+ default: 70,
92
+ operations: {
93
+ 'code-gen': {
94
+ default: 80,
95
+ dimensions: { style: 95 },
96
+ },
97
+ },
98
+ });
99
+ const threshold = getDimensionThreshold(thresholds, 'style', 'code-gen');
100
+ assert.strictEqual(threshold, 95);
101
+ });
102
+ });
103
+
104
+ describe('checkThreshold', () => {
105
+ it('returns pass when score meets threshold', () => {
106
+ const thresholds = createThresholds({ default: 70 });
107
+ const result = checkThreshold(thresholds, { composite: 80 });
108
+ assert.strictEqual(result.pass, true);
109
+ });
110
+
111
+ it('returns fail when score below threshold', () => {
112
+ const thresholds = createThresholds({ default: 70 });
113
+ const result = checkThreshold(thresholds, { composite: 60 });
114
+ assert.strictEqual(result.pass, false);
115
+ });
116
+
117
+ it('returns which dimensions failed', () => {
118
+ const thresholds = createThresholds({
119
+ default: 70,
120
+ dimensions: { style: 80, correctness: 90 },
121
+ });
122
+ const scores = { style: 75, correctness: 85, documentation: 90 };
123
+ const result = checkThreshold(thresholds, scores);
124
+ assert.ok(result.failed);
125
+ assert.ok(result.failed.includes('style'));
126
+ assert.ok(result.failed.includes('correctness'));
127
+ assert.ok(!result.failed.includes('documentation'));
128
+ });
129
+
130
+ it('returns margin for each dimension', () => {
131
+ const thresholds = createThresholds({ default: 70 });
132
+ const scores = { style: 80, correctness: 60 };
133
+ const result = checkThreshold(thresholds, scores, { margins: true });
134
+ assert.ok(result.margins);
135
+ assert.strictEqual(result.margins.style, 10);
136
+ assert.strictEqual(result.margins.correctness, -10);
137
+ });
138
+
139
+ it('passes when exactly at threshold', () => {
140
+ const thresholds = createThresholds({ default: 70 });
141
+ const result = checkThreshold(thresholds, { composite: 70 });
142
+ assert.strictEqual(result.pass, true);
143
+ });
144
+ });
145
+
146
+ describe('applyPreset', () => {
147
+ it('applies fast preset with lower thresholds', () => {
148
+ const thresholds = applyPreset(PRESET_FAST);
149
+ assert.ok(thresholds.default <= 60);
150
+ });
151
+
152
+ it('applies balanced preset with moderate thresholds', () => {
153
+ const thresholds = applyPreset(PRESET_BALANCED);
154
+ assert.ok(thresholds.default >= 65 && thresholds.default <= 80);
155
+ });
156
+
157
+ it('applies thorough preset with higher thresholds', () => {
158
+ const thresholds = applyPreset(PRESET_THOROUGH);
159
+ assert.ok(thresholds.default >= 80);
160
+ });
161
+
162
+ it('merges preset with custom overrides', () => {
163
+ const thresholds = applyPreset(PRESET_BALANCED, { default: 85 });
164
+ assert.strictEqual(thresholds.default, 85);
165
+ });
166
+
167
+ it('preserves preset name', () => {
168
+ const thresholds = applyPreset(PRESET_FAST);
169
+ assert.strictEqual(thresholds.preset, 'fast');
170
+ });
171
+ });
172
+
173
+ describe('presets', () => {
174
+ it('fast has lower thresholds than balanced', () => {
175
+ const fast = applyPreset(PRESET_FAST);
176
+ const balanced = applyPreset(PRESET_BALANCED);
177
+ assert.ok(fast.default < balanced.default);
178
+ });
179
+
180
+ it('balanced has lower thresholds than thorough', () => {
181
+ const balanced = applyPreset(PRESET_BALANCED);
182
+ const thorough = applyPreset(PRESET_THOROUGH);
183
+ assert.ok(balanced.default < thorough.default);
184
+ });
185
+
186
+ it('fast preset allows cheaper models', () => {
187
+ const fast = applyPreset(PRESET_FAST);
188
+ assert.ok(fast.allowedModels || fast.modelTier === 'basic');
189
+ });
190
+
191
+ it('thorough preset requires better models', () => {
192
+ const thorough = applyPreset(PRESET_THOROUGH);
193
+ assert.ok(thorough.modelTier === 'premium' || thorough.minModel);
194
+ });
195
+ });
196
+
197
+ describe('saveThresholds', () => {
198
+ it('persists thresholds to config', async () => {
199
+ const thresholds = createThresholds({ default: 85 });
200
+ let savedData = null;
201
+ const mockSave = async (data) => {
202
+ savedData = data;
203
+ };
204
+ await saveThresholds(thresholds, { save: mockSave });
205
+ assert.ok(savedData);
206
+ assert.strictEqual(savedData.default, 85);
207
+ });
208
+
209
+ it('returns success status', async () => {
210
+ const thresholds = createThresholds();
211
+ const result = await saveThresholds(thresholds, {
212
+ save: async () => {},
213
+ });
214
+ assert.strictEqual(result.success, true);
215
+ });
216
+ });
217
+
218
+ describe('loadThresholds', () => {
219
+ it('reads thresholds from config', async () => {
220
+ const mockLoad = async () => ({ default: 90 });
221
+ const thresholds = await loadThresholds({ load: mockLoad });
222
+ assert.strictEqual(thresholds.default, 90);
223
+ });
224
+
225
+ it('returns defaults when no config', async () => {
226
+ const mockLoad = async () => null;
227
+ const thresholds = await loadThresholds({ load: mockLoad });
228
+ assert.ok(thresholds.default >= 0);
229
+ });
230
+
231
+ it('validates loaded config', async () => {
232
+ const mockLoad = async () => ({ default: 'invalid' });
233
+ const thresholds = await loadThresholds({ load: mockLoad });
234
+ assert.ok(typeof thresholds.default === 'number');
235
+ });
236
+ });
237
+ });
@@ -0,0 +1,333 @@
1
+ /**
2
+ * Secure Auth Module
3
+ *
4
+ * Secure authentication patterns for code generation
5
+ */
6
+
7
+ /**
8
+ * Create a secure auth configuration
9
+ * @param {Object} options - Auth options
10
+ * @returns {Object} Auth configuration
11
+ */
12
+ function createSecureAuth(options = {}) {
13
+ return {
14
+ hashAlgorithm: options.hashAlgorithm || 'argon2id',
15
+ memoryCost: options.memoryCost || 65536,
16
+ timeCost: options.timeCost || 3,
17
+ parallelism: options.parallelism || 4,
18
+ };
19
+ }
20
+
21
+ /**
22
+ * Generate password hashing configuration
23
+ * @param {Object} options - Hashing options
24
+ * @returns {Object} Hashing configuration
25
+ */
26
+ function generatePasswordHash(options = {}) {
27
+ const algorithm = options.algorithm || 'argon2id';
28
+ const memoryCost = options.memoryCost || 65536;
29
+ const timeCost = options.timeCost || 3;
30
+ const parallelism = options.parallelism || 4;
31
+
32
+ const params = {
33
+ algorithm,
34
+ memoryCost,
35
+ timeCost,
36
+ parallelism,
37
+ };
38
+
39
+ let warning = null;
40
+ if (algorithm === 'bcrypt') {
41
+ warning = 'bcrypt is less secure than argon2id. Consider using argon2id as recommended by OWASP.';
42
+ }
43
+
44
+ const code = `
45
+ const argon2 = require('argon2');
46
+
47
+ async function hashPassword(password) {
48
+ return argon2.hash(password, {
49
+ type: argon2.argon2id,
50
+ memoryCost: ${memoryCost},
51
+ timeCost: ${timeCost},
52
+ parallelism: ${parallelism},
53
+ });
54
+ }`;
55
+
56
+ return {
57
+ params,
58
+ code,
59
+ warning,
60
+ };
61
+ }
62
+
63
+ /**
64
+ * Generate password verification code
65
+ * @param {Object} options - Verification options
66
+ * @returns {string} Generated code
67
+ */
68
+ function verifyPassword(options = {}) {
69
+ const { language = 'javascript' } = options;
70
+
71
+ if (language === 'javascript') {
72
+ return `
73
+ const argon2 = require('argon2');
74
+ const crypto = require('crypto');
75
+
76
+ async function verifyPassword(password, hash) {
77
+ try {
78
+ // Use argon2's built-in timing-safe comparison
79
+ const isValid = await argon2.verify(hash, password);
80
+ return isValid;
81
+ } catch (error) {
82
+ // Log error but don't expose details
83
+ console.error('Password verification error');
84
+ return false;
85
+ }
86
+ }`;
87
+ }
88
+
89
+ return '';
90
+ }
91
+
92
+ /**
93
+ * Generate rate limiter configuration
94
+ * @param {Object} options - Rate limiter options
95
+ * @returns {Object} Rate limiter configuration
96
+ */
97
+ function generateRateLimiter(options = {}) {
98
+ const {
99
+ type = 'sliding-window',
100
+ maxAttempts = 5,
101
+ windowMs = 60000,
102
+ keyBy = 'ip',
103
+ store = 'memory',
104
+ tokensPerInterval = 5,
105
+ } = options;
106
+
107
+ const code = store === 'redis'
108
+ ? `
109
+ const rateLimit = require('express-rate-limit');
110
+ const RedisStore = require('rate-limit-redis');
111
+
112
+ const limiter = rateLimit({
113
+ store: new RedisStore({ /* redis config */ }),
114
+ windowMs: ${windowMs},
115
+ max: ${maxAttempts},
116
+ keyGenerator: (req) => req.${keyBy},
117
+ message: 'Too many attempts, please try again later',
118
+ });`
119
+ : `
120
+ const rateLimit = require('express-rate-limit');
121
+
122
+ const limiter = rateLimit({
123
+ windowMs: ${windowMs},
124
+ max: ${maxAttempts},
125
+ keyGenerator: (req) => req.${keyBy},
126
+ message: 'Too many attempts, please try again later',
127
+ });`;
128
+
129
+ return {
130
+ type,
131
+ maxAttempts,
132
+ windowMs,
133
+ keyBy,
134
+ store,
135
+ tokensPerInterval,
136
+ code,
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Generate account lockout configuration
142
+ * @param {Object} options - Lockout options
143
+ * @returns {Object} Lockout configuration
144
+ */
145
+ function generateAccountLockout(options = {}) {
146
+ const {
147
+ maxAttempts = 5,
148
+ lockoutDuration = 900000,
149
+ progressive = false,
150
+ baseDelay = 60000,
151
+ notifyOnLockout = false,
152
+ unlockMethod = 'time',
153
+ auditLog = false,
154
+ } = options;
155
+
156
+ const code = `
157
+ class AccountLockout {
158
+ constructor() {
159
+ this.attempts = new Map();
160
+ this.locked = new Map();
161
+ }
162
+
163
+ async recordFailure(userId) {
164
+ const current = this.attempts.get(userId) || 0;
165
+ const newCount = current + 1;
166
+ this.attempts.set(userId, newCount);
167
+
168
+ if (newCount >= ${maxAttempts}) {
169
+ this.locked.set(userId, Date.now() + ${lockoutDuration});
170
+ ${auditLog ? 'await this.logLockout(userId);' : ''}
171
+ ${notifyOnLockout ? 'await this.notifyUser(userId);' : ''}
172
+ }
173
+ }
174
+
175
+ isLocked(userId) {
176
+ const lockUntil = this.locked.get(userId);
177
+ if (!lockUntil) return false;
178
+ if (Date.now() > lockUntil) {
179
+ this.locked.delete(userId);
180
+ this.attempts.delete(userId);
181
+ return false;
182
+ }
183
+ return true;
184
+ }
185
+ }`;
186
+
187
+ return {
188
+ maxAttempts,
189
+ lockoutDuration,
190
+ progressive,
191
+ baseDelay,
192
+ notifyOnLockout,
193
+ unlockMethod,
194
+ auditLog,
195
+ code,
196
+ };
197
+ }
198
+
199
+ /**
200
+ * Generate secure session configuration
201
+ * @param {Object} options - Session options
202
+ * @returns {Object} Session configuration
203
+ */
204
+ function generateSessionConfig(options = {}) {
205
+ const { maxAge = 3600000, regenerateOnLogin = true } = options;
206
+
207
+ const cookie = {
208
+ httpOnly: true,
209
+ secure: true,
210
+ sameSite: 'strict',
211
+ maxAge,
212
+ };
213
+
214
+ const code = `
215
+ const crypto = require('crypto');
216
+ const session = require('express-session');
217
+
218
+ app.use(session({
219
+ secret: process.env.SESSION_SECRET,
220
+ resave: false,
221
+ saveUninitialized: false,
222
+ cookie: {
223
+ httpOnly: true,
224
+ secure: true,
225
+ sameSite: 'strict',
226
+ maxAge: ${maxAge},
227
+ },
228
+ genid: () => crypto.randomBytes(32).toString('hex'),
229
+ }));
230
+
231
+ // Regenerate session on login
232
+ async function loginUser(req, user) {
233
+ return new Promise((resolve, reject) => {
234
+ req.session.regenerate((err) => {
235
+ if (err) return reject(err);
236
+ req.session.userId = user.id;
237
+ resolve();
238
+ });
239
+ });
240
+ }`;
241
+
242
+ return {
243
+ cookie,
244
+ regenerateOnLogin,
245
+ code,
246
+ };
247
+ }
248
+
249
+ /**
250
+ * Generate complete auth module code
251
+ * @param {Object} options - Generation options
252
+ * @returns {string} Generated code
253
+ */
254
+ function generateAuthCode(options = {}) {
255
+ const { language = 'javascript', features = [], owaspCompliant = false } = options;
256
+
257
+ if (language === 'typescript') {
258
+ return `
259
+ interface AuthConfig {
260
+ maxAttempts: number;
261
+ lockoutDuration: number;
262
+ }
263
+
264
+ interface AuthResult {
265
+ success: boolean;
266
+ error?: string;
267
+ }
268
+
269
+ async function hashPassword(password: string): Promise<string> {
270
+ // Use argon2id
271
+ return hash;
272
+ }
273
+
274
+ async function verifyPassword(password: string, hash: string): Promise<boolean> {
275
+ return verified;
276
+ }`;
277
+ }
278
+
279
+ if (language === 'python') {
280
+ return `
281
+ import argon2
282
+ from functools import wraps
283
+
284
+ def hash_password(password: str) -> str:
285
+ ph = argon2.PasswordHasher()
286
+ return ph.hash(password)
287
+
288
+ def verify_password(password: str, hash: str) -> bool:
289
+ ph = argon2.PasswordHasher()
290
+ try:
291
+ return ph.verify(hash, password)
292
+ except argon2.exceptions.VerifyMismatchError:
293
+ return False`;
294
+ }
295
+
296
+ // JavaScript
297
+ return `
298
+ const argon2 = require('argon2');
299
+ const crypto = require('crypto');
300
+
301
+ async function hashPassword(password) {
302
+ return argon2.hash(password, {
303
+ type: argon2.argon2id,
304
+ memoryCost: 65536,
305
+ timeCost: 3,
306
+ parallelism: 4,
307
+ });
308
+ }
309
+
310
+ async function verifyPassword(password, hash) {
311
+ try {
312
+ return await argon2.verify(hash, password);
313
+ } catch (error) {
314
+ return false;
315
+ }
316
+ }
317
+
318
+ function generateSecureToken(length = 32) {
319
+ return crypto.randomBytes(length).toString('hex');
320
+ }
321
+
322
+ module.exports = { hashPassword, verifyPassword, generateSecureToken };`;
323
+ }
324
+
325
+ module.exports = {
326
+ createSecureAuth,
327
+ generatePasswordHash,
328
+ verifyPassword,
329
+ generateRateLimiter,
330
+ generateAccountLockout,
331
+ generateSessionConfig,
332
+ generateAuthCode,
333
+ };