tlc-claude-code 1.4.7 → 1.4.9

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 (170) hide show
  1. package/docker-compose.dev.yml +6 -3
  2. package/package.json +1 -1
  3. package/server/index.js +229 -14
  4. package/server/lib/compliance/control-mapper.js +401 -0
  5. package/server/lib/compliance/control-mapper.test.js +117 -0
  6. package/server/lib/compliance/evidence-linker.js +296 -0
  7. package/server/lib/compliance/evidence-linker.test.js +121 -0
  8. package/server/lib/compliance/gdpr-checklist.js +416 -0
  9. package/server/lib/compliance/gdpr-checklist.test.js +131 -0
  10. package/server/lib/compliance/hipaa-checklist.js +277 -0
  11. package/server/lib/compliance/hipaa-checklist.test.js +101 -0
  12. package/server/lib/compliance/iso27001-checklist.js +287 -0
  13. package/server/lib/compliance/iso27001-checklist.test.js +99 -0
  14. package/server/lib/compliance/multi-framework-reporter.js +284 -0
  15. package/server/lib/compliance/multi-framework-reporter.test.js +127 -0
  16. package/server/lib/compliance/pci-dss-checklist.js +214 -0
  17. package/server/lib/compliance/pci-dss-checklist.test.js +95 -0
  18. package/server/lib/compliance/trust-centre.js +187 -0
  19. package/server/lib/compliance/trust-centre.test.js +93 -0
  20. package/server/lib/dashboard/api-server.js +155 -0
  21. package/server/lib/dashboard/api-server.test.js +155 -0
  22. package/server/lib/dashboard/health-api.js +199 -0
  23. package/server/lib/dashboard/health-api.test.js +122 -0
  24. package/server/lib/dashboard/notes-api.js +234 -0
  25. package/server/lib/dashboard/notes-api.test.js +134 -0
  26. package/server/lib/dashboard/router-api.js +176 -0
  27. package/server/lib/dashboard/router-api.test.js +132 -0
  28. package/server/lib/dashboard/tasks-api.js +289 -0
  29. package/server/lib/dashboard/tasks-api.test.js +161 -0
  30. package/server/lib/dashboard/tlc-introspection.js +197 -0
  31. package/server/lib/dashboard/tlc-introspection.test.js +138 -0
  32. package/server/lib/dashboard/version-api.js +222 -0
  33. package/server/lib/dashboard/version-api.test.js +112 -0
  34. package/server/lib/dashboard/websocket-server.js +104 -0
  35. package/server/lib/dashboard/websocket-server.test.js +118 -0
  36. package/server/lib/deploy/branch-classifier.js +163 -0
  37. package/server/lib/deploy/branch-classifier.test.js +164 -0
  38. package/server/lib/deploy/deployment-approval.js +299 -0
  39. package/server/lib/deploy/deployment-approval.test.js +296 -0
  40. package/server/lib/deploy/deployment-audit.js +374 -0
  41. package/server/lib/deploy/deployment-audit.test.js +307 -0
  42. package/server/lib/deploy/deployment-executor.js +335 -0
  43. package/server/lib/deploy/deployment-executor.test.js +329 -0
  44. package/server/lib/deploy/deployment-rules.js +163 -0
  45. package/server/lib/deploy/deployment-rules.test.js +188 -0
  46. package/server/lib/deploy/rollback-manager.js +379 -0
  47. package/server/lib/deploy/rollback-manager.test.js +321 -0
  48. package/server/lib/deploy/security-gates.js +236 -0
  49. package/server/lib/deploy/security-gates.test.js +222 -0
  50. package/server/lib/k8s/gitops-config.js +188 -0
  51. package/server/lib/k8s/gitops-config.test.js +59 -0
  52. package/server/lib/k8s/helm-generator.js +196 -0
  53. package/server/lib/k8s/helm-generator.test.js +59 -0
  54. package/server/lib/k8s/kustomize-generator.js +176 -0
  55. package/server/lib/k8s/kustomize-generator.test.js +58 -0
  56. package/server/lib/k8s/network-policy.js +114 -0
  57. package/server/lib/k8s/network-policy.test.js +53 -0
  58. package/server/lib/k8s/pod-security.js +114 -0
  59. package/server/lib/k8s/pod-security.test.js +55 -0
  60. package/server/lib/k8s/rbac-generator.js +132 -0
  61. package/server/lib/k8s/rbac-generator.test.js +57 -0
  62. package/server/lib/k8s/resource-manager.js +172 -0
  63. package/server/lib/k8s/resource-manager.test.js +60 -0
  64. package/server/lib/k8s/secrets-encryption.js +168 -0
  65. package/server/lib/k8s/secrets-encryption.test.js +49 -0
  66. package/server/lib/monitoring/alert-manager.js +238 -0
  67. package/server/lib/monitoring/alert-manager.test.js +106 -0
  68. package/server/lib/monitoring/health-check.js +226 -0
  69. package/server/lib/monitoring/health-check.test.js +176 -0
  70. package/server/lib/monitoring/incident-manager.js +230 -0
  71. package/server/lib/monitoring/incident-manager.test.js +98 -0
  72. package/server/lib/monitoring/log-aggregator.js +147 -0
  73. package/server/lib/monitoring/log-aggregator.test.js +89 -0
  74. package/server/lib/monitoring/metrics-collector.js +337 -0
  75. package/server/lib/monitoring/metrics-collector.test.js +172 -0
  76. package/server/lib/monitoring/status-page.js +214 -0
  77. package/server/lib/monitoring/status-page.test.js +105 -0
  78. package/server/lib/monitoring/uptime-monitor.js +194 -0
  79. package/server/lib/monitoring/uptime-monitor.test.js +109 -0
  80. package/server/lib/network/fail2ban-config.js +294 -0
  81. package/server/lib/network/fail2ban-config.test.js +275 -0
  82. package/server/lib/network/firewall-manager.js +252 -0
  83. package/server/lib/network/firewall-manager.test.js +254 -0
  84. package/server/lib/network/geoip-filter.js +282 -0
  85. package/server/lib/network/geoip-filter.test.js +264 -0
  86. package/server/lib/network/rate-limiter.js +229 -0
  87. package/server/lib/network/rate-limiter.test.js +293 -0
  88. package/server/lib/network/request-validator.js +351 -0
  89. package/server/lib/network/request-validator.test.js +345 -0
  90. package/server/lib/network/security-headers.js +251 -0
  91. package/server/lib/network/security-headers.test.js +283 -0
  92. package/server/lib/network/tls-config.js +210 -0
  93. package/server/lib/network/tls-config.test.js +248 -0
  94. package/server/lib/security/auth-security.js +369 -0
  95. package/server/lib/security/auth-security.test.js +448 -0
  96. package/server/lib/security/cis-benchmark.js +152 -0
  97. package/server/lib/security/cis-benchmark.test.js +137 -0
  98. package/server/lib/security/compose-templates.js +312 -0
  99. package/server/lib/security/compose-templates.test.js +229 -0
  100. package/server/lib/security/container-runtime.js +456 -0
  101. package/server/lib/security/container-runtime.test.js +503 -0
  102. package/server/lib/security/cors-validator.js +278 -0
  103. package/server/lib/security/cors-validator.test.js +310 -0
  104. package/server/lib/security/crypto-utils.js +253 -0
  105. package/server/lib/security/crypto-utils.test.js +409 -0
  106. package/server/lib/security/dockerfile-linter.js +459 -0
  107. package/server/lib/security/dockerfile-linter.test.js +483 -0
  108. package/server/lib/security/dockerfile-templates.js +278 -0
  109. package/server/lib/security/dockerfile-templates.test.js +164 -0
  110. package/server/lib/security/error-sanitizer.js +426 -0
  111. package/server/lib/security/error-sanitizer.test.js +331 -0
  112. package/server/lib/security/headers-generator.js +368 -0
  113. package/server/lib/security/headers-generator.test.js +398 -0
  114. package/server/lib/security/image-scanner.js +83 -0
  115. package/server/lib/security/image-scanner.test.js +106 -0
  116. package/server/lib/security/input-validator.js +352 -0
  117. package/server/lib/security/input-validator.test.js +330 -0
  118. package/server/lib/security/network-policy.js +174 -0
  119. package/server/lib/security/network-policy.test.js +164 -0
  120. package/server/lib/security/output-encoder.js +237 -0
  121. package/server/lib/security/output-encoder.test.js +276 -0
  122. package/server/lib/security/path-validator.js +359 -0
  123. package/server/lib/security/path-validator.test.js +293 -0
  124. package/server/lib/security/query-builder.js +421 -0
  125. package/server/lib/security/query-builder.test.js +318 -0
  126. package/server/lib/security/secret-detector.js +290 -0
  127. package/server/lib/security/secret-detector.test.js +354 -0
  128. package/server/lib/security/secrets-validator.js +137 -0
  129. package/server/lib/security/secrets-validator.test.js +120 -0
  130. package/server/lib/security-testing/dast-runner.js +154 -0
  131. package/server/lib/security-testing/dast-runner.test.js +62 -0
  132. package/server/lib/security-testing/dependency-scanner.js +172 -0
  133. package/server/lib/security-testing/dependency-scanner.test.js +64 -0
  134. package/server/lib/security-testing/pentest-runner.js +230 -0
  135. package/server/lib/security-testing/pentest-runner.test.js +60 -0
  136. package/server/lib/security-testing/sast-runner.js +136 -0
  137. package/server/lib/security-testing/sast-runner.test.js +62 -0
  138. package/server/lib/security-testing/secret-scanner.js +153 -0
  139. package/server/lib/security-testing/secret-scanner.test.js +66 -0
  140. package/server/lib/security-testing/security-gate.js +216 -0
  141. package/server/lib/security-testing/security-gate.test.js +115 -0
  142. package/server/lib/security-testing/security-reporter.js +303 -0
  143. package/server/lib/security-testing/security-reporter.test.js +114 -0
  144. package/server/lib/standards/audit-checker.js +546 -0
  145. package/server/lib/standards/audit-checker.test.js +415 -0
  146. package/server/lib/standards/cleanup-executor.js +452 -0
  147. package/server/lib/standards/cleanup-executor.test.js +293 -0
  148. package/server/lib/standards/refactor-stepper.js +425 -0
  149. package/server/lib/standards/refactor-stepper.test.js +298 -0
  150. package/server/lib/standards/standards-injector.js +167 -0
  151. package/server/lib/standards/standards-injector.test.js +232 -0
  152. package/server/lib/user-management.test.js +284 -0
  153. package/server/lib/vps/backup-manager.js +157 -0
  154. package/server/lib/vps/backup-manager.test.js +59 -0
  155. package/server/lib/vps/caddy-config.js +159 -0
  156. package/server/lib/vps/caddy-config.test.js +48 -0
  157. package/server/lib/vps/compose-orchestrator.js +219 -0
  158. package/server/lib/vps/compose-orchestrator.test.js +50 -0
  159. package/server/lib/vps/database-config.js +208 -0
  160. package/server/lib/vps/database-config.test.js +47 -0
  161. package/server/lib/vps/deploy-script.js +211 -0
  162. package/server/lib/vps/deploy-script.test.js +53 -0
  163. package/server/lib/vps/secrets-manager.js +148 -0
  164. package/server/lib/vps/secrets-manager.test.js +58 -0
  165. package/server/lib/vps/server-hardening.js +174 -0
  166. package/server/lib/vps/server-hardening.test.js +70 -0
  167. package/server/package-lock.json +19 -0
  168. package/server/package.json +1 -0
  169. package/server/templates/CLAUDE.md +37 -0
  170. package/server/templates/CODING-STANDARDS.md +408 -0
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Firewall Manager - UFW rules generation and management
3
+ */
4
+
5
+ /**
6
+ * UFW policy constants
7
+ */
8
+ export const UFW_POLICIES = {
9
+ ALLOW: 'allow',
10
+ DENY: 'deny',
11
+ REJECT: 'reject',
12
+ };
13
+
14
+ /**
15
+ * Generate UFW enable command
16
+ * @param {Object} options - Options
17
+ * @param {boolean} options.force - Include --force flag
18
+ * @returns {string} UFW enable command
19
+ */
20
+ export function generateUfwEnableCommand(options = {}) {
21
+ const { force = false } = options;
22
+ if (force) {
23
+ return 'ufw --force enable';
24
+ }
25
+ return 'ufw enable';
26
+ }
27
+
28
+ /**
29
+ * Set default policy
30
+ * @param {Object} options - Options
31
+ * @param {string} options.direction - 'incoming' or 'outgoing'
32
+ * @param {string} options.policy - 'allow', 'deny', or 'reject'
33
+ * @returns {string} UFW default policy command
34
+ */
35
+ export function setDefaultPolicy(options) {
36
+ const { direction, policy } = options;
37
+ return `ufw default ${policy} ${direction}`;
38
+ }
39
+
40
+ /**
41
+ * Generate allow rule for port
42
+ * @param {Object} options - Options
43
+ * @param {number|string} options.port - Port number, range, or service name
44
+ * @param {string} options.protocol - Protocol (tcp, udp)
45
+ * @returns {string} UFW allow rule
46
+ */
47
+ export function allowPort(options) {
48
+ const { port, protocol } = options;
49
+ if (protocol) {
50
+ return `ufw allow ${port}/${protocol}`;
51
+ }
52
+ return `ufw allow ${port}`;
53
+ }
54
+
55
+ /**
56
+ * Generate allow rule for IP
57
+ * @param {Object} options - Options
58
+ * @param {string} options.ip - IP address or CIDR range
59
+ * @param {number} options.port - Port number (optional)
60
+ * @returns {string} UFW allow from IP rule
61
+ */
62
+ export function allowFromIp(options) {
63
+ const { ip, port } = options;
64
+ if (port) {
65
+ return `ufw allow from ${ip} to any port ${port}`;
66
+ }
67
+ return `ufw allow from ${ip}`;
68
+ }
69
+
70
+ /**
71
+ * Generate deny rule for port
72
+ * @param {Object} options - Options
73
+ * @param {number|string} options.port - Port number
74
+ * @param {string} options.protocol - Protocol (tcp, udp)
75
+ * @returns {string} UFW deny rule
76
+ */
77
+ export function denyPort(options) {
78
+ const { port, protocol } = options;
79
+ if (protocol) {
80
+ return `ufw deny ${port}/${protocol}`;
81
+ }
82
+ return `ufw deny ${port}`;
83
+ }
84
+
85
+ /**
86
+ * Validate UFW rule syntax
87
+ * @param {string} rule - UFW rule to validate
88
+ * @returns {Object} Validation result with valid and error properties
89
+ */
90
+ export function validateRule(rule) {
91
+ // Check for port numbers
92
+ const portMatch = rule.match(/(?:port\s+|allow\s+|deny\s+)(\d+)/);
93
+ if (portMatch) {
94
+ const port = parseInt(portMatch[1], 10);
95
+ if (port < 1 || port > 65535) {
96
+ return { valid: false, error: 'Invalid port number' };
97
+ }
98
+ }
99
+
100
+ // Check for IP addresses
101
+ const ipMatch = rule.match(/from\s+([\d.]+(?:\/\d+)?)/);
102
+ if (ipMatch) {
103
+ const ipPart = ipMatch[1];
104
+ const [ip, cidr] = ipPart.split('/');
105
+
106
+ // Validate IP octets
107
+ const octets = ip.split('.');
108
+ if (octets.length !== 4) {
109
+ return { valid: false, error: 'Invalid IP address format' };
110
+ }
111
+
112
+ for (const octet of octets) {
113
+ const num = parseInt(octet, 10);
114
+ if (isNaN(num) || num < 0 || num > 255) {
115
+ return { valid: false, error: 'Invalid IP address' };
116
+ }
117
+ }
118
+
119
+ // Validate CIDR if present
120
+ if (cidr !== undefined) {
121
+ const cidrNum = parseInt(cidr, 10);
122
+ if (isNaN(cidrNum) || cidrNum < 0 || cidrNum > 32) {
123
+ return { valid: false, error: 'Invalid CIDR notation' };
124
+ }
125
+ }
126
+ }
127
+
128
+ return { valid: true };
129
+ }
130
+
131
+ /**
132
+ * Generate complete UFW rules configuration
133
+ * @param {Object} options - Options
134
+ * @param {number[]} options.allowPorts - Ports to allow
135
+ * @param {number} options.sshPort - SSH port
136
+ * @param {string[]} options.adminIps - Admin IP addresses
137
+ * @param {boolean} options.rateLimit - Enable rate limiting
138
+ * @param {string} options.format - Output format ('rules' or 'script')
139
+ * @returns {string} UFW rules or script
140
+ */
141
+ export function generateUfwRules(options) {
142
+ const {
143
+ allowPorts = [],
144
+ sshPort = 22,
145
+ adminIps = [],
146
+ rateLimit = false,
147
+ format = 'rules',
148
+ } = options;
149
+
150
+ const lines = [];
151
+
152
+ if (format === 'script') {
153
+ lines.push('#!/bin/bash');
154
+ lines.push('');
155
+ }
156
+
157
+ // Default policies
158
+ lines.push('ufw default deny incoming');
159
+ lines.push('ufw default allow outgoing');
160
+
161
+ // SSH rule
162
+ if (rateLimit) {
163
+ lines.push(`ufw limit ${sshPort}`);
164
+ } else {
165
+ lines.push(`ufw allow ${sshPort}`);
166
+ }
167
+
168
+ // Allowed ports
169
+ for (const port of allowPorts) {
170
+ lines.push(`ufw allow ${port}`);
171
+ }
172
+
173
+ // Admin IPs
174
+ for (const ip of adminIps) {
175
+ lines.push(`ufw allow from ${ip}`);
176
+ }
177
+
178
+ return lines.join('\n');
179
+ }
180
+
181
+ /**
182
+ * Create a firewall manager instance
183
+ * @param {Object} options - Initial options
184
+ * @returns {Object} Firewall manager object
185
+ */
186
+ export function createFirewallManager(options = {}) {
187
+ const { sshPort = 22 } = options;
188
+ const rules = [];
189
+
190
+ return {
191
+ /**
192
+ * Generate rules using the current configuration
193
+ */
194
+ generateRules(opts = {}) {
195
+ return generateUfwRules({ ...opts, sshPort });
196
+ },
197
+
198
+ /**
199
+ * Add an allow port rule
200
+ */
201
+ allowPort(opts) {
202
+ const rule = allowPort(opts);
203
+ rules.push(rule);
204
+ return rule;
205
+ },
206
+
207
+ /**
208
+ * Add a deny port rule
209
+ */
210
+ denyPort(opts) {
211
+ const rule = denyPort(opts);
212
+ rules.push(rule);
213
+ return rule;
214
+ },
215
+
216
+ /**
217
+ * Add an allow from IP rule
218
+ */
219
+ allowFromIp(opts) {
220
+ const rule = allowFromIp(opts);
221
+ rules.push(rule);
222
+ return rule;
223
+ },
224
+
225
+ /**
226
+ * Validate a rule
227
+ */
228
+ validate(rule) {
229
+ return validateRule(rule);
230
+ },
231
+
232
+ /**
233
+ * Get all added rules
234
+ */
235
+ getRules() {
236
+ return [...rules];
237
+ },
238
+
239
+ /**
240
+ * Generate complete configuration
241
+ */
242
+ generateConfig() {
243
+ const lines = [
244
+ 'ufw default deny incoming',
245
+ 'ufw default allow outgoing',
246
+ `ufw allow ${sshPort}`,
247
+ ...rules,
248
+ ];
249
+ return lines.join('\n');
250
+ },
251
+ };
252
+ }
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Firewall Manager Tests
3
+ */
4
+ import { describe, it, expect } from 'vitest';
5
+ import {
6
+ generateUfwRules,
7
+ generateUfwEnableCommand,
8
+ setDefaultPolicy,
9
+ allowPort,
10
+ allowFromIp,
11
+ denyPort,
12
+ validateRule,
13
+ UFW_POLICIES,
14
+ createFirewallManager,
15
+ } from './firewall-manager.js';
16
+
17
+ describe('firewall-manager', () => {
18
+ describe('UFW_POLICIES', () => {
19
+ it('defines policy constants', () => {
20
+ expect(UFW_POLICIES.ALLOW).toBe('allow');
21
+ expect(UFW_POLICIES.DENY).toBe('deny');
22
+ expect(UFW_POLICIES.REJECT).toBe('reject');
23
+ });
24
+ });
25
+
26
+ describe('generateUfwEnableCommand', () => {
27
+ it('generates enable command', () => {
28
+ const command = generateUfwEnableCommand();
29
+
30
+ expect(command).toContain('ufw');
31
+ expect(command).toContain('enable');
32
+ });
33
+
34
+ it('includes force flag', () => {
35
+ const command = generateUfwEnableCommand({ force: true });
36
+
37
+ expect(command).toContain('--force');
38
+ });
39
+ });
40
+
41
+ describe('setDefaultPolicy', () => {
42
+ it('sets default deny incoming', () => {
43
+ const command = setDefaultPolicy({
44
+ direction: 'incoming',
45
+ policy: 'deny',
46
+ });
47
+
48
+ expect(command).toContain('default deny incoming');
49
+ });
50
+
51
+ it('sets default allow outgoing', () => {
52
+ const command = setDefaultPolicy({
53
+ direction: 'outgoing',
54
+ policy: 'allow',
55
+ });
56
+
57
+ expect(command).toContain('default allow outgoing');
58
+ });
59
+ });
60
+
61
+ describe('allowPort', () => {
62
+ it('generates allow rule for port', () => {
63
+ const rule = allowPort({ port: 443 });
64
+
65
+ expect(rule).toContain('allow');
66
+ expect(rule).toContain('443');
67
+ });
68
+
69
+ it('supports protocol specification', () => {
70
+ const rule = allowPort({ port: 443, protocol: 'tcp' });
71
+
72
+ expect(rule).toContain('443/tcp');
73
+ });
74
+
75
+ it('supports port ranges', () => {
76
+ const rule = allowPort({ port: '3000:3010' });
77
+
78
+ expect(rule).toContain('3000:3010');
79
+ });
80
+
81
+ it('supports named services', () => {
82
+ const rule = allowPort({ port: 'ssh' });
83
+
84
+ expect(rule).toContain('ssh');
85
+ });
86
+ });
87
+
88
+ describe('allowFromIp', () => {
89
+ it('generates allow rule for IP', () => {
90
+ const rule = allowFromIp({
91
+ ip: '192.168.1.100',
92
+ port: 22,
93
+ });
94
+
95
+ expect(rule).toContain('from 192.168.1.100');
96
+ expect(rule).toContain('22');
97
+ });
98
+
99
+ it('supports CIDR notation', () => {
100
+ const rule = allowFromIp({
101
+ ip: '10.0.0.0/8',
102
+ port: 22,
103
+ });
104
+
105
+ expect(rule).toContain('from 10.0.0.0/8');
106
+ });
107
+
108
+ it('supports any destination', () => {
109
+ const rule = allowFromIp({
110
+ ip: '192.168.1.100',
111
+ });
112
+
113
+ expect(rule).toContain('from 192.168.1.100');
114
+ });
115
+ });
116
+
117
+ describe('denyPort', () => {
118
+ it('generates deny rule for port', () => {
119
+ const rule = denyPort({ port: 23 });
120
+
121
+ expect(rule).toContain('deny');
122
+ expect(rule).toContain('23');
123
+ });
124
+
125
+ it('supports protocol specification', () => {
126
+ const rule = denyPort({ port: 23, protocol: 'tcp' });
127
+
128
+ expect(rule).toContain('23/tcp');
129
+ });
130
+ });
131
+
132
+ describe('validateRule', () => {
133
+ it('validates correct rule syntax', () => {
134
+ const result = validateRule('ufw allow 443/tcp');
135
+
136
+ expect(result.valid).toBe(true);
137
+ });
138
+
139
+ it('rejects invalid port numbers', () => {
140
+ const result = validateRule('ufw allow 99999');
141
+
142
+ expect(result.valid).toBe(false);
143
+ expect(result.error).toContain('port');
144
+ });
145
+
146
+ it('rejects invalid IP addresses', () => {
147
+ const result = validateRule('ufw allow from 999.999.999.999');
148
+
149
+ expect(result.valid).toBe(false);
150
+ expect(result.error).toContain('IP');
151
+ });
152
+
153
+ it('validates CIDR notation', () => {
154
+ const validResult = validateRule('ufw allow from 10.0.0.0/8');
155
+ expect(validResult.valid).toBe(true);
156
+
157
+ const invalidResult = validateRule('ufw allow from 10.0.0.0/33');
158
+ expect(invalidResult.valid).toBe(false);
159
+ });
160
+ });
161
+
162
+ describe('generateUfwRules', () => {
163
+ it('generates complete UFW configuration', () => {
164
+ const rules = generateUfwRules({
165
+ allowPorts: [80, 443],
166
+ sshPort: 22,
167
+ });
168
+
169
+ expect(rules).toContain('default deny incoming');
170
+ expect(rules).toContain('default allow outgoing');
171
+ expect(rules).toContain('allow 80');
172
+ expect(rules).toContain('allow 443');
173
+ expect(rules).toContain('allow 22');
174
+ });
175
+
176
+ it('supports custom SSH port', () => {
177
+ const rules = generateUfwRules({
178
+ allowPorts: [80, 443],
179
+ sshPort: 2222,
180
+ });
181
+
182
+ expect(rules).toContain('allow 2222');
183
+ expect(rules).not.toContain('allow 22/tcp');
184
+ });
185
+
186
+ it('includes IP allowlist for admin', () => {
187
+ const rules = generateUfwRules({
188
+ allowPorts: [80, 443],
189
+ sshPort: 22,
190
+ adminIps: ['192.168.1.100', '10.0.0.50'],
191
+ });
192
+
193
+ expect(rules).toContain('from 192.168.1.100');
194
+ expect(rules).toContain('from 10.0.0.50');
195
+ });
196
+
197
+ it('supports rate limiting', () => {
198
+ const rules = generateUfwRules({
199
+ allowPorts: [80, 443],
200
+ sshPort: 22,
201
+ rateLimit: true,
202
+ });
203
+
204
+ expect(rules).toContain('limit');
205
+ });
206
+
207
+ it('generates script format', () => {
208
+ const rules = generateUfwRules({
209
+ allowPorts: [80, 443],
210
+ sshPort: 22,
211
+ format: 'script',
212
+ });
213
+
214
+ expect(rules).toContain('#!/bin/bash');
215
+ expect(rules).toContain('ufw');
216
+ });
217
+ });
218
+
219
+ describe('createFirewallManager', () => {
220
+ it('creates manager with methods', () => {
221
+ const manager = createFirewallManager();
222
+
223
+ expect(manager.generateRules).toBeDefined();
224
+ expect(manager.allowPort).toBeDefined();
225
+ expect(manager.denyPort).toBeDefined();
226
+ expect(manager.allowFromIp).toBeDefined();
227
+ expect(manager.validate).toBeDefined();
228
+ });
229
+
230
+ it('tracks added rules', () => {
231
+ const manager = createFirewallManager();
232
+
233
+ manager.allowPort({ port: 80 });
234
+ manager.allowPort({ port: 443 });
235
+
236
+ const rules = manager.getRules();
237
+ expect(rules.length).toBe(2);
238
+ });
239
+
240
+ it('generates complete config', () => {
241
+ const manager = createFirewallManager({
242
+ sshPort: 22,
243
+ });
244
+
245
+ manager.allowPort({ port: 80 });
246
+ manager.allowPort({ port: 443 });
247
+
248
+ const config = manager.generateConfig();
249
+ expect(config).toContain('80');
250
+ expect(config).toContain('443');
251
+ expect(config).toContain('22');
252
+ });
253
+ });
254
+ });