secure-coding-rules 2.0.0 → 2.0.1

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/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # secure-coding-rules
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/secure-coding-rules.svg)](https://www.npmjs.com/package/secure-coding-rules)
4
- [![license](https://img.shields.io/npm/l/secure-coding-rules.svg)](https://github.com/user/secure-coding-rules/blob/main/LICENSE)
4
+ [![license](https://img.shields.io/npm/l/secure-coding-rules.svg)](https://github.com/kwakseongjae/js-secure-coding-prompt-templates/blob/main/LICENSE)
5
5
  [![node](https://img.shields.io/node/v/secure-coding-rules.svg)](https://nodejs.org)
6
6
 
7
- **OWASP Top 10 2025** 기반 JavaScript/TypeScript 보안 코딩 룰을 AI 코딩 어시스턴트에 자동 적용하는 CLI 도구입니다.
7
+ Apply **OWASP Top 10 2025** JavaScript/TypeScript security rules to your AI coding assistant with one command.
8
8
 
9
- `npx secure-coding-rules` 줄이면 프로젝트의 CLAUDE.md, .cursor/rules, .windsurf/rules, copilot-instructions.md, AGENTS.md에 보안 룰이 적용됩니다.
9
+ Auto-generates security guidelines for CLAUDE.md, .cursor/rules, .windsurf/rules, copilot-instructions.md, and AGENTS.md.
10
10
 
11
11
  ---
12
12
 
@@ -16,107 +16,107 @@
16
16
  npx secure-coding-rules
17
17
  ```
18
18
 
19
- 인터랙티브 프롬프트:
20
- 1. AI 도구 선택 (Claude Code / Cursor / Windsurf / Copilot / AGENTS.md)
21
- 2. 프레임워크 선택 (React / Vue / Node.js / Vanilla) - **자동 감지됨**
22
- 3. 보안 카테고리 선택 (전체 또는 개별)
19
+ Interactive prompts:
20
+ 1. Select AI tool (Claude Code / Cursor / Windsurf / Copilot / AGENTS.md)
21
+ 2. Select framework (React / Vue / Node.js / Vanilla) - **auto-detected**
22
+ 3. Select security categories (all or individual)
23
23
 
24
24
  ### Auto Mode
25
25
 
26
- 프로젝트를 분석하여 자동으로 최적의 설정을 적용합니다:
26
+ Analyzes your project and applies optimal settings automatically:
27
27
 
28
28
  ```bash
29
29
  npx secure-coding-rules --yes
30
30
  ```
31
31
 
32
- - 기존 AI 도구 설정 파일이 있으면 자동 감지 후 업데이트
33
- - package.json에서 프레임워크 자동 감지 (React, Vue, Node.js )
34
- - CI/CD non-interactive 환경에서도 동작
32
+ - Auto-detects existing AI tool config files and updates them
33
+ - Auto-detects framework from package.json (React, Vue, Node.js, etc.)
34
+ - Works in CI/CD and other non-interactive environments
35
35
 
36
36
  ### Status Check
37
37
 
38
- 현재 프로젝트의 보안 상태만 확인:
38
+ Check current project security rule status:
39
39
 
40
40
  ```bash
41
41
  npx secure-coding-rules --check
42
42
  ```
43
43
 
44
- ## 지원 AI 도구
44
+ ## Supported AI Tools
45
45
 
46
- | AI Tool | Output | 기존 파일 |
47
- |---------|--------|----------|
48
- | **Claude Code** | `CLAUDE.md` | 자동 병합 |
49
- | **Cursor** | `.cursor/rules/*.mdc` | 개별 파일 생성 |
50
- | **Windsurf** | `.windsurf/rules/*.md` | 개별 파일 생성 |
51
- | **GitHub Copilot** | `.github/copilot-instructions.md` | 자동 병합 |
52
- | **AGENTS.md** | `AGENTS.md` | 자동 병합 |
46
+ | AI Tool | Output | Existing files |
47
+ |---------|--------|----------------|
48
+ | **Claude Code** | `CLAUDE.md` | Auto-merge |
49
+ | **Cursor** | `.cursor/rules/*.mdc` | Per-category files |
50
+ | **Windsurf** | `.windsurf/rules/*.md` | Per-category files |
51
+ | **GitHub Copilot** | `.github/copilot-instructions.md` | Auto-merge |
52
+ | **AGENTS.md** | `AGENTS.md` | Auto-merge |
53
53
 
54
- ## 보안 카테고리 (OWASP Top 10 2025)
54
+ ## Security Categories (OWASP Top 10 2025)
55
55
 
56
56
  | Code | Category | Description |
57
57
  |------|----------|-------------|
58
- | A01 | Broken Access Control | RBAC/ABAC, IDOR 방지, 서버사이드 인가 |
59
- | A02 | Security Misconfiguration | 보안 헤더, CORS, 환경변수 관리 |
60
- | A03 | Supply Chain Failures | npm audit, lockfile 무결성, SRI **(2025 신규)** |
61
- | A04 | Cryptographic Failures | 안전한 해싱, 암호화, 관리 |
58
+ | A01 | Broken Access Control | RBAC/ABAC, IDOR prevention, server-side authz |
59
+ | A02 | Security Misconfiguration | Security headers, CORS, env vars |
60
+ | A03 | Supply Chain Failures | npm audit, lockfile integrity, SRI **(New in 2025)** |
61
+ | A04 | Cryptographic Failures | Secure hashing, encryption, key management |
62
62
  | A05 | Injection | XSS, SQLi, NoSQLi, Command Injection |
63
- | A06 | Insecure Design | Threat modeling, 최소 권한 원칙 |
64
- | A07 | Authentication Failures | MFA, 세션 관리, 패스워드 정책 |
65
- | A08 | Data Integrity Failures | SRI, 안전한 역직렬화, CI/CD 보안 |
66
- | A09 | Logging & Alerting | 보안 로깅, 민감정보 마스킹, 알림 |
67
- | A10 | Error Handling | Fail-safe 기본값, 에러 정보 노출 방지 **(2025 신규)** |
63
+ | A06 | Insecure Design | Threat modeling, least privilege |
64
+ | A07 | Authentication Failures | MFA, session management, password policy |
65
+ | A08 | Data Integrity Failures | SRI, safe deserialization, CI/CD security |
66
+ | A09 | Logging & Alerting | Security logging, sensitive data masking |
67
+ | A10 | Error Handling | Fail-safe defaults, error info leakage **(New in 2025)** |
68
68
 
69
69
  ### Frontend Modules
70
70
 
71
71
  | Code | Category | Description |
72
72
  |------|----------|-------------|
73
- | FE-01 | XSS Prevention | DOM 조작 보안, sanitization |
74
- | FE-02 | CSRF Protection | 토큰 기반 방어, SameSite 쿠키 |
75
- | FE-03 | Content Security Policy | CSP 헤더, nonce, 리포팅 |
76
- | FE-04 | Secure State | 안전한 상태관리, 메모리 토큰 |
73
+ | FE-01 | XSS Prevention | Safe DOM manipulation, sanitization |
74
+ | FE-02 | CSRF Protection | Token-based defense, SameSite cookies |
75
+ | FE-03 | Content Security Policy | CSP headers, nonce, reporting |
76
+ | FE-04 | Secure State | Safe state management, in-memory tokens |
77
77
 
78
- ## 동작 방식
78
+ ## How It Works
79
79
 
80
- ### 형식
80
+ ### Rule Format
81
81
 
82
- 모든 보안 룰은 AI가 이해하기 쉬운 일관된 구조를 따릅니다:
82
+ All security rules follow a consistent, AI-friendly structure:
83
83
 
84
84
  ```markdown
85
85
  ### 1. Rule Title
86
- - **DO**: 구체적으로 해야
87
- - **DON'T**: 하지 말아야 할 것
88
- - **WHY**: 중요한지
86
+ - **DO**: What to do (specific instruction)
87
+ - **DON'T**: What to avoid
88
+ - **WHY**: Why it matters
89
89
 
90
90
  ## Code Examples
91
91
  ### Bad Practice / Good Practice
92
92
 
93
93
  ## Quick Checklist
94
- - [ ] 체크리스트 항목
94
+ - [ ] Checklist items
95
95
  ```
96
96
 
97
- ### 기존 파일 병합
97
+ ### File Merging
98
98
 
99
- 이미 CLAUDE.md 등이 있으면 기존 내용을 보존하고 보안 섹션만 추가/업데이트합니다:
99
+ If CLAUDE.md or other config files already exist, existing content is preserved and only the security section is added/updated:
100
100
 
101
101
  ```html
102
102
  <!-- js-secure-coding:start -->
103
- ( 영역만 업데이트됨)
103
+ (only this region is updated)
104
104
  <!-- js-secure-coding:end -->
105
105
  ```
106
106
 
107
- 다시 실행하면 해당 영역만 최신 버전으로 교체됩니다.
107
+ Re-running replaces only the marked region with the latest version.
108
108
 
109
- ### 프로젝트 자동 감지
109
+ ### Auto-Detection
110
110
 
111
- `secure-coding-rules`는 실행 현재 프로젝트를 분석합니다:
111
+ `secure-coding-rules` analyzes your project at runtime:
112
112
 
113
- - **AI 도구 감지**: CLAUDE.md, .cursor/, .windsurf/, .github/ 존재 여부 확인
114
- - **프레임워크 감지**: package.json dependencies에서 React/Vue/Express 등 파악
115
- - **상태 표시**: 인터랙티브 모드에서 감지 결과를 보여주고, 관련 항목을 우선 추천
113
+ - **AI tools**: Checks for CLAUDE.md, .cursor/, .windsurf/, .github/
114
+ - **Framework**: Reads package.json dependencies (React, Vue, Express, etc.)
115
+ - **Smart prompts**: Detected items are highlighted and prioritized in interactive mode
116
116
 
117
- ## 수동 사용
117
+ ## Manual Usage
118
118
 
119
- CLI 없이 `src/templates/` 마크다운 파일을 직접 복사하여 사용 가능합니다:
119
+ You can also copy markdown files from `src/templates/` directly without the CLI:
120
120
 
121
121
  ```
122
122
  src/templates/
@@ -141,18 +141,29 @@ src/templates/
141
141
  ## CLI Options
142
142
 
143
143
  ```
144
- npx secure-coding-rules 인터랙티브 모드 (자동 감지)
145
- npx secure-coding-rules --yes 스마트 기본값으로 자동 적용
146
- npx secure-coding-rules --check 프로젝트 보안 상태 확인
147
- npx secure-coding-rules --help 도움말
148
- npx secure-coding-rules --version 버전
144
+ npx secure-coding-rules Interactive mode (auto-detect)
145
+ npx secure-coding-rules --yes Smart defaults
146
+ npx secure-coding-rules --check Project security status
147
+ npx secure-coding-rules --dry-run Preview (no file writes)
148
+ npx secure-coding-rules --lang ko Run in Korean (한국어)
149
+ npx secure-coding-rules --help Help
150
+ npx secure-coding-rules --version Version
151
+ ```
152
+
153
+ ### Language / 다국어
154
+
155
+ Auto-detects system locale (`LANG` env). Override with `--lang`:
156
+
157
+ ```bash
158
+ npx secure-coding-rules --lang en # English (default)
159
+ npx secure-coding-rules --lang ko # 한국어
149
160
  ```
150
161
 
151
162
  ## Legacy Templates
152
163
 
153
- v1.0 원본 템플릿은 `legacy/` 디렉토리에 보존되어 있습니다.
164
+ Original v1.0 prompt templates are preserved in the `legacy/` directory.
154
165
 
155
- ## 참고 자료
166
+ ## References
156
167
 
157
168
  - [OWASP Top 10 2025](https://owasp.org/Top10/2025/)
158
169
  - [Node.js Security Best Practices](https://nodejs.org/en/learn/getting-started/security-best-practices)
@@ -161,7 +172,7 @@ v1.0 원본 템플릿은 `legacy/` 디렉토리에 보존되어 있습니다.
161
172
 
162
173
  ## Contributing
163
174
 
164
- PR을 환영합니다! 새로운 보안 룰, AI 도구 어댑터, 기존 내용 개선 등.
175
+ PRs welcome! New security rules, AI tool adapters, or improvements to existing content.
165
176
 
166
177
  ## License
167
178
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "secure-coding-rules",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "OWASP 2025 security rules for AI coding assistants. Auto-apply to CLAUDE.md, Cursor, Windsurf, Copilot, AGENTS.md with one command.",
5
5
  "main": "src/index.js",
6
6
  "exports": {
@@ -44,16 +44,16 @@
44
44
  ],
45
45
  "author": {
46
46
  "name": "Gwak Seong-jae",
47
- "url": "https://github.com/user"
47
+ "url": "https://github.com/kwakseongjae"
48
48
  },
49
49
  "license": "MIT",
50
50
  "repository": {
51
51
  "type": "git",
52
- "url": "git+https://github.com/user/secure-coding-rules.git"
52
+ "url": "git+https://github.com/kwakseongjae/js-secure-coding-prompt-templates.git"
53
53
  },
54
- "homepage": "https://github.com/user/secure-coding-rules#readme",
54
+ "homepage": "https://github.com/kwakseongjae/js-secure-coding-prompt-templates#readme",
55
55
  "bugs": {
56
- "url": "https://github.com/user/secure-coding-rules/issues"
56
+ "url": "https://github.com/kwakseongjae/js-secure-coding-prompt-templates/issues"
57
57
  },
58
58
  "engines": {
59
59
  "node": ">=18.0.0"
@@ -0,0 +1,201 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import * as claude from '../adapters/claude.js';
4
+ import * as copilot from '../adapters/copilot.js';
5
+ import * as agents from '../adapters/agents.js';
6
+ import * as cursor from '../adapters/cursor.js';
7
+ import * as windsurf from '../adapters/windsurf.js';
8
+
9
+ const MOCK_TEMPLATE = `# Test Security Rules
10
+
11
+ > OWASP Top 10 2025 - A01: Test
12
+
13
+ ## Rules
14
+
15
+ ### 1. Test Rule One
16
+ - **DO**: Do the right thing.
17
+ - **DON'T**: Do the wrong thing.
18
+ - **WHY**: Because security matters.
19
+
20
+ ### 2. Test Rule Two
21
+ - **DO**: Validate input.
22
+ - **DON'T**: Trust user data.
23
+ - **WHY**: Injection attacks are common.
24
+
25
+ ## Code Examples
26
+
27
+ ### Bad Practice
28
+ \`\`\`javascript
29
+ eval(userInput);
30
+ \`\`\`
31
+
32
+ ### Good Practice
33
+ \`\`\`javascript
34
+ sanitize(userInput);
35
+ \`\`\`
36
+
37
+ ## Quick Checklist
38
+ - [ ] Input validated
39
+ - [ ] Output encoded
40
+ `;
41
+
42
+ function mockTemplates() {
43
+ return new Map([['access-control', MOCK_TEMPLATE]]);
44
+ }
45
+
46
+ describe('claude adapter', () => {
47
+ it('formats templates with markers', () => {
48
+ const output = claude.format(mockTemplates());
49
+ assert.ok(output.includes('<!-- js-secure-coding:start -->'));
50
+ assert.ok(output.includes('<!-- js-secure-coding:end -->'));
51
+ assert.ok(output.includes('A01: Broken Access Control'));
52
+ });
53
+
54
+ it('extracts Rules and Checklist, not Code Examples', () => {
55
+ const output = claude.format(mockTemplates());
56
+ assert.ok(output.includes('Test Rule One'));
57
+ assert.ok(output.includes('Input validated'));
58
+ assert.ok(!output.includes('eval(userInput)'));
59
+ });
60
+
61
+ it('merges into existing content', () => {
62
+ const existing = '# My Project\n\nSome content here.';
63
+ const section = claude.format(mockTemplates());
64
+ const merged = claude.merge(existing, section);
65
+ assert.ok(merged.startsWith('# My Project'));
66
+ assert.ok(merged.includes('<!-- js-secure-coding:start -->'));
67
+ });
68
+
69
+ it('replaces existing section on re-merge', () => {
70
+ const first = claude.format(mockTemplates());
71
+ const existing = `# Project\n\n${first}\n\n# Other stuff`;
72
+ const newSection = claude.format(mockTemplates(), { framework: 'react' });
73
+ const merged = claude.merge(existing, newSection);
74
+
75
+ const starts = merged.match(/<!-- js-secure-coding:start -->/g);
76
+ assert.equal(starts.length, 1, 'Should have exactly one start marker');
77
+ assert.ok(merged.includes('Framework: react'));
78
+ assert.ok(merged.includes('# Other stuff'));
79
+ });
80
+
81
+ it('handles empty file append without leading whitespace', () => {
82
+ const merged = claude.merge('', claude.format(mockTemplates()));
83
+ assert.ok(!merged.startsWith('\n'));
84
+ });
85
+ });
86
+
87
+ describe('copilot adapter', () => {
88
+ it('formats with correct markers', () => {
89
+ const output = copilot.format(mockTemplates());
90
+ assert.ok(output.includes('<!-- js-secure-coding:start -->'));
91
+ assert.ok(output.includes('Security Coding Guidelines'));
92
+ });
93
+
94
+ it('extracts DO, DONT, and WHY rules', () => {
95
+ const output = copilot.format(mockTemplates());
96
+ assert.ok(output.includes('**DO**'));
97
+ assert.ok(output.includes("**DON'T**"));
98
+ assert.ok(output.includes('**WHY**'));
99
+ });
100
+
101
+ it('handles empty file merge', () => {
102
+ const merged = copilot.merge('', copilot.format(mockTemplates()));
103
+ assert.ok(!merged.startsWith('\n'));
104
+ });
105
+ });
106
+
107
+ describe('agents adapter', () => {
108
+ it('formats with markers and title', () => {
109
+ const output = agents.format(mockTemplates());
110
+ assert.ok(output.includes('# Security Guidelines'));
111
+ assert.ok(output.includes('<!-- js-secure-coding:start -->'));
112
+ });
113
+
114
+ it('strips original title from template', () => {
115
+ const output = agents.format(mockTemplates());
116
+ assert.ok(!output.includes('# Test Security Rules'));
117
+ });
118
+
119
+ it('handles empty file merge', () => {
120
+ const merged = agents.merge('', agents.format(mockTemplates()));
121
+ assert.ok(!merged.startsWith('\n'));
122
+ });
123
+ });
124
+
125
+ describe('claude adapter - directory mode', () => {
126
+ it('generates individual rule files via formatMultiple', () => {
127
+ const files = claude.formatMultiple(mockTemplates());
128
+ assert.equal(files.size, 1);
129
+ assert.ok(files.has('security-access-control.md'));
130
+ });
131
+
132
+ it('has rulesDir defined', () => {
133
+ assert.equal(claude.rulesDir, '.claude/rules');
134
+ });
135
+
136
+ it('generates reference text via formatReference', () => {
137
+ const ref = claude.formatReference(['access-control', 'injection']);
138
+ assert.ok(ref.includes('<!-- js-secure-coding:start -->'));
139
+ assert.ok(ref.includes('.claude/rules/'));
140
+ assert.ok(ref.includes('security-access-control.md'));
141
+ assert.ok(ref.includes('security-injection.md'));
142
+ assert.ok(ref.includes('A01'));
143
+ assert.ok(ref.includes('A05'));
144
+ });
145
+
146
+ it('reference can be merged into existing CLAUDE.md', () => {
147
+ const existing = '# My Project\n\nSome content.';
148
+ const ref = claude.formatReference(['access-control']);
149
+ const merged = claude.merge(existing, ref);
150
+ assert.ok(merged.startsWith('# My Project'));
151
+ assert.ok(merged.includes('.claude/rules/'));
152
+ });
153
+ });
154
+
155
+ describe('copilot adapter - directory mode', () => {
156
+ it('generates individual rule files via formatMultiple', () => {
157
+ const files = copilot.formatMultiple(mockTemplates());
158
+ assert.equal(files.size, 1);
159
+ assert.ok(files.has('security-access-control.md'));
160
+ });
161
+
162
+ it('has rulesDir defined', () => {
163
+ assert.equal(copilot.rulesDir, '.github/instructions');
164
+ });
165
+
166
+ it('generates reference text via formatReference', () => {
167
+ const ref = copilot.formatReference(['access-control']);
168
+ assert.ok(ref.includes('.github/instructions/'));
169
+ assert.ok(ref.includes('security-access-control.md'));
170
+ });
171
+ });
172
+
173
+ describe('cursor adapter', () => {
174
+ it('generates multiple .mdc files', () => {
175
+ const files = cursor.formatMultiple(mockTemplates());
176
+ assert.equal(files.size, 1);
177
+ assert.ok(files.has('security-access-control.mdc'));
178
+ });
179
+
180
+ it('includes frontmatter with description', () => {
181
+ const files = cursor.formatMultiple(mockTemplates());
182
+ const content = files.get('security-access-control.mdc');
183
+ assert.ok(content.startsWith('---'));
184
+ assert.ok(content.includes('description:'));
185
+ });
186
+ });
187
+
188
+ describe('windsurf adapter', () => {
189
+ it('generates multiple .md files', () => {
190
+ const files = windsurf.formatMultiple(mockTemplates());
191
+ assert.equal(files.size, 1);
192
+ assert.ok(files.has('security-access-control.md'));
193
+ });
194
+
195
+ it('strips original title and adds own', () => {
196
+ const files = windsurf.formatMultiple(mockTemplates());
197
+ const content = files.get('security-access-control.md');
198
+ assert.ok(content.startsWith('# A01: Broken Access Control'));
199
+ assert.ok(!content.includes('# Test Security Rules'));
200
+ });
201
+ });
@@ -0,0 +1,68 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { loadTemplate, loadTemplates, getCategoryInfo } from '../loader.js';
4
+
5
+ describe('loader', () => {
6
+ describe('loadTemplate', () => {
7
+ it('loads a core template', async () => {
8
+ const content = await loadTemplate('access-control');
9
+ assert.ok(content);
10
+ assert.ok(content.includes('## Rules'));
11
+ assert.ok(content.includes('## Quick Checklist'));
12
+ });
13
+
14
+ it('loads a frontend template', async () => {
15
+ const content = await loadTemplate('xss-prevention');
16
+ assert.ok(content);
17
+ assert.ok(content.includes('## Rules'));
18
+ });
19
+
20
+ it('returns null for unknown category', async () => {
21
+ const content = await loadTemplate('nonexistent-category');
22
+ assert.equal(content, null);
23
+ });
24
+ });
25
+
26
+ describe('loadTemplates', () => {
27
+ it('loads multiple templates', async () => {
28
+ const templates = await loadTemplates(['access-control', 'injection']);
29
+ assert.equal(templates.size, 2);
30
+ assert.ok(templates.has('access-control'));
31
+ assert.ok(templates.has('injection'));
32
+ });
33
+
34
+ it('loads all 14 templates', async () => {
35
+ const all = [
36
+ 'access-control', 'security-config', 'supply-chain', 'cryptographic',
37
+ 'injection', 'secure-design', 'authentication', 'data-integrity',
38
+ 'logging-alerting', 'error-handling', 'xss-prevention',
39
+ 'csrf-protection', 'csp', 'secure-state',
40
+ ];
41
+ const templates = await loadTemplates(all);
42
+ assert.equal(templates.size, 14);
43
+ });
44
+
45
+ it('skips unknown categories gracefully', async () => {
46
+ const templates = await loadTemplates(['access-control', 'fake']);
47
+ assert.equal(templates.size, 1);
48
+ });
49
+ });
50
+
51
+ describe('getCategoryInfo', () => {
52
+ it('returns correct OWASP code for core categories', () => {
53
+ assert.equal(getCategoryInfo('access-control').owasp, 'A01');
54
+ assert.equal(getCategoryInfo('injection').owasp, 'A05');
55
+ assert.equal(getCategoryInfo('error-handling').owasp, 'A10');
56
+ });
57
+
58
+ it('returns correct info for frontend categories', () => {
59
+ assert.equal(getCategoryInfo('xss-prevention').group, 'frontend');
60
+ assert.equal(getCategoryInfo('csp').owasp, 'FE-03');
61
+ });
62
+
63
+ it('returns fallback for unknown category', () => {
64
+ const info = getCategoryInfo('unknown');
65
+ assert.equal(info.owasp, '??');
66
+ });
67
+ });
68
+ });
@@ -13,11 +13,11 @@ const SECTION_START = '<!-- js-secure-coding:start -->';
13
13
  const SECTION_END = '<!-- js-secure-coding:end -->';
14
14
 
15
15
  export function format(templates, options = {}) {
16
- const { framework = 'vanilla' } = options;
16
+ const { framework = 'vanilla', version = '2.0.0' } = options;
17
17
  const lines = [];
18
18
 
19
19
  lines.push(SECTION_START);
20
- lines.push('<!-- version: 2.0.0 -->');
20
+ lines.push(`<!-- version: ${version} -->`);
21
21
  lines.push('');
22
22
  lines.push('# Security Guidelines');
23
23
  lines.push('');
@@ -6,6 +6,7 @@ import { getCategoryInfo } from '../loader.js';
6
6
 
7
7
  export const name = 'Claude Code';
8
8
  export const outputPath = 'CLAUDE.md';
9
+ export const rulesDir = '.claude/rules';
9
10
  export const description = 'Generates CLAUDE.md for Claude Code';
10
11
 
11
12
  /**
@@ -15,15 +16,15 @@ const SECTION_START = '<!-- js-secure-coding:start -->';
15
16
  const SECTION_END = '<!-- js-secure-coding:end -->';
16
17
 
17
18
  export function format(templates, options = {}) {
18
- const { framework = 'vanilla' } = options;
19
+ const { framework = 'vanilla', version = '2.0.0' } = options;
19
20
  const lines = [];
20
21
 
21
22
  lines.push(SECTION_START);
22
- lines.push('<!-- version: 2.0.0 -->');
23
+ lines.push(`<!-- version: ${version} -->`);
23
24
  lines.push('');
24
25
  lines.push('# Security Rules (OWASP 2025)');
25
26
  lines.push('');
26
- lines.push(`> Auto-generated by js-secure-coding v2.0 | Framework: ${framework}`);
27
+ lines.push(`> Auto-generated by secure-coding-rules v${version} | Framework: ${framework}`);
27
28
  lines.push('> Reference: https://owasp.org/Top10/2025/');
28
29
  lines.push('');
29
30
 
@@ -61,6 +62,44 @@ export function merge(existingContent, newSection) {
61
62
  return (trimmed ? trimmed + '\n\n' : '') + newSection + '\n';
62
63
  }
63
64
 
65
+ /**
66
+ * Format templates into individual files for directory mode
67
+ * Returns Map<filename, content>
68
+ */
69
+ export function formatMultiple(templates, options = {}) {
70
+ const files = new Map();
71
+ for (const [category, content] of templates) {
72
+ files.set(`security-${category}.md`, content);
73
+ }
74
+ return files;
75
+ }
76
+
77
+ /**
78
+ * Generate reference text for CLAUDE.md pointing to rules directory
79
+ */
80
+ export function formatReference(categories, options = {}) {
81
+ const { version = '2.0.0' } = options;
82
+ const lines = [
83
+ SECTION_START,
84
+ `<!-- version: ${version} -->`,
85
+ '',
86
+ '# Security Rules (OWASP 2025)',
87
+ '',
88
+ `> Auto-generated by secure-coding-rules v${version}`,
89
+ '> Full rules are in .claude/rules/security-*.md',
90
+ '',
91
+ 'Security rules are loaded from `.claude/rules/` directory:',
92
+ '',
93
+ ];
94
+ for (const cat of categories) {
95
+ const info = getCategoryInfo(cat);
96
+ lines.push(`- \`security-${cat}.md\` - ${info.owasp}: ${info.title}`);
97
+ }
98
+ lines.push('');
99
+ lines.push(SECTION_END);
100
+ return lines.join('\n');
101
+ }
102
+
64
103
  function extractEssentials(content) {
65
104
  const lines = content.split('\n');
66
105
  const result = [];