aiwf 0.3.21 → 0.3.23
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/package.json +3 -2
- package/src/cli/index.js +39 -336
- package/src/lib/installer.js +310 -90
- package/src/utils/messages.js +24 -0
- package/src/DEPENDENCY_MAP.md +0 -90
- package/src/cli/cache-cli.js +0 -459
- package/src/cli/checkpoint-cli.js +0 -417
- package/src/cli/language-cli.js +0 -286
- package/src/cli/sprint-cli.js +0 -287
- package/src/commands/ai-tool.js +0 -383
- package/src/commands/compress.js +0 -60
- package/src/commands/create-project.js +0 -160
- package/src/commands/evaluate.js +0 -459
- package/src/commands/persona.js +0 -309
- package/src/commands/sprint-task.js +0 -262
- package/src/commands/token.js +0 -312
- package/src/lib/ai-persona-manager.js +0 -711
- package/src/lib/cache-system.js +0 -332
- package/src/lib/context-engine.js +0 -568
- package/src/lib/github-integration.js +0 -402
- package/src/lib/memory-profiler.js +0 -471
- package/src/lib/metrics-collector.js +0 -885
- package/src/lib/offline-detector.js +0 -386
- package/src/lib/resource-loader-enhanced.js +0 -399
- package/src/lib/resource-loader.js +0 -250
- package/src/lib/resources/commands/ai-persona.js +0 -602
- package/src/lib/resources/commands/compress-context.js +0 -389
- package/src/lib/resources/commands/evaluate.js +0 -246
- package/src/lib/resources/commands/persona-context-apply.js +0 -562
- package/src/lib/resources/commands/token-tracking.js +0 -443
- package/src/lib/resources/config/commit-patterns.js +0 -103
- package/src/lib/resources/config/language.json +0 -6
- package/src/lib/resources/personas/PERSONA_INDEX.md +0 -57
- package/src/lib/resources/personas/analyst.json +0 -44
- package/src/lib/resources/personas/architect/best_practices.md +0 -136
- package/src/lib/resources/personas/architect/knowledge_base.md +0 -377
- package/src/lib/resources/personas/architect.json +0 -44
- package/src/lib/resources/personas/backend/best_practices.md +0 -766
- package/src/lib/resources/personas/backend/knowledge_base.md +0 -1070
- package/src/lib/resources/personas/data_analyst/best_practices.md +0 -594
- package/src/lib/resources/personas/data_analyst/knowledge_base.md +0 -1057
- package/src/lib/resources/personas/developer.json +0 -44
- package/src/lib/resources/personas/developer.md +0 -37
- package/src/lib/resources/personas/evaluation_criteria.json +0 -137
- package/src/lib/resources/personas/frontend/best_practices.md +0 -445
- package/src/lib/resources/personas/frontend/knowledge_base.md +0 -729
- package/src/lib/resources/personas/persona-index.json +0 -31
- package/src/lib/resources/personas/reviewer.json +0 -44
- package/src/lib/resources/personas/security/best_practices.md +0 -307
- package/src/lib/resources/personas/security/knowledge_base.md +0 -498
- package/src/lib/resources/personas/tester.json +0 -44
- package/src/lib/resources/templates/README.md +0 -78
- package/src/lib/resources/templates/api-server/config.json +0 -64
- package/src/lib/resources/templates/api-server/template/.aiwf/config.json +0 -56
- package/src/lib/resources/templates/api-server/template/.aiwf/feature-ledger.json +0 -42
- package/src/lib/resources/templates/api-server/template/.aiwf/personas/backend-engineer.json +0 -40
- package/src/lib/resources/templates/api-server/template/.aiwf/scripts/cli.js +0 -111
- package/src/lib/resources/templates/api-server/template/.env.example +0 -29
- package/src/lib/resources/templates/api-server/template/.eslintrc.json +0 -23
- package/src/lib/resources/templates/api-server/template/README.md +0 -171
- package/src/lib/resources/templates/api-server/template/jest.config.js +0 -26
- package/src/lib/resources/templates/api-server/template/nodemon.json +0 -9
- package/src/lib/resources/templates/api-server/template/package.json +0 -61
- package/src/lib/resources/templates/api-server/template/src/app.ts +0 -60
- package/src/lib/resources/templates/api-server/template/src/config/swagger.ts +0 -38
- package/src/lib/resources/templates/api-server/template/src/controllers/aiwfController.ts +0 -54
- package/src/lib/resources/templates/api-server/template/src/controllers/authController.ts +0 -128
- package/src/lib/resources/templates/api-server/template/src/controllers/statusController.ts +0 -28
- package/src/lib/resources/templates/api-server/template/src/index.ts +0 -28
- package/src/lib/resources/templates/api-server/template/src/middleware/aiwfMiddleware.ts +0 -50
- package/src/lib/resources/templates/api-server/template/src/middleware/authMiddleware.ts +0 -41
- package/src/lib/resources/templates/api-server/template/src/middleware/errorHandler.ts +0 -42
- package/src/lib/resources/templates/api-server/template/src/middleware/notFoundHandler.ts +0 -14
- package/src/lib/resources/templates/api-server/template/src/middleware/requestLogger.ts +0 -20
- package/src/lib/resources/templates/api-server/template/src/routes/aiwf.ts +0 -31
- package/src/lib/resources/templates/api-server/template/src/routes/index.ts +0 -13
- package/src/lib/resources/templates/api-server/template/src/routes/v1/index.ts +0 -67
- package/src/lib/resources/templates/api-server/template/src/utils/logger.ts +0 -37
- package/src/lib/resources/templates/api-server/template/tests/app.test.ts +0 -40
- package/src/lib/resources/templates/api-server/template/tsconfig.json +0 -43
- package/src/lib/resources/templates/npm-library/config.json +0 -61
- package/src/lib/resources/templates/npm-library/template/LICENSE +0 -21
- package/src/lib/resources/templates/npm-library/template/README.md +0 -201
- package/src/lib/resources/templates/npm-library/template/package.json +0 -78
- package/src/lib/resources/templates/web-app/config.json +0 -53
- package/src/lib/resources/templates/web-app/template/.aiwf/config.json +0 -54
- package/src/lib/resources/templates/web-app/template/.aiwf/feature-ledger.json +0 -37
- package/src/lib/resources/templates/web-app/template/.aiwf/personas/fullstack-developer.json +0 -40
- package/src/lib/resources/templates/web-app/template/.aiwf/scripts/cli.js +0 -110
- package/src/lib/resources/templates/web-app/template/.eslintrc.cjs +0 -20
- package/src/lib/resources/templates/web-app/template/README.md +0 -151
- package/src/lib/resources/templates/web-app/template/index.html +0 -14
- package/src/lib/resources/templates/web-app/template/package.json +0 -44
- package/src/lib/resources/templates/web-app/template/postcss.config.js +0 -6
- package/src/lib/resources/templates/web-app/template/public/vite.svg +0 -1
- package/src/lib/resources/templates/web-app/template/src/App.tsx +0 -21
- package/src/lib/resources/templates/web-app/template/src/components/Layout.tsx +0 -57
- package/src/lib/resources/templates/web-app/template/src/components/aiwf/ContextStatus.tsx +0 -107
- package/src/lib/resources/templates/web-app/template/src/components/aiwf/TokenUsage.tsx +0 -71
- package/src/lib/resources/templates/web-app/template/src/index.css +0 -60
- package/src/lib/resources/templates/web-app/template/src/main.tsx +0 -10
- package/src/lib/resources/templates/web-app/template/src/pages/AiwfDashboard.tsx +0 -57
- package/src/lib/resources/templates/web-app/template/src/pages/HomePage.tsx +0 -89
- package/src/lib/resources/templates/web-app/template/src/pages/NotFound.tsx +0 -25
- package/src/lib/resources/templates/web-app/template/src/stores/aiwfStore.ts +0 -126
- package/src/lib/resources/templates/web-app/template/src/types/global.d.ts +0 -9
- package/src/lib/resources/templates/web-app/template/src/vite-env.d.ts +0 -1
- package/src/lib/resources/templates/web-app/template/tailwind.config.js +0 -30
- package/src/lib/resources/templates/web-app/template/tsconfig.json +0 -37
- package/src/lib/resources/templates/web-app/template/tsconfig.node.json +0 -10
- package/src/lib/resources/templates/web-app/template/vite.config.ts +0 -23
- package/src/lib/resources/utils/background-monitor.js +0 -223
- package/src/lib/resources/utils/compression-metrics.js +0 -1031
- package/src/lib/resources/utils/compression-strategies.js +0 -557
- package/src/lib/resources/utils/content-normalizer.js +0 -455
- package/src/lib/resources/utils/context-compressor.js +0 -583
- package/src/lib/resources/utils/context-rule-parser.js +0 -180
- package/src/lib/resources/utils/context-token-monitor.js +0 -463
- package/src/lib/resources/utils/context-update-manager.js +0 -502
- package/src/lib/resources/utils/git-utils.js +0 -220
- package/src/lib/resources/utils/importance-classifier.js +0 -645
- package/src/lib/resources/utils/information-filter.js +0 -710
- package/src/lib/resources/utils/persona-aware-compressor.js +0 -598
- package/src/lib/resources/utils/prompt-injector.js +0 -242
- package/src/lib/resources/utils/simplified-evaluator.js +0 -119
- package/src/lib/resources/utils/text-summarizer.js +0 -492
- package/src/lib/resources/utils/token-counter.js +0 -177
- package/src/lib/resources/utils/token-monitor.js +0 -484
- package/src/lib/resources/utils/token-reporter.js +0 -452
- package/src/lib/resources/utils/token-storage.js +0 -433
- package/src/lib/resources/utils/token-tracker.js +0 -283
- package/src/lib/state/priority-calculator.js +0 -217
- package/src/lib/state/state-index.js +0 -155
- package/src/lib/state/task-scanner.js +0 -328
- package/src/lib/task-analyzer.js +0 -599
- package/src/lib/template-cache-system.js +0 -559
- package/src/lib/template-downloader.js +0 -467
- package/src/lib/template-version-manager.js +0 -491
- package/src/lib/token-optimizer.js +0 -517
- package/src/utils/engineering-guard.js +0 -399
|
@@ -1,498 +0,0 @@
|
|
|
1
|
-
# Security 페르소나 Knowledge Base
|
|
2
|
-
|
|
3
|
-
## 보안 위협 백과사전
|
|
4
|
-
|
|
5
|
-
### 웹 애플리케이션 공격
|
|
6
|
-
|
|
7
|
-
#### 1. SQL Injection
|
|
8
|
-
```sql
|
|
9
|
-
-- 취약한 코드
|
|
10
|
-
SELECT * FROM users WHERE username = '$username' AND password = '$password';
|
|
11
|
-
|
|
12
|
-
-- 공격 예시
|
|
13
|
-
username: admin' OR '1'='1' --
|
|
14
|
-
password: anything
|
|
15
|
-
|
|
16
|
-
-- 방어 코드 (파라미터화된 쿼리)
|
|
17
|
-
const query = 'SELECT * FROM users WHERE username = ? AND password = ?';
|
|
18
|
-
db.query(query, [username, password]);
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
#### 2. Cross-Site Scripting (XSS)
|
|
22
|
-
```javascript
|
|
23
|
-
// 저장형 XSS 방어
|
|
24
|
-
function sanitizeUserInput(input) {
|
|
25
|
-
// DOMPurify 라이브러리 사용
|
|
26
|
-
return DOMPurify.sanitize(input, {
|
|
27
|
-
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
|
|
28
|
-
ALLOWED_ATTR: ['href']
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// 반사형 XSS 방어
|
|
33
|
-
function renderUserContent(content) {
|
|
34
|
-
const div = document.createElement('div');
|
|
35
|
-
div.textContent = content; // innerHTML 대신 textContent 사용
|
|
36
|
-
return div;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// CSP 헤더 설정
|
|
40
|
-
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}';
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
#### 3. Cross-Site Request Forgery (CSRF)
|
|
44
|
-
```javascript
|
|
45
|
-
// CSRF 토큰 생성
|
|
46
|
-
class CSRFProtection {
|
|
47
|
-
generateToken(sessionId) {
|
|
48
|
-
const token = crypto.randomBytes(32).toString('hex');
|
|
49
|
-
this.storeToken(sessionId, token);
|
|
50
|
-
return token;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
validateToken(sessionId, token) {
|
|
54
|
-
const storedToken = this.getToken(sessionId);
|
|
55
|
-
if (!storedToken || storedToken !== token) {
|
|
56
|
-
throw new SecurityError('Invalid CSRF token');
|
|
57
|
-
}
|
|
58
|
-
// 토큰 재생성 (일회용)
|
|
59
|
-
return this.generateToken(sessionId);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Double Submit Cookie Pattern
|
|
64
|
-
app.use((req, res, next) => {
|
|
65
|
-
const token = req.cookies.csrfToken || crypto.randomBytes(32).toString('hex');
|
|
66
|
-
res.cookie('csrfToken', token, { httpOnly: false, sameSite: 'strict' });
|
|
67
|
-
req.csrfToken = token;
|
|
68
|
-
next();
|
|
69
|
-
});
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### 인증 및 권한 관리
|
|
73
|
-
|
|
74
|
-
#### OAuth 2.0 구현
|
|
75
|
-
```javascript
|
|
76
|
-
class OAuth2Provider {
|
|
77
|
-
// Authorization Code Flow
|
|
78
|
-
async authorize(clientId, redirectUri, scope) {
|
|
79
|
-
// 1. 사용자 인증
|
|
80
|
-
const user = await this.authenticateUser();
|
|
81
|
-
|
|
82
|
-
// 2. 클라이언트 검증
|
|
83
|
-
const client = await this.validateClient(clientId, redirectUri);
|
|
84
|
-
|
|
85
|
-
// 3. 권한 부여 코드 생성
|
|
86
|
-
const code = crypto.randomBytes(32).toString('hex');
|
|
87
|
-
await this.storeAuthCode(code, {
|
|
88
|
-
clientId,
|
|
89
|
-
userId: user.id,
|
|
90
|
-
scope,
|
|
91
|
-
expiresAt: Date.now() + 600000 // 10분
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
return code;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Token Exchange
|
|
98
|
-
async exchangeToken(code, clientId, clientSecret) {
|
|
99
|
-
const authCode = await this.getAuthCode(code);
|
|
100
|
-
|
|
101
|
-
// 검증
|
|
102
|
-
if (!authCode || authCode.clientId !== clientId) {
|
|
103
|
-
throw new Error('Invalid authorization code');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (Date.now() > authCode.expiresAt) {
|
|
107
|
-
throw new Error('Authorization code expired');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// 토큰 생성
|
|
111
|
-
const accessToken = this.generateJWT(authCode.userId, authCode.scope);
|
|
112
|
-
const refreshToken = crypto.randomBytes(32).toString('hex');
|
|
113
|
-
|
|
114
|
-
await this.storeRefreshToken(refreshToken, authCode.userId);
|
|
115
|
-
await this.revokeAuthCode(code);
|
|
116
|
-
|
|
117
|
-
return { accessToken, refreshToken };
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
#### JWT 보안
|
|
123
|
-
```javascript
|
|
124
|
-
class SecureJWT {
|
|
125
|
-
constructor() {
|
|
126
|
-
this.algorithm = 'RS256'; // 비대칭 키 사용
|
|
127
|
-
this.issuer = 'secure-app';
|
|
128
|
-
this.audience = 'api.secure-app.com';
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
generateToken(payload) {
|
|
132
|
-
const token = jwt.sign(payload, this.privateKey, {
|
|
133
|
-
algorithm: this.algorithm,
|
|
134
|
-
expiresIn: '15m', // 짧은 만료 시간
|
|
135
|
-
issuer: this.issuer,
|
|
136
|
-
audience: this.audience,
|
|
137
|
-
jwtid: uuidv4() // 토큰 ID로 재사용 방지
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
return token;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
verifyToken(token) {
|
|
144
|
-
try {
|
|
145
|
-
const decoded = jwt.verify(token, this.publicKey, {
|
|
146
|
-
algorithms: [this.algorithm],
|
|
147
|
-
issuer: this.issuer,
|
|
148
|
-
audience: this.audience
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// 토큰 블랙리스트 확인
|
|
152
|
-
if (this.isBlacklisted(decoded.jti)) {
|
|
153
|
-
throw new Error('Token revoked');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return decoded;
|
|
157
|
-
} catch (error) {
|
|
158
|
-
throw new SecurityError('Invalid token: ' + error.message);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
### 암호화 알고리즘
|
|
165
|
-
|
|
166
|
-
#### 대칭키 암호화 (AES)
|
|
167
|
-
```javascript
|
|
168
|
-
class AESEncryption {
|
|
169
|
-
constructor(key) {
|
|
170
|
-
this.algorithm = 'aes-256-gcm';
|
|
171
|
-
this.key = Buffer.from(key, 'hex');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
encrypt(plaintext) {
|
|
175
|
-
const iv = crypto.randomBytes(16);
|
|
176
|
-
const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
|
|
177
|
-
|
|
178
|
-
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
|
|
179
|
-
encrypted += cipher.final('hex');
|
|
180
|
-
|
|
181
|
-
const authTag = cipher.getAuthTag();
|
|
182
|
-
|
|
183
|
-
return {
|
|
184
|
-
encrypted,
|
|
185
|
-
iv: iv.toString('hex'),
|
|
186
|
-
authTag: authTag.toString('hex')
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
decrypt(encryptedData) {
|
|
191
|
-
const decipher = crypto.createDecipheriv(
|
|
192
|
-
this.algorithm,
|
|
193
|
-
this.key,
|
|
194
|
-
Buffer.from(encryptedData.iv, 'hex')
|
|
195
|
-
);
|
|
196
|
-
|
|
197
|
-
decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex'));
|
|
198
|
-
|
|
199
|
-
let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
|
|
200
|
-
decrypted += decipher.final('utf8');
|
|
201
|
-
|
|
202
|
-
return decrypted;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
#### 비대칭키 암호화 (RSA)
|
|
208
|
-
```javascript
|
|
209
|
-
class RSAEncryption {
|
|
210
|
-
generateKeyPair() {
|
|
211
|
-
const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
|
|
212
|
-
modulusLength: 4096,
|
|
213
|
-
publicKeyEncoding: {
|
|
214
|
-
type: 'spki',
|
|
215
|
-
format: 'pem'
|
|
216
|
-
},
|
|
217
|
-
privateKeyEncoding: {
|
|
218
|
-
type: 'pkcs8',
|
|
219
|
-
format: 'pem',
|
|
220
|
-
cipher: 'aes-256-cbc',
|
|
221
|
-
passphrase: process.env.KEY_PASSPHRASE
|
|
222
|
-
}
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
return { publicKey, privateKey };
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
encrypt(data, publicKey) {
|
|
229
|
-
const buffer = Buffer.from(data, 'utf8');
|
|
230
|
-
const encrypted = crypto.publicEncrypt(
|
|
231
|
-
{
|
|
232
|
-
key: publicKey,
|
|
233
|
-
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
234
|
-
oaepHash: 'sha256'
|
|
235
|
-
},
|
|
236
|
-
buffer
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
return encrypted.toString('base64');
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
decrypt(encryptedData, privateKey) {
|
|
243
|
-
const buffer = Buffer.from(encryptedData, 'base64');
|
|
244
|
-
const decrypted = crypto.privateDecrypt(
|
|
245
|
-
{
|
|
246
|
-
key: privateKey,
|
|
247
|
-
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
|
|
248
|
-
oaepHash: 'sha256',
|
|
249
|
-
passphrase: process.env.KEY_PASSPHRASE
|
|
250
|
-
},
|
|
251
|
-
buffer
|
|
252
|
-
);
|
|
253
|
-
|
|
254
|
-
return decrypted.toString('utf8');
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### 네트워크 보안
|
|
260
|
-
|
|
261
|
-
#### TLS/SSL 설정
|
|
262
|
-
```javascript
|
|
263
|
-
// HTTPS 서버 설정
|
|
264
|
-
const https = require('https');
|
|
265
|
-
const tls = require('tls');
|
|
266
|
-
|
|
267
|
-
const options = {
|
|
268
|
-
key: fs.readFileSync('private-key.pem'),
|
|
269
|
-
cert: fs.readFileSync('certificate.pem'),
|
|
270
|
-
|
|
271
|
-
// 보안 강화 설정
|
|
272
|
-
secureOptions: tls.constants.SSL_OP_NO_TLSv1 |
|
|
273
|
-
tls.constants.SSL_OP_NO_TLSv1_1,
|
|
274
|
-
ciphers: [
|
|
275
|
-
'ECDHE-RSA-AES128-GCM-SHA256',
|
|
276
|
-
'ECDHE-RSA-AES256-GCM-SHA384',
|
|
277
|
-
'ECDHE-RSA-AES128-SHA256',
|
|
278
|
-
'ECDHE-RSA-AES256-SHA384'
|
|
279
|
-
].join(':'),
|
|
280
|
-
honorCipherOrder: true,
|
|
281
|
-
|
|
282
|
-
// HSTS
|
|
283
|
-
hsts: {
|
|
284
|
-
maxAge: 31536000,
|
|
285
|
-
includeSubDomains: true,
|
|
286
|
-
preload: true
|
|
287
|
-
}
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
https.createServer(options, app).listen(443);
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
#### 방화벽 규칙
|
|
294
|
-
```bash
|
|
295
|
-
# iptables 기본 정책
|
|
296
|
-
iptables -P INPUT DROP
|
|
297
|
-
iptables -P FORWARD DROP
|
|
298
|
-
iptables -P OUTPUT ACCEPT
|
|
299
|
-
|
|
300
|
-
# 필요한 포트만 열기
|
|
301
|
-
iptables -A INPUT -p tcp --dport 443 -j ACCEPT # HTTPS
|
|
302
|
-
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH (IP 제한 권장)
|
|
303
|
-
|
|
304
|
-
# DDoS 방어
|
|
305
|
-
iptables -A INPUT -p tcp --syn -m limit --limit 25/s --limit-burst 50 -j ACCEPT
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
### 보안 모니터링
|
|
309
|
-
|
|
310
|
-
#### 이상 탐지 시스템
|
|
311
|
-
```javascript
|
|
312
|
-
class AnomalyDetector {
|
|
313
|
-
constructor() {
|
|
314
|
-
this.baseline = new Map();
|
|
315
|
-
this.threshold = 2.5; // 표준편차 배수
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// 사용자 행동 분석
|
|
319
|
-
analyzeUserBehavior(userId, action) {
|
|
320
|
-
const userBaseline = this.baseline.get(userId) || {
|
|
321
|
-
loginTimes: [],
|
|
322
|
-
ipAddresses: new Set(),
|
|
323
|
-
requestRate: []
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
// 로그인 시간 이상 탐지
|
|
327
|
-
if (action.type === 'login') {
|
|
328
|
-
const hour = new Date(action.timestamp).getHours();
|
|
329
|
-
const avgHour = average(userBaseline.loginTimes);
|
|
330
|
-
const stdDev = standardDeviation(userBaseline.loginTimes);
|
|
331
|
-
|
|
332
|
-
if (Math.abs(hour - avgHour) > stdDev * this.threshold) {
|
|
333
|
-
this.alertSuspiciousLogin(userId, action);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
// IP 주소 변경 탐지
|
|
338
|
-
if (!userBaseline.ipAddresses.has(action.ipAddress)) {
|
|
339
|
-
this.alertNewLocation(userId, action);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// 요청 빈도 이상 탐지
|
|
343
|
-
const requestsPerMinute = this.calculateRequestRate(userId);
|
|
344
|
-
if (requestsPerMinute > userBaseline.avgRate * this.threshold) {
|
|
345
|
-
this.alertHighRequestRate(userId, requestsPerMinute);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
#### 보안 이벤트 상관 분석
|
|
352
|
-
```javascript
|
|
353
|
-
class SecurityEventCorrelator {
|
|
354
|
-
correlateEvents(events) {
|
|
355
|
-
const patterns = {
|
|
356
|
-
bruteForce: this.detectBruteForce(events),
|
|
357
|
-
privilegeEscalation: this.detectPrivilegeEscalation(events),
|
|
358
|
-
dataExfiltration: this.detectDataExfiltration(events),
|
|
359
|
-
lateralMovement: this.detectLateralMovement(events)
|
|
360
|
-
};
|
|
361
|
-
|
|
362
|
-
return patterns;
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
detectBruteForce(events) {
|
|
366
|
-
const failedLogins = events.filter(e =>
|
|
367
|
-
e.type === 'login_failed' &&
|
|
368
|
-
e.timestamp > Date.now() - 300000 // 5분
|
|
369
|
-
);
|
|
370
|
-
|
|
371
|
-
const attempts = {};
|
|
372
|
-
failedLogins.forEach(event => {
|
|
373
|
-
const key = `${event.username}:${event.ipAddress}`;
|
|
374
|
-
attempts[key] = (attempts[key] || 0) + 1;
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
return Object.entries(attempts)
|
|
378
|
-
.filter(([_, count]) => count > 5)
|
|
379
|
-
.map(([key, count]) => ({
|
|
380
|
-
type: 'brute_force',
|
|
381
|
-
target: key.split(':')[0],
|
|
382
|
-
source: key.split(':')[1],
|
|
383
|
-
attempts: count
|
|
384
|
-
}));
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
### 컴플라이언스 구현
|
|
390
|
-
|
|
391
|
-
#### GDPR 데이터 처리
|
|
392
|
-
```javascript
|
|
393
|
-
class GDPRCompliance {
|
|
394
|
-
// 동의 관리
|
|
395
|
-
async recordConsent(userId, purposes) {
|
|
396
|
-
const consent = {
|
|
397
|
-
userId,
|
|
398
|
-
purposes,
|
|
399
|
-
timestamp: new Date().toISOString(),
|
|
400
|
-
ipAddress: getClientIP(),
|
|
401
|
-
version: 'v1.2'
|
|
402
|
-
};
|
|
403
|
-
|
|
404
|
-
await this.store.saveConsent(consent);
|
|
405
|
-
return consent;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// 데이터 이동권
|
|
409
|
-
async exportUserData(userId) {
|
|
410
|
-
const data = {
|
|
411
|
-
profile: await this.getUserProfile(userId),
|
|
412
|
-
activities: await this.getUserActivities(userId),
|
|
413
|
-
preferences: await this.getUserPreferences(userId),
|
|
414
|
-
consents: await this.getUserConsents(userId)
|
|
415
|
-
};
|
|
416
|
-
|
|
417
|
-
// 민감한 정보 마스킹
|
|
418
|
-
data.profile = this.maskSensitiveData(data.profile);
|
|
419
|
-
|
|
420
|
-
return {
|
|
421
|
-
exportDate: new Date().toISOString(),
|
|
422
|
-
format: 'json',
|
|
423
|
-
data: data
|
|
424
|
-
};
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// 삭제권 (잊혀질 권리)
|
|
428
|
-
async deleteUserData(userId) {
|
|
429
|
-
// 감사 로그 생성
|
|
430
|
-
await this.auditLog.record({
|
|
431
|
-
action: 'user_data_deletion',
|
|
432
|
-
userId,
|
|
433
|
-
timestamp: new Date().toISOString(),
|
|
434
|
-
reason: 'GDPR Article 17 Request'
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
// 데이터 삭제 (보존 의무가 있는 데이터 제외)
|
|
438
|
-
await Promise.all([
|
|
439
|
-
this.deleteProfile(userId),
|
|
440
|
-
this.deleteActivities(userId),
|
|
441
|
-
this.deletePreferences(userId),
|
|
442
|
-
this.anonymizeTransactions(userId)
|
|
443
|
-
]);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
### 보안 테스트 자동화
|
|
449
|
-
|
|
450
|
-
#### 취약점 스캐닝 스크립트
|
|
451
|
-
```javascript
|
|
452
|
-
class SecurityScanner {
|
|
453
|
-
async runSecurityChecks() {
|
|
454
|
-
const results = {
|
|
455
|
-
timestamp: new Date().toISOString(),
|
|
456
|
-
vulnerabilities: []
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
// 의존성 취약점 검사
|
|
460
|
-
const npmAudit = await this.runNpmAudit();
|
|
461
|
-
results.vulnerabilities.push(...npmAudit);
|
|
462
|
-
|
|
463
|
-
// 보안 헤더 검사
|
|
464
|
-
const headers = await this.checkSecurityHeaders();
|
|
465
|
-
results.vulnerabilities.push(...headers);
|
|
466
|
-
|
|
467
|
-
// SSL/TLS 설정 검사
|
|
468
|
-
const ssl = await this.checkSSLConfiguration();
|
|
469
|
-
results.vulnerabilities.push(...ssl);
|
|
470
|
-
|
|
471
|
-
// 설정 파일 검사
|
|
472
|
-
const config = await this.checkConfigurationFiles();
|
|
473
|
-
results.vulnerabilities.push(...config);
|
|
474
|
-
|
|
475
|
-
return results;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
async checkSecurityHeaders() {
|
|
479
|
-
const requiredHeaders = [
|
|
480
|
-
'Strict-Transport-Security',
|
|
481
|
-
'X-Frame-Options',
|
|
482
|
-
'X-Content-Type-Options',
|
|
483
|
-
'Content-Security-Policy',
|
|
484
|
-
'X-XSS-Protection'
|
|
485
|
-
];
|
|
486
|
-
|
|
487
|
-
const response = await fetch(this.targetUrl);
|
|
488
|
-
const missing = requiredHeaders.filter(header =>
|
|
489
|
-
!response.headers.has(header)
|
|
490
|
-
);
|
|
491
|
-
|
|
492
|
-
return missing.map(header => ({
|
|
493
|
-
severity: 'medium',
|
|
494
|
-
type: 'missing_security_header',
|
|
495
|
-
details: `Missing header: ${header}`
|
|
496
|
-
}));
|
|
497
|
-
}
|
|
498
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "tester",
|
|
3
|
-
"name": "Quality Assurance Engineer",
|
|
4
|
-
"description": "Creates test scenarios, ensures quality, and validates functionality",
|
|
5
|
-
"focus_areas": [
|
|
6
|
-
"Test scenario creation",
|
|
7
|
-
"Edge case identification",
|
|
8
|
-
"Test automation",
|
|
9
|
-
"Quality metrics",
|
|
10
|
-
"User acceptance criteria"
|
|
11
|
-
],
|
|
12
|
-
"communication_style": {
|
|
13
|
-
"tone": "methodical, precise, detail-oriented",
|
|
14
|
-
"language": "clear test descriptions with expected outcomes",
|
|
15
|
-
"format": "test cases, bug reports, test plans"
|
|
16
|
-
},
|
|
17
|
-
"capabilities": [
|
|
18
|
-
"Design comprehensive test suites",
|
|
19
|
-
"Identify edge cases and corner cases",
|
|
20
|
-
"Create automated test scripts",
|
|
21
|
-
"Perform regression testing",
|
|
22
|
-
"Validate acceptance criteria"
|
|
23
|
-
],
|
|
24
|
-
"tools_and_methods": [
|
|
25
|
-
"Test-driven development",
|
|
26
|
-
"Behavior-driven development",
|
|
27
|
-
"Exploratory testing",
|
|
28
|
-
"Performance testing",
|
|
29
|
-
"Security testing"
|
|
30
|
-
],
|
|
31
|
-
"output_formats": [
|
|
32
|
-
"Test plans",
|
|
33
|
-
"Test cases",
|
|
34
|
-
"Bug reports",
|
|
35
|
-
"Test automation scripts",
|
|
36
|
-
"Quality reports"
|
|
37
|
-
],
|
|
38
|
-
"example_prompts": [
|
|
39
|
-
"Create test cases for the authentication feature",
|
|
40
|
-
"Design edge case scenarios for payment processing",
|
|
41
|
-
"Write automated tests for the user API",
|
|
42
|
-
"Perform security testing on the login flow"
|
|
43
|
-
]
|
|
44
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# AIWF 프로젝트 템플릿
|
|
2
|
-
|
|
3
|
-
이 디렉토리에는 AIWF 프로젝트 템플릿이 포함되어 있습니다.
|
|
4
|
-
|
|
5
|
-
## 사용 가능한 템플릿
|
|
6
|
-
|
|
7
|
-
### 1. web-app (웹 애플리케이션)
|
|
8
|
-
- React 18 + TypeScript
|
|
9
|
-
- Vite 빌드 도구
|
|
10
|
-
- Tailwind CSS
|
|
11
|
-
- React Router
|
|
12
|
-
- Zustand 상태 관리
|
|
13
|
-
- AIWF 대시보드 통합
|
|
14
|
-
|
|
15
|
-
### 2. api-server (API 서버)
|
|
16
|
-
- Express + TypeScript
|
|
17
|
-
- JWT 인증
|
|
18
|
-
- Swagger 문서화
|
|
19
|
-
- 에러 핸들링
|
|
20
|
-
- AIWF API 엔드포인트
|
|
21
|
-
|
|
22
|
-
### 3. npm-library (NPM 라이브러리)
|
|
23
|
-
- TypeScript 기반
|
|
24
|
-
- Rollup 번들링
|
|
25
|
-
- Jest 테스트
|
|
26
|
-
- 듀얼 모듈 시스템 (ESM/CJS)
|
|
27
|
-
- 자동 버전 관리
|
|
28
|
-
|
|
29
|
-
## 템플릿 사용법
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
# 대화형 모드
|
|
33
|
-
aiwf create
|
|
34
|
-
|
|
35
|
-
# 직접 지정
|
|
36
|
-
aiwf create web-app my-app
|
|
37
|
-
|
|
38
|
-
# 오프라인 모드
|
|
39
|
-
aiwf create --offline web-app my-app
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## 템플릿 구조
|
|
43
|
-
|
|
44
|
-
각 템플릿은 다음 구조를 따릅니다:
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
template-name/
|
|
48
|
-
├── config.json # 템플릿 메타데이터
|
|
49
|
-
└── template/ # 실제 프로젝트 파일
|
|
50
|
-
├── src/ # 소스 코드
|
|
51
|
-
├── .aiwf/ # AIWF 설정
|
|
52
|
-
├── package.json # 의존성
|
|
53
|
-
└── README.md # 프로젝트 문서
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
## 템플릿 커스터마이징
|
|
57
|
-
|
|
58
|
-
템플릿의 플레이스홀더:
|
|
59
|
-
- `{{projectName}}` - 프로젝트 이름
|
|
60
|
-
- `{{description}}` - 프로젝트 설명
|
|
61
|
-
- `{{author}}` - 작성자
|
|
62
|
-
- `{{year}}` - 현재 연도
|
|
63
|
-
- `{{createdAt}}` - 생성 시간
|
|
64
|
-
|
|
65
|
-
## 캐시 관리
|
|
66
|
-
|
|
67
|
-
템플릿은 오프라인 사용을 위해 캐시될 수 있습니다:
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
# 캐시 생성
|
|
71
|
-
aiwf cache create
|
|
72
|
-
|
|
73
|
-
# 캐시 확인
|
|
74
|
-
aiwf cache check
|
|
75
|
-
|
|
76
|
-
# 캐시 삭제
|
|
77
|
-
aiwf cache clear
|
|
78
|
-
```
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "api-server",
|
|
3
|
-
"displayName": "API 서버 (Node.js + Express)",
|
|
4
|
-
"description": "Express와 TypeScript로 구성된 RESTful API 서버 템플릿",
|
|
5
|
-
"type": "api-server",
|
|
6
|
-
"language": "typescript",
|
|
7
|
-
"framework": "express",
|
|
8
|
-
"features": [
|
|
9
|
-
"Express 4",
|
|
10
|
-
"TypeScript",
|
|
11
|
-
"JWT Authentication",
|
|
12
|
-
"Swagger Documentation",
|
|
13
|
-
"Database Ready",
|
|
14
|
-
"AIWF Integration",
|
|
15
|
-
"Error Handling",
|
|
16
|
-
"Request Validation"
|
|
17
|
-
],
|
|
18
|
-
"structure": {
|
|
19
|
-
"src": "소스 코드",
|
|
20
|
-
"tests": "테스트 파일",
|
|
21
|
-
".aiwf": "AIWF 설정 및 메타데이터",
|
|
22
|
-
"docs": "API 문서"
|
|
23
|
-
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"express": "^4.18.2",
|
|
26
|
-
"cors": "^2.8.5",
|
|
27
|
-
"helmet": "^7.0.0",
|
|
28
|
-
"compression": "^1.7.4",
|
|
29
|
-
"dotenv": "^16.3.1",
|
|
30
|
-
"jsonwebtoken": "^9.0.1",
|
|
31
|
-
"bcryptjs": "^2.4.3",
|
|
32
|
-
"express-validator": "^7.0.1",
|
|
33
|
-
"swagger-jsdoc": "^6.2.8",
|
|
34
|
-
"swagger-ui-express": "^5.0.0"
|
|
35
|
-
},
|
|
36
|
-
"devDependencies": {
|
|
37
|
-
"@types/express": "^4.17.17",
|
|
38
|
-
"@types/node": "^20.0.0",
|
|
39
|
-
"@types/cors": "^2.8.13",
|
|
40
|
-
"@types/compression": "^1.7.2",
|
|
41
|
-
"@types/jsonwebtoken": "^9.0.2",
|
|
42
|
-
"@types/bcryptjs": "^2.4.2",
|
|
43
|
-
"@types/swagger-jsdoc": "^6.0.1",
|
|
44
|
-
"@types/swagger-ui-express": "^4.1.3",
|
|
45
|
-
"@typescript-eslint/eslint-plugin": "^5.60.0",
|
|
46
|
-
"@typescript-eslint/parser": "^5.60.0",
|
|
47
|
-
"typescript": "^5.1.0",
|
|
48
|
-
"ts-node": "^10.9.0",
|
|
49
|
-
"nodemon": "^3.0.0",
|
|
50
|
-
"eslint": "^8.43.0",
|
|
51
|
-
"jest": "^29.5.0",
|
|
52
|
-
"@types/jest": "^29.5.0",
|
|
53
|
-
"supertest": "^6.3.0",
|
|
54
|
-
"@types/supertest": "^2.0.12"
|
|
55
|
-
},
|
|
56
|
-
"scripts": {
|
|
57
|
-
"dev": "nodemon",
|
|
58
|
-
"build": "tsc",
|
|
59
|
-
"start": "node dist/index.js",
|
|
60
|
-
"test": "jest",
|
|
61
|
-
"lint": "eslint . --ext .ts",
|
|
62
|
-
"aiwf": "node .aiwf/scripts/cli.js"
|
|
63
|
-
}
|
|
64
|
-
}
|