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.
- package/docker-compose.dev.yml +6 -3
- package/package.json +1 -1
- package/server/index.js +229 -14
- package/server/lib/compliance/control-mapper.js +401 -0
- package/server/lib/compliance/control-mapper.test.js +117 -0
- package/server/lib/compliance/evidence-linker.js +296 -0
- package/server/lib/compliance/evidence-linker.test.js +121 -0
- package/server/lib/compliance/gdpr-checklist.js +416 -0
- package/server/lib/compliance/gdpr-checklist.test.js +131 -0
- package/server/lib/compliance/hipaa-checklist.js +277 -0
- package/server/lib/compliance/hipaa-checklist.test.js +101 -0
- package/server/lib/compliance/iso27001-checklist.js +287 -0
- package/server/lib/compliance/iso27001-checklist.test.js +99 -0
- package/server/lib/compliance/multi-framework-reporter.js +284 -0
- package/server/lib/compliance/multi-framework-reporter.test.js +127 -0
- package/server/lib/compliance/pci-dss-checklist.js +214 -0
- package/server/lib/compliance/pci-dss-checklist.test.js +95 -0
- package/server/lib/compliance/trust-centre.js +187 -0
- package/server/lib/compliance/trust-centre.test.js +93 -0
- package/server/lib/dashboard/api-server.js +155 -0
- package/server/lib/dashboard/api-server.test.js +155 -0
- package/server/lib/dashboard/health-api.js +199 -0
- package/server/lib/dashboard/health-api.test.js +122 -0
- package/server/lib/dashboard/notes-api.js +234 -0
- package/server/lib/dashboard/notes-api.test.js +134 -0
- package/server/lib/dashboard/router-api.js +176 -0
- package/server/lib/dashboard/router-api.test.js +132 -0
- package/server/lib/dashboard/tasks-api.js +289 -0
- package/server/lib/dashboard/tasks-api.test.js +161 -0
- package/server/lib/dashboard/tlc-introspection.js +197 -0
- package/server/lib/dashboard/tlc-introspection.test.js +138 -0
- package/server/lib/dashboard/version-api.js +222 -0
- package/server/lib/dashboard/version-api.test.js +112 -0
- package/server/lib/dashboard/websocket-server.js +104 -0
- package/server/lib/dashboard/websocket-server.test.js +118 -0
- package/server/lib/deploy/branch-classifier.js +163 -0
- package/server/lib/deploy/branch-classifier.test.js +164 -0
- package/server/lib/deploy/deployment-approval.js +299 -0
- package/server/lib/deploy/deployment-approval.test.js +296 -0
- package/server/lib/deploy/deployment-audit.js +374 -0
- package/server/lib/deploy/deployment-audit.test.js +307 -0
- package/server/lib/deploy/deployment-executor.js +335 -0
- package/server/lib/deploy/deployment-executor.test.js +329 -0
- package/server/lib/deploy/deployment-rules.js +163 -0
- package/server/lib/deploy/deployment-rules.test.js +188 -0
- package/server/lib/deploy/rollback-manager.js +379 -0
- package/server/lib/deploy/rollback-manager.test.js +321 -0
- package/server/lib/deploy/security-gates.js +236 -0
- package/server/lib/deploy/security-gates.test.js +222 -0
- package/server/lib/k8s/gitops-config.js +188 -0
- package/server/lib/k8s/gitops-config.test.js +59 -0
- package/server/lib/k8s/helm-generator.js +196 -0
- package/server/lib/k8s/helm-generator.test.js +59 -0
- package/server/lib/k8s/kustomize-generator.js +176 -0
- package/server/lib/k8s/kustomize-generator.test.js +58 -0
- package/server/lib/k8s/network-policy.js +114 -0
- package/server/lib/k8s/network-policy.test.js +53 -0
- package/server/lib/k8s/pod-security.js +114 -0
- package/server/lib/k8s/pod-security.test.js +55 -0
- package/server/lib/k8s/rbac-generator.js +132 -0
- package/server/lib/k8s/rbac-generator.test.js +57 -0
- package/server/lib/k8s/resource-manager.js +172 -0
- package/server/lib/k8s/resource-manager.test.js +60 -0
- package/server/lib/k8s/secrets-encryption.js +168 -0
- package/server/lib/k8s/secrets-encryption.test.js +49 -0
- package/server/lib/monitoring/alert-manager.js +238 -0
- package/server/lib/monitoring/alert-manager.test.js +106 -0
- package/server/lib/monitoring/health-check.js +226 -0
- package/server/lib/monitoring/health-check.test.js +176 -0
- package/server/lib/monitoring/incident-manager.js +230 -0
- package/server/lib/monitoring/incident-manager.test.js +98 -0
- package/server/lib/monitoring/log-aggregator.js +147 -0
- package/server/lib/monitoring/log-aggregator.test.js +89 -0
- package/server/lib/monitoring/metrics-collector.js +337 -0
- package/server/lib/monitoring/metrics-collector.test.js +172 -0
- package/server/lib/monitoring/status-page.js +214 -0
- package/server/lib/monitoring/status-page.test.js +105 -0
- package/server/lib/monitoring/uptime-monitor.js +194 -0
- package/server/lib/monitoring/uptime-monitor.test.js +109 -0
- package/server/lib/network/fail2ban-config.js +294 -0
- package/server/lib/network/fail2ban-config.test.js +275 -0
- package/server/lib/network/firewall-manager.js +252 -0
- package/server/lib/network/firewall-manager.test.js +254 -0
- package/server/lib/network/geoip-filter.js +282 -0
- package/server/lib/network/geoip-filter.test.js +264 -0
- package/server/lib/network/rate-limiter.js +229 -0
- package/server/lib/network/rate-limiter.test.js +293 -0
- package/server/lib/network/request-validator.js +351 -0
- package/server/lib/network/request-validator.test.js +345 -0
- package/server/lib/network/security-headers.js +251 -0
- package/server/lib/network/security-headers.test.js +283 -0
- package/server/lib/network/tls-config.js +210 -0
- package/server/lib/network/tls-config.test.js +248 -0
- package/server/lib/security/auth-security.js +369 -0
- package/server/lib/security/auth-security.test.js +448 -0
- package/server/lib/security/cis-benchmark.js +152 -0
- package/server/lib/security/cis-benchmark.test.js +137 -0
- package/server/lib/security/compose-templates.js +312 -0
- package/server/lib/security/compose-templates.test.js +229 -0
- package/server/lib/security/container-runtime.js +456 -0
- package/server/lib/security/container-runtime.test.js +503 -0
- package/server/lib/security/cors-validator.js +278 -0
- package/server/lib/security/cors-validator.test.js +310 -0
- package/server/lib/security/crypto-utils.js +253 -0
- package/server/lib/security/crypto-utils.test.js +409 -0
- package/server/lib/security/dockerfile-linter.js +459 -0
- package/server/lib/security/dockerfile-linter.test.js +483 -0
- package/server/lib/security/dockerfile-templates.js +278 -0
- package/server/lib/security/dockerfile-templates.test.js +164 -0
- package/server/lib/security/error-sanitizer.js +426 -0
- package/server/lib/security/error-sanitizer.test.js +331 -0
- package/server/lib/security/headers-generator.js +368 -0
- package/server/lib/security/headers-generator.test.js +398 -0
- package/server/lib/security/image-scanner.js +83 -0
- package/server/lib/security/image-scanner.test.js +106 -0
- package/server/lib/security/input-validator.js +352 -0
- package/server/lib/security/input-validator.test.js +330 -0
- package/server/lib/security/network-policy.js +174 -0
- package/server/lib/security/network-policy.test.js +164 -0
- package/server/lib/security/output-encoder.js +237 -0
- package/server/lib/security/output-encoder.test.js +276 -0
- package/server/lib/security/path-validator.js +359 -0
- package/server/lib/security/path-validator.test.js +293 -0
- package/server/lib/security/query-builder.js +421 -0
- package/server/lib/security/query-builder.test.js +318 -0
- package/server/lib/security/secret-detector.js +290 -0
- package/server/lib/security/secret-detector.test.js +354 -0
- package/server/lib/security/secrets-validator.js +137 -0
- package/server/lib/security/secrets-validator.test.js +120 -0
- package/server/lib/security-testing/dast-runner.js +154 -0
- package/server/lib/security-testing/dast-runner.test.js +62 -0
- package/server/lib/security-testing/dependency-scanner.js +172 -0
- package/server/lib/security-testing/dependency-scanner.test.js +64 -0
- package/server/lib/security-testing/pentest-runner.js +230 -0
- package/server/lib/security-testing/pentest-runner.test.js +60 -0
- package/server/lib/security-testing/sast-runner.js +136 -0
- package/server/lib/security-testing/sast-runner.test.js +62 -0
- package/server/lib/security-testing/secret-scanner.js +153 -0
- package/server/lib/security-testing/secret-scanner.test.js +66 -0
- package/server/lib/security-testing/security-gate.js +216 -0
- package/server/lib/security-testing/security-gate.test.js +115 -0
- package/server/lib/security-testing/security-reporter.js +303 -0
- package/server/lib/security-testing/security-reporter.test.js +114 -0
- package/server/lib/standards/audit-checker.js +546 -0
- package/server/lib/standards/audit-checker.test.js +415 -0
- package/server/lib/standards/cleanup-executor.js +452 -0
- package/server/lib/standards/cleanup-executor.test.js +293 -0
- package/server/lib/standards/refactor-stepper.js +425 -0
- package/server/lib/standards/refactor-stepper.test.js +298 -0
- package/server/lib/standards/standards-injector.js +167 -0
- package/server/lib/standards/standards-injector.test.js +232 -0
- package/server/lib/user-management.test.js +284 -0
- package/server/lib/vps/backup-manager.js +157 -0
- package/server/lib/vps/backup-manager.test.js +59 -0
- package/server/lib/vps/caddy-config.js +159 -0
- package/server/lib/vps/caddy-config.test.js +48 -0
- package/server/lib/vps/compose-orchestrator.js +219 -0
- package/server/lib/vps/compose-orchestrator.test.js +50 -0
- package/server/lib/vps/database-config.js +208 -0
- package/server/lib/vps/database-config.test.js +47 -0
- package/server/lib/vps/deploy-script.js +211 -0
- package/server/lib/vps/deploy-script.test.js +53 -0
- package/server/lib/vps/secrets-manager.js +148 -0
- package/server/lib/vps/secrets-manager.test.js +58 -0
- package/server/lib/vps/server-hardening.js +174 -0
- package/server/lib/vps/server-hardening.test.js +70 -0
- package/server/package-lock.json +19 -0
- package/server/package.json +1 -0
- package/server/templates/CLAUDE.md +37 -0
- package/server/templates/CODING-STANDARDS.md +408 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HIPAA Compliance Checklist
|
|
3
|
+
* Health Insurance Portability and Accountability Act safeguards
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// HIPAA Safeguards
|
|
7
|
+
const SAFEGUARDS = [
|
|
8
|
+
// Administrative Safeguards
|
|
9
|
+
{ id: 'security-management', name: 'Security Management Process', category: 'administrative', type: 'required', section: '164.308(a)(1)' },
|
|
10
|
+
{ id: 'assigned-security', name: 'Assigned Security Responsibility', category: 'administrative', type: 'required', section: '164.308(a)(2)' },
|
|
11
|
+
{ id: 'workforce-security', name: 'Workforce Security', category: 'administrative', type: 'addressable', section: '164.308(a)(3)' },
|
|
12
|
+
{ id: 'info-access-mgmt', name: 'Information Access Management', category: 'administrative', type: 'required', section: '164.308(a)(4)' },
|
|
13
|
+
{ id: 'security-training', name: 'Security Awareness and Training', category: 'administrative', type: 'addressable', section: '164.308(a)(5)' },
|
|
14
|
+
{ id: 'security-incident', name: 'Security Incident Procedures', category: 'administrative', type: 'required', section: '164.308(a)(6)' },
|
|
15
|
+
{ id: 'contingency-plan', name: 'Contingency Plan', category: 'administrative', type: 'required', section: '164.308(a)(7)' },
|
|
16
|
+
{ id: 'evaluation', name: 'Evaluation', category: 'administrative', type: 'required', section: '164.308(a)(8)' },
|
|
17
|
+
{ id: 'baa', name: 'Business Associate Contracts', category: 'administrative', type: 'required', section: '164.308(b)(1)' },
|
|
18
|
+
|
|
19
|
+
// Physical Safeguards
|
|
20
|
+
{ id: 'facility-access', name: 'Facility Access Controls', category: 'physical', type: 'addressable', section: '164.310(a)(1)' },
|
|
21
|
+
{ id: 'workstation-use', name: 'Workstation Use', category: 'physical', type: 'required', section: '164.310(b)' },
|
|
22
|
+
{ id: 'workstation-security', name: 'Workstation Security', category: 'physical', type: 'required', section: '164.310(c)' },
|
|
23
|
+
{ id: 'device-media', name: 'Device and Media Controls', category: 'physical', type: 'required', section: '164.310(d)(1)' },
|
|
24
|
+
|
|
25
|
+
// Technical Safeguards
|
|
26
|
+
{ id: 'access-control', name: 'Access Control', category: 'technical', type: 'required', section: '164.312(a)(1)' },
|
|
27
|
+
{ id: 'audit-controls', name: 'Audit Controls', category: 'technical', type: 'required', section: '164.312(b)' },
|
|
28
|
+
{ id: 'integrity', name: 'Integrity', category: 'technical', type: 'addressable', section: '164.312(c)(1)' },
|
|
29
|
+
{ id: 'person-auth', name: 'Person or Entity Authentication', category: 'technical', type: 'required', section: '164.312(d)' },
|
|
30
|
+
{ id: 'transmission-security', name: 'Transmission Security', category: 'technical', type: 'addressable', section: '164.312(e)(1)' },
|
|
31
|
+
{ id: 'encryption', name: 'Encryption', category: 'technical', type: 'addressable', section: '164.312(e)(2)' }
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// PHI data element patterns
|
|
35
|
+
const PHI_PATTERNS = {
|
|
36
|
+
ssn: { element: 'ssn', description: 'Social Security Number', sensitivity: 'high' },
|
|
37
|
+
'patient.ssn': { element: 'ssn', description: 'Patient Social Security Number', sensitivity: 'high' },
|
|
38
|
+
dateOfBirth: { element: 'dateOfBirth', description: 'Date of Birth', sensitivity: 'medium' },
|
|
39
|
+
'patient.dateOfBirth': { element: 'dateOfBirth', description: 'Patient Date of Birth', sensitivity: 'medium' },
|
|
40
|
+
medicalRecord: { element: 'medicalRecord', description: 'Medical Record', sensitivity: 'high' },
|
|
41
|
+
diagnosis: { element: 'diagnosis', description: 'Diagnosis Information', sensitivity: 'high' },
|
|
42
|
+
treatment: { element: 'treatment', description: 'Treatment Information', sensitivity: 'high' },
|
|
43
|
+
prescription: { element: 'prescription', description: 'Prescription Information', sensitivity: 'high' },
|
|
44
|
+
healthPlan: { element: 'healthPlan', description: 'Health Plan Information', sensitivity: 'medium' },
|
|
45
|
+
'patient.name': { element: 'name', description: 'Patient Name', sensitivity: 'medium' },
|
|
46
|
+
'patient.address': { element: 'address', description: 'Patient Address', sensitivity: 'medium' },
|
|
47
|
+
'patient.phone': { element: 'phone', description: 'Patient Phone', sensitivity: 'medium' },
|
|
48
|
+
'patient.email': { element: 'email', description: 'Patient Email', sensitivity: 'medium' }
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Safeguard check implementations
|
|
52
|
+
const SAFEGUARD_CHECKS = {
|
|
53
|
+
'access-control': (evidence) => {
|
|
54
|
+
return evidence.accessControls?.enabled === true;
|
|
55
|
+
},
|
|
56
|
+
'encryption': (evidence) => {
|
|
57
|
+
return evidence.encryption?.atRest === true && evidence.encryption?.inTransit === true;
|
|
58
|
+
},
|
|
59
|
+
'audit-controls': (evidence) => {
|
|
60
|
+
if (!evidence.auditLogs?.enabled) return false;
|
|
61
|
+
// Check retention period (HIPAA requires 6 years)
|
|
62
|
+
const retention = evidence.auditLogs.retention;
|
|
63
|
+
if (retention) {
|
|
64
|
+
const years = parseInt(retention);
|
|
65
|
+
return years >= 6;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create a HIPAA checklist instance
|
|
73
|
+
* @returns {Object} Checklist instance
|
|
74
|
+
*/
|
|
75
|
+
export function createHipaaChecklist() {
|
|
76
|
+
return {
|
|
77
|
+
evaluate(evidence) {
|
|
78
|
+
const results = [];
|
|
79
|
+
const safeguards = getSafeguards();
|
|
80
|
+
|
|
81
|
+
for (const safeguard of safeguards) {
|
|
82
|
+
const result = checkSafeguard(safeguard.id, evidence);
|
|
83
|
+
results.push(result);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
results,
|
|
88
|
+
compliant: results.every(r => r.implemented || r.safeguard?.type === 'addressable'),
|
|
89
|
+
score: (results.filter(r => r.implemented).length / results.length) * 100
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
getSafeguards() {
|
|
94
|
+
return getSafeguards();
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
getCategories() {
|
|
98
|
+
return ['administrative', 'physical', 'technical'];
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Get HIPAA safeguards
|
|
105
|
+
* @param {Object} options - Filter options
|
|
106
|
+
* @param {string} options.category - Filter by category
|
|
107
|
+
* @returns {Array} Safeguards list
|
|
108
|
+
*/
|
|
109
|
+
export function getSafeguards(options = {}) {
|
|
110
|
+
let safeguards = [...SAFEGUARDS];
|
|
111
|
+
|
|
112
|
+
if (options.category) {
|
|
113
|
+
safeguards = safeguards.filter(s => s.category === options.category);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return safeguards;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Check implementation of a specific safeguard
|
|
121
|
+
* @param {string} safeguardId - Safeguard identifier
|
|
122
|
+
* @param {Object} evidence - Evidence for compliance check
|
|
123
|
+
* @returns {Object} Check result
|
|
124
|
+
*/
|
|
125
|
+
export function checkSafeguard(safeguardId, evidence) {
|
|
126
|
+
const safeguard = SAFEGUARDS.find(s => s.id === safeguardId);
|
|
127
|
+
const checkFn = SAFEGUARD_CHECKS[safeguardId];
|
|
128
|
+
|
|
129
|
+
let implemented = false;
|
|
130
|
+
|
|
131
|
+
if (checkFn) {
|
|
132
|
+
implemented = checkFn(evidence);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
safeguardId,
|
|
137
|
+
safeguardName: safeguard?.name || 'Unknown safeguard',
|
|
138
|
+
category: safeguard?.category,
|
|
139
|
+
type: safeguard?.type,
|
|
140
|
+
implemented,
|
|
141
|
+
safeguard
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Generate Business Associate Agreement template
|
|
147
|
+
* @param {Object} options - BAA options
|
|
148
|
+
* @param {string} options.coveredEntity - Covered entity name
|
|
149
|
+
* @param {string} options.businessAssociate - Business associate name
|
|
150
|
+
* @returns {string} BAA template
|
|
151
|
+
*/
|
|
152
|
+
export function generateBaaTemplate(options = {}) {
|
|
153
|
+
const coveredEntity = options.coveredEntity || '[COVERED ENTITY]';
|
|
154
|
+
const businessAssociate = options.businessAssociate || '[BUSINESS ASSOCIATE]';
|
|
155
|
+
const date = new Date().toISOString().split('T')[0];
|
|
156
|
+
|
|
157
|
+
return `# Business Associate Agreement
|
|
158
|
+
|
|
159
|
+
**Effective Date:** ${date}
|
|
160
|
+
|
|
161
|
+
**Between:**
|
|
162
|
+
- Covered Entity: ${coveredEntity}
|
|
163
|
+
- Business Associate: ${businessAssociate}
|
|
164
|
+
|
|
165
|
+
## Recitals
|
|
166
|
+
|
|
167
|
+
This Business Associate Agreement ("BAA") is entered into by and between ${coveredEntity} ("Covered Entity") and ${businessAssociate} ("Business Associate") to ensure compliance with the Health Insurance Portability and Accountability Act of 1996 ("HIPAA").
|
|
168
|
+
|
|
169
|
+
## Article I: Definitions
|
|
170
|
+
|
|
171
|
+
Terms used herein shall have the same meaning as defined in 45 CFR Parts 160 and 164.
|
|
172
|
+
|
|
173
|
+
## Article II: Obligations of Business Associate
|
|
174
|
+
|
|
175
|
+
### 2.1 Permitted Uses and Disclosures
|
|
176
|
+
|
|
177
|
+
Business Associate agrees to not use or disclose PHI other than as permitted or required by this Agreement or as Required by Law.
|
|
178
|
+
|
|
179
|
+
The permitted uses and disclosures of PHI are limited to:
|
|
180
|
+
- Treatment, payment, and health care operations
|
|
181
|
+
- Functions, activities, or services specified in the underlying agreement
|
|
182
|
+
- As required by law
|
|
183
|
+
|
|
184
|
+
### 2.2 Safeguards
|
|
185
|
+
|
|
186
|
+
Business Associate agrees to use appropriate safeguards to prevent use or disclosure of PHI other than as provided for by this Agreement.
|
|
187
|
+
|
|
188
|
+
Required safeguards include:
|
|
189
|
+
- Administrative safeguards (policies and procedures)
|
|
190
|
+
- Physical safeguards (facility access controls)
|
|
191
|
+
- Technical safeguards (access controls, encryption)
|
|
192
|
+
|
|
193
|
+
### 2.3 Breach Notification
|
|
194
|
+
|
|
195
|
+
Business Associate agrees to report to Covered Entity any breach notification requirements under 45 CFR 164.410.
|
|
196
|
+
|
|
197
|
+
In the event of a breach:
|
|
198
|
+
- Notification within 60 days of discovery
|
|
199
|
+
- Description of PHI involved
|
|
200
|
+
- Recommended mitigation steps
|
|
201
|
+
|
|
202
|
+
## Article III: Termination
|
|
203
|
+
|
|
204
|
+
This Agreement may be terminated:
|
|
205
|
+
- Upon termination of the underlying agreement
|
|
206
|
+
- Upon breach of material terms
|
|
207
|
+
- As required by law
|
|
208
|
+
|
|
209
|
+
## Signatures
|
|
210
|
+
|
|
211
|
+
_________________________
|
|
212
|
+
${coveredEntity}
|
|
213
|
+
Covered Entity
|
|
214
|
+
|
|
215
|
+
_________________________
|
|
216
|
+
${businessAssociate}
|
|
217
|
+
Business Associate
|
|
218
|
+
`;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Assess PHI handling in code patterns
|
|
223
|
+
* @param {Array} codePatterns - Array of code patterns to analyze
|
|
224
|
+
* @returns {Object} Assessment result
|
|
225
|
+
*/
|
|
226
|
+
export function assessPhiHandling(codePatterns) {
|
|
227
|
+
const dataElements = new Set();
|
|
228
|
+
const findings = [];
|
|
229
|
+
const recommendations = [];
|
|
230
|
+
|
|
231
|
+
for (const pattern of codePatterns) {
|
|
232
|
+
const patternStr = pattern.pattern || '';
|
|
233
|
+
|
|
234
|
+
// Check against known PHI patterns
|
|
235
|
+
for (const [key, info] of Object.entries(PHI_PATTERNS)) {
|
|
236
|
+
if (patternStr.toLowerCase().includes(key.toLowerCase())) {
|
|
237
|
+
dataElements.add(info.element);
|
|
238
|
+
findings.push({
|
|
239
|
+
file: pattern.file,
|
|
240
|
+
pattern: patternStr,
|
|
241
|
+
element: info.element,
|
|
242
|
+
description: info.description,
|
|
243
|
+
sensitivity: info.sensitivity
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Generate recommendations based on findings
|
|
250
|
+
if (findings.some(f => f.sensitivity === 'high')) {
|
|
251
|
+
recommendations.push('Implement encryption at rest for high-sensitivity PHI data');
|
|
252
|
+
recommendations.push('Use encryption in transit (TLS 1.2+) for all PHI transmissions');
|
|
253
|
+
recommendations.push('Implement access controls with role-based permissions');
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (dataElements.has('ssn')) {
|
|
257
|
+
recommendations.push('Consider tokenization for SSN storage');
|
|
258
|
+
recommendations.push('Implement audit logging for SSN access');
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (dataElements.has('medicalRecord')) {
|
|
262
|
+
recommendations.push('Implement audit logging for medical record access');
|
|
263
|
+
recommendations.push('Ensure minimum necessary access principle');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (recommendations.length === 0 && findings.length > 0) {
|
|
267
|
+
recommendations.push('Review data handling practices for HIPAA compliance');
|
|
268
|
+
recommendations.push('Document PHI data flows');
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
phiIdentified: dataElements.size > 0,
|
|
273
|
+
dataElements: Array.from(dataElements),
|
|
274
|
+
findings,
|
|
275
|
+
recommendations
|
|
276
|
+
};
|
|
277
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HIPAA Checklist Tests
|
|
3
|
+
*/
|
|
4
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
5
|
+
import { createHipaaChecklist, getSafeguards, checkSafeguard, generateBaaTemplate, assessPhiHandling } from './hipaa-checklist.js';
|
|
6
|
+
|
|
7
|
+
describe('hipaa-checklist', () => {
|
|
8
|
+
describe('createHipaaChecklist', () => {
|
|
9
|
+
it('creates HIPAA checklist', () => {
|
|
10
|
+
const checklist = createHipaaChecklist();
|
|
11
|
+
expect(checklist.evaluate).toBeDefined();
|
|
12
|
+
expect(checklist.getSafeguards).toBeDefined();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('covers all safeguard categories', () => {
|
|
16
|
+
const checklist = createHipaaChecklist();
|
|
17
|
+
const categories = checklist.getCategories();
|
|
18
|
+
expect(categories).toContain('administrative');
|
|
19
|
+
expect(categories).toContain('physical');
|
|
20
|
+
expect(categories).toContain('technical');
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('getSafeguards', () => {
|
|
25
|
+
it('returns all HIPAA safeguards', () => {
|
|
26
|
+
const safeguards = getSafeguards();
|
|
27
|
+
expect(safeguards.length).toBeGreaterThan(0);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('filters by category', () => {
|
|
31
|
+
const technical = getSafeguards({ category: 'technical' });
|
|
32
|
+
expect(technical.every(s => s.category === 'technical')).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('distinguishes required vs addressable', () => {
|
|
36
|
+
const safeguards = getSafeguards();
|
|
37
|
+
expect(safeguards.some(s => s.type === 'required')).toBe(true);
|
|
38
|
+
expect(safeguards.some(s => s.type === 'addressable')).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('checkSafeguard', () => {
|
|
43
|
+
it('checks safeguard implementation', () => {
|
|
44
|
+
const evidence = { accessControls: { enabled: true } };
|
|
45
|
+
const result = checkSafeguard('access-control', evidence);
|
|
46
|
+
expect(result.safeguardId).toBe('access-control');
|
|
47
|
+
expect(result.implemented).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('checks encryption requirements', () => {
|
|
51
|
+
const evidence = { encryption: { atRest: true, inTransit: true } };
|
|
52
|
+
const result = checkSafeguard('encryption', evidence);
|
|
53
|
+
expect(result.implemented).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('validates audit controls', () => {
|
|
57
|
+
const evidence = { auditLogs: { enabled: true, retention: '6years' } };
|
|
58
|
+
const result = checkSafeguard('audit-controls', evidence);
|
|
59
|
+
expect(result.implemented).toBe(true);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('generateBaaTemplate', () => {
|
|
64
|
+
it('generates Business Associate Agreement template', () => {
|
|
65
|
+
const baa = generateBaaTemplate({ coveredEntity: 'Hospital', businessAssociate: 'TLC Inc' });
|
|
66
|
+
expect(baa).toContain('Business Associate Agreement');
|
|
67
|
+
expect(baa).toContain('Hospital');
|
|
68
|
+
expect(baa).toContain('TLC Inc');
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('includes required provisions', () => {
|
|
72
|
+
const baa = generateBaaTemplate({});
|
|
73
|
+
expect(baa).toContain('permitted uses');
|
|
74
|
+
expect(baa).toContain('safeguards');
|
|
75
|
+
expect(baa).toContain('breach notification');
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('assessPhiHandling', () => {
|
|
80
|
+
it('assesses PHI data handling', () => {
|
|
81
|
+
const codePatterns = [
|
|
82
|
+
{ file: 'patient.js', pattern: 'patient.ssn' },
|
|
83
|
+
{ file: 'records.js', pattern: 'medicalRecord' }
|
|
84
|
+
];
|
|
85
|
+
const assessment = assessPhiHandling(codePatterns);
|
|
86
|
+
expect(assessment.phiIdentified).toBe(true);
|
|
87
|
+
expect(assessment.dataElements.length).toBeGreaterThan(0);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('identifies PHI data elements', () => {
|
|
91
|
+
const codePatterns = [{ file: 'test.js', pattern: 'patient.dateOfBirth' }];
|
|
92
|
+
const assessment = assessPhiHandling(codePatterns);
|
|
93
|
+
expect(assessment.dataElements).toContain('dateOfBirth');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('suggests protection measures', () => {
|
|
97
|
+
const assessment = assessPhiHandling([{ file: 'test.js', pattern: 'ssn' }]);
|
|
98
|
+
expect(assessment.recommendations.length).toBeGreaterThan(0);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ISO 27001:2022 Compliance Checklist
|
|
3
|
+
* Information Security Management System controls
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ISO 27001:2022 Annex A Controls
|
|
7
|
+
const CONTROLS = [
|
|
8
|
+
// Organizational controls (A.5)
|
|
9
|
+
{ id: 'A.5.1', name: 'Policies for information security', theme: 'organizational', purpose: 'To provide management direction and support for information security' },
|
|
10
|
+
{ id: 'A.5.2', name: 'Information security roles and responsibilities', theme: 'organizational', purpose: 'To establish a defined and approved information security organizational structure' },
|
|
11
|
+
{ id: 'A.5.3', name: 'Segregation of duties', theme: 'organizational', purpose: 'To reduce the risk of fraud and error' },
|
|
12
|
+
{ id: 'A.5.4', name: 'Management responsibilities', theme: 'organizational', purpose: 'To ensure all personnel support information security' },
|
|
13
|
+
{ id: 'A.5.5', name: 'Contact with authorities', theme: 'organizational', purpose: 'To maintain appropriate contacts with relevant authorities' },
|
|
14
|
+
{ id: 'A.5.6', name: 'Contact with special interest groups', theme: 'organizational', purpose: 'To maintain appropriate contacts with special interest groups' },
|
|
15
|
+
{ id: 'A.5.7', name: 'Threat intelligence', theme: 'organizational', purpose: 'To provide awareness of the threat environment' },
|
|
16
|
+
{ id: 'A.5.8', name: 'Information security in project management', theme: 'organizational', purpose: 'To ensure information security is integrated into project management' },
|
|
17
|
+
{ id: 'A.5.9', name: 'Inventory of information and other associated assets', theme: 'organizational', purpose: 'To identify and manage information assets' },
|
|
18
|
+
{ id: 'A.5.10', name: 'Acceptable use of information and other associated assets', theme: 'organizational', purpose: 'To ensure information assets are appropriately used' },
|
|
19
|
+
{ id: 'A.5.11', name: 'Return of assets', theme: 'organizational', purpose: 'To protect assets when employment ends' },
|
|
20
|
+
{ id: 'A.5.12', name: 'Classification of information', theme: 'organizational', purpose: 'To ensure information is classified appropriately' },
|
|
21
|
+
{ id: 'A.5.13', name: 'Labelling of information', theme: 'organizational', purpose: 'To facilitate information classification' },
|
|
22
|
+
{ id: 'A.5.14', name: 'Information transfer', theme: 'organizational', purpose: 'To maintain security during information transfer' },
|
|
23
|
+
{ id: 'A.5.15', name: 'Access control', theme: 'organizational', purpose: 'To ensure authorized access to information' },
|
|
24
|
+
{ id: 'A.5.16', name: 'Identity management', theme: 'organizational', purpose: 'To enable unique identification of individuals' },
|
|
25
|
+
{ id: 'A.5.17', name: 'Authentication information', theme: 'organizational', purpose: 'To prevent unauthorized disclosure of authentication information' },
|
|
26
|
+
{ id: 'A.5.18', name: 'Access rights', theme: 'organizational', purpose: 'To ensure access rights are authorized, reviewed, and removed' },
|
|
27
|
+
|
|
28
|
+
// People controls (A.6)
|
|
29
|
+
{ id: 'A.6.1', name: 'Screening', theme: 'people', purpose: 'To ensure personnel are suitable and trustworthy' },
|
|
30
|
+
{ id: 'A.6.2', name: 'Terms and conditions of employment', theme: 'people', purpose: 'To ensure personnel understand their responsibilities' },
|
|
31
|
+
{ id: 'A.6.3', name: 'Information security awareness, education and training', theme: 'people', purpose: 'To ensure personnel are aware of security requirements' },
|
|
32
|
+
{ id: 'A.6.4', name: 'Disciplinary process', theme: 'people', purpose: 'To ensure there are consequences for security violations' },
|
|
33
|
+
{ id: 'A.6.5', name: 'Responsibilities after termination or change of employment', theme: 'people', purpose: 'To protect organizational interests during employment changes' },
|
|
34
|
+
{ id: 'A.6.6', name: 'Confidentiality or non-disclosure agreements', theme: 'people', purpose: 'To protect confidential information' },
|
|
35
|
+
{ id: 'A.6.7', name: 'Remote working', theme: 'people', purpose: 'To protect information when working remotely' },
|
|
36
|
+
{ id: 'A.6.8', name: 'Information security event reporting', theme: 'people', purpose: 'To provide timely reporting of security events' },
|
|
37
|
+
|
|
38
|
+
// Physical controls (A.7)
|
|
39
|
+
{ id: 'A.7.1', name: 'Physical security perimeters', theme: 'physical', purpose: 'To prevent unauthorized physical access' },
|
|
40
|
+
{ id: 'A.7.2', name: 'Physical entry', theme: 'physical', purpose: 'To protect areas by appropriate entry controls' },
|
|
41
|
+
{ id: 'A.7.3', name: 'Securing offices, rooms and facilities', theme: 'physical', purpose: 'To prevent unauthorized physical access' },
|
|
42
|
+
{ id: 'A.7.4', name: 'Physical security monitoring', theme: 'physical', purpose: 'To detect and deter unauthorized access' },
|
|
43
|
+
{ id: 'A.7.5', name: 'Protecting against physical and environmental threats', theme: 'physical', purpose: 'To protect against environmental damage' },
|
|
44
|
+
{ id: 'A.7.6', name: 'Working in secure areas', theme: 'physical', purpose: 'To protect information in secure areas' },
|
|
45
|
+
{ id: 'A.7.7', name: 'Clear desk and clear screen', theme: 'physical', purpose: 'To reduce risks from unattended workspaces' },
|
|
46
|
+
{ id: 'A.7.8', name: 'Equipment siting and protection', theme: 'physical', purpose: 'To protect equipment from environmental threats' },
|
|
47
|
+
{ id: 'A.7.9', name: 'Security of assets off-premises', theme: 'physical', purpose: 'To protect assets outside organizational premises' },
|
|
48
|
+
{ id: 'A.7.10', name: 'Storage media', theme: 'physical', purpose: 'To prevent unauthorized disclosure from storage media' },
|
|
49
|
+
{ id: 'A.7.11', name: 'Supporting utilities', theme: 'physical', purpose: 'To prevent loss or damage from utility failures' },
|
|
50
|
+
{ id: 'A.7.12', name: 'Cabling security', theme: 'physical', purpose: 'To protect cabling from interception or damage' },
|
|
51
|
+
{ id: 'A.7.13', name: 'Equipment maintenance', theme: 'physical', purpose: 'To ensure continued availability and integrity' },
|
|
52
|
+
{ id: 'A.7.14', name: 'Secure disposal or re-use of equipment', theme: 'physical', purpose: 'To prevent information leakage from disposed equipment' },
|
|
53
|
+
|
|
54
|
+
// Technological controls (A.8)
|
|
55
|
+
{ id: 'A.8.1', name: 'User endpoint devices', theme: 'technological', purpose: 'To protect information on endpoint devices' },
|
|
56
|
+
{ id: 'A.8.2', name: 'Privileged access rights', theme: 'technological', purpose: 'To restrict and manage privileged access' },
|
|
57
|
+
{ id: 'A.8.3', name: 'Information access restriction', theme: 'technological', purpose: 'To prevent unauthorized access to information' },
|
|
58
|
+
{ id: 'A.8.4', name: 'Access to source code', theme: 'technological', purpose: 'To prevent unauthorized access to source code' },
|
|
59
|
+
{ id: 'A.8.5', name: 'Secure authentication', theme: 'technological', purpose: 'To implement secure authentication mechanisms' },
|
|
60
|
+
{ id: 'A.8.6', name: 'Capacity management', theme: 'technological', purpose: 'To ensure adequate resource capacity' },
|
|
61
|
+
{ id: 'A.8.7', name: 'Protection against malware', theme: 'technological', purpose: 'To protect against malware' },
|
|
62
|
+
{ id: 'A.8.8', name: 'Management of technical vulnerabilities', theme: 'technological', purpose: 'To prevent exploitation of vulnerabilities' },
|
|
63
|
+
{ id: 'A.8.9', name: 'Configuration management', theme: 'technological', purpose: 'To ensure secure configurations' },
|
|
64
|
+
{ id: 'A.8.10', name: 'Information deletion', theme: 'technological', purpose: 'To ensure secure deletion of information' },
|
|
65
|
+
{ id: 'A.8.11', name: 'Data masking', theme: 'technological', purpose: 'To limit exposure of sensitive data' },
|
|
66
|
+
{ id: 'A.8.12', name: 'Data leakage prevention', theme: 'technological', purpose: 'To prevent unauthorized data disclosure' },
|
|
67
|
+
{ id: 'A.8.13', name: 'Information backup', theme: 'technological', purpose: 'To maintain backup copies of information' },
|
|
68
|
+
{ id: 'A.8.14', name: 'Redundancy of information processing facilities', theme: 'technological', purpose: 'To ensure availability of processing facilities' },
|
|
69
|
+
{ id: 'A.8.15', name: 'Logging', theme: 'technological', purpose: 'To record events for investigation' },
|
|
70
|
+
{ id: 'A.8.16', name: 'Monitoring activities', theme: 'technological', purpose: 'To detect anomalous behavior' },
|
|
71
|
+
{ id: 'A.8.17', name: 'Clock synchronization', theme: 'technological', purpose: 'To ensure consistent timestamps' },
|
|
72
|
+
{ id: 'A.8.18', name: 'Use of privileged utility programs', theme: 'technological', purpose: 'To restrict use of privileged utilities' },
|
|
73
|
+
{ id: 'A.8.19', name: 'Installation of software on operational systems', theme: 'technological', purpose: 'To control software installation' },
|
|
74
|
+
{ id: 'A.8.20', name: 'Networks security', theme: 'technological', purpose: 'To protect network infrastructure' },
|
|
75
|
+
{ id: 'A.8.21', name: 'Security of network services', theme: 'technological', purpose: 'To ensure security of network services' },
|
|
76
|
+
{ id: 'A.8.22', name: 'Segregation of networks', theme: 'technological', purpose: 'To segregate network segments' },
|
|
77
|
+
{ id: 'A.8.23', name: 'Web filtering', theme: 'technological', purpose: 'To restrict access to external websites' },
|
|
78
|
+
{ id: 'A.8.24', name: 'Use of cryptography', theme: 'technological', purpose: 'To ensure proper use of cryptography' },
|
|
79
|
+
{ id: 'A.8.25', name: 'Secure development life cycle', theme: 'technological', purpose: 'To establish secure development practices' },
|
|
80
|
+
{ id: 'A.8.26', name: 'Application security requirements', theme: 'technological', purpose: 'To identify security requirements' },
|
|
81
|
+
{ id: 'A.8.27', name: 'Secure system architecture and engineering principles', theme: 'technological', purpose: 'To establish secure design principles' },
|
|
82
|
+
{ id: 'A.8.28', name: 'Secure coding', theme: 'technological', purpose: 'To apply secure coding practices' },
|
|
83
|
+
{ id: 'A.8.29', name: 'Security testing in development and acceptance', theme: 'technological', purpose: 'To test security during development' },
|
|
84
|
+
{ id: 'A.8.30', name: 'Outsourced development', theme: 'technological', purpose: 'To manage security of outsourced development' },
|
|
85
|
+
{ id: 'A.8.31', name: 'Separation of development, test and production environments', theme: 'technological', purpose: 'To separate environments' },
|
|
86
|
+
{ id: 'A.8.32', name: 'Change management', theme: 'technological', purpose: 'To control changes' },
|
|
87
|
+
{ id: 'A.8.33', name: 'Test information', theme: 'technological', purpose: 'To protect test information' },
|
|
88
|
+
{ id: 'A.8.34', name: 'Protection of information systems during audit testing', theme: 'technological', purpose: 'To minimize impact of audit testing' }
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
// Control check implementations
|
|
92
|
+
const CONTROL_CHECKS = {
|
|
93
|
+
'A.5.1': (evidence) => {
|
|
94
|
+
const implemented = evidence.policies?.informationSecurity === true;
|
|
95
|
+
return {
|
|
96
|
+
implemented,
|
|
97
|
+
effectiveness: implemented ? 'full' : 'none',
|
|
98
|
+
missingEvidence: implemented ? [] : ['Information security policy document']
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
'A.5.15': (evidence) => {
|
|
102
|
+
const ac = evidence.accessControl;
|
|
103
|
+
const implemented = ac?.implemented === true;
|
|
104
|
+
const tested = ac?.tested === true;
|
|
105
|
+
const documented = ac?.documented === true;
|
|
106
|
+
|
|
107
|
+
let effectiveness = 'none';
|
|
108
|
+
if (implemented && tested && documented) effectiveness = 'full';
|
|
109
|
+
else if (implemented && (tested || documented)) effectiveness = 'partial';
|
|
110
|
+
else if (implemented) effectiveness = 'limited';
|
|
111
|
+
|
|
112
|
+
const missing = [];
|
|
113
|
+
if (!implemented) missing.push('Access control implementation');
|
|
114
|
+
if (!tested) missing.push('Access control testing evidence');
|
|
115
|
+
if (!documented) missing.push('Access control documentation');
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
implemented,
|
|
119
|
+
effectiveness,
|
|
120
|
+
missingEvidence: missing
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Control to technical implementation mappings
|
|
126
|
+
const CONTROL_MAPPINGS = {
|
|
127
|
+
'A.8.24': [
|
|
128
|
+
{ type: 'encryption', description: 'Data encryption implementation', patterns: ['encrypt', 'aes', 'crypto', 'tls'] },
|
|
129
|
+
{ type: 'key-management', description: 'Cryptographic key management', patterns: ['key-vault', 'kms', 'secret'] }
|
|
130
|
+
],
|
|
131
|
+
'A.8.3': [
|
|
132
|
+
{ type: 'access-control', description: 'Information access restriction', patterns: ['rbac', 'acl', 'permission', 'authorize'] },
|
|
133
|
+
{ type: 'authentication', description: 'User authentication', patterns: ['auth', 'login', 'session'] }
|
|
134
|
+
]
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Create an ISO 27001 checklist instance
|
|
139
|
+
* @param {Object} options - Configuration options
|
|
140
|
+
* @param {string} options.version - ISO 27001 version (default: '2022')
|
|
141
|
+
* @returns {Object} Checklist instance
|
|
142
|
+
*/
|
|
143
|
+
export function createIso27001Checklist(options = {}) {
|
|
144
|
+
const version = options.version || '2022';
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
evaluate(evidence) {
|
|
148
|
+
const results = [];
|
|
149
|
+
const controls = getControls();
|
|
150
|
+
|
|
151
|
+
for (const control of controls) {
|
|
152
|
+
const result = checkControl(control.id, evidence);
|
|
153
|
+
results.push(result);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
version,
|
|
158
|
+
results,
|
|
159
|
+
compliant: results.every(r => r.implemented),
|
|
160
|
+
score: (results.filter(r => r.implemented).length / results.length) * 100
|
|
161
|
+
};
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
getControls() {
|
|
165
|
+
return getControls();
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get ISO 27001 controls
|
|
172
|
+
* @param {Object} options - Filter options
|
|
173
|
+
* @param {string} options.groupBy - Group by 'theme' or return flat list
|
|
174
|
+
* @returns {Array|Object} Controls list or grouped object
|
|
175
|
+
*/
|
|
176
|
+
export function getControls(options = {}) {
|
|
177
|
+
if (options.groupBy === 'theme') {
|
|
178
|
+
const grouped = {
|
|
179
|
+
organizational: [],
|
|
180
|
+
people: [],
|
|
181
|
+
physical: [],
|
|
182
|
+
technological: []
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
for (const control of CONTROLS) {
|
|
186
|
+
grouped[control.theme].push(control);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return grouped;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return [...CONTROLS];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Check implementation of a specific control
|
|
197
|
+
* @param {string} controlId - Control identifier (e.g., 'A.5.1')
|
|
198
|
+
* @param {Object} evidence - Evidence for compliance check
|
|
199
|
+
* @returns {Object} Check result
|
|
200
|
+
*/
|
|
201
|
+
export function checkControl(controlId, evidence) {
|
|
202
|
+
const control = CONTROLS.find(c => c.id === controlId);
|
|
203
|
+
const checkFn = CONTROL_CHECKS[controlId];
|
|
204
|
+
|
|
205
|
+
let implemented = false;
|
|
206
|
+
let effectiveness = 'none';
|
|
207
|
+
let missingEvidence = ['Evidence not provided'];
|
|
208
|
+
|
|
209
|
+
if (checkFn) {
|
|
210
|
+
const result = checkFn(evidence);
|
|
211
|
+
implemented = result.implemented;
|
|
212
|
+
effectiveness = result.effectiveness;
|
|
213
|
+
missingEvidence = result.missingEvidence;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
controlId,
|
|
218
|
+
controlName: control?.name || 'Unknown control',
|
|
219
|
+
theme: control?.theme,
|
|
220
|
+
purpose: control?.purpose,
|
|
221
|
+
implemented,
|
|
222
|
+
effectiveness,
|
|
223
|
+
missingEvidence
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Generate Statement of Applicability
|
|
229
|
+
* @param {Array} assessments - Array of control assessments
|
|
230
|
+
* @returns {string} SoA document
|
|
231
|
+
*/
|
|
232
|
+
export function generateSoa(assessments) {
|
|
233
|
+
const date = new Date().toISOString().split('T')[0];
|
|
234
|
+
|
|
235
|
+
let soa = `# Statement of Applicability
|
|
236
|
+
|
|
237
|
+
**Document Date:** ${date}
|
|
238
|
+
**ISO 27001:2022**
|
|
239
|
+
|
|
240
|
+
## Purpose
|
|
241
|
+
|
|
242
|
+
This Statement of Applicability (SoA) documents the applicability and implementation status of ISO 27001:2022 Annex A controls.
|
|
243
|
+
|
|
244
|
+
## Control Assessment
|
|
245
|
+
|
|
246
|
+
| Control ID | Control Name | Applicable | Implemented | Justification |
|
|
247
|
+
|------------|--------------|------------|-------------|---------------|
|
|
248
|
+
`;
|
|
249
|
+
|
|
250
|
+
for (const assessment of assessments) {
|
|
251
|
+
const control = CONTROLS.find(c => c.id === assessment.controlId);
|
|
252
|
+
const name = control?.name || 'Unknown';
|
|
253
|
+
const applicable = assessment.applicable ? 'Yes' : 'No';
|
|
254
|
+
const implemented = assessment.implemented ? 'Yes' : 'No';
|
|
255
|
+
const justification = assessment.justification || '-';
|
|
256
|
+
|
|
257
|
+
soa += `| ${assessment.controlId} | ${name} | ${applicable} | ${implemented} | ${justification} |\n`;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
soa += `
|
|
261
|
+
## Summary
|
|
262
|
+
|
|
263
|
+
- **Total Controls:** ${assessments.length}
|
|
264
|
+
- **Applicable:** ${assessments.filter(a => a.applicable).length}
|
|
265
|
+
- **Not Applicable:** ${assessments.filter(a => !a.applicable).length}
|
|
266
|
+
- **Implemented:** ${assessments.filter(a => a.implemented).length}
|
|
267
|
+
|
|
268
|
+
## Approval
|
|
269
|
+
|
|
270
|
+
_________________________
|
|
271
|
+
Information Security Manager
|
|
272
|
+
|
|
273
|
+
_________________________
|
|
274
|
+
Management Representative
|
|
275
|
+
`;
|
|
276
|
+
|
|
277
|
+
return soa;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Map Annex A control to technical implementations
|
|
282
|
+
* @param {string} controlId - Control identifier
|
|
283
|
+
* @returns {Array} Technical implementation mappings
|
|
284
|
+
*/
|
|
285
|
+
export function mapAnnexAControls(controlId) {
|
|
286
|
+
return CONTROL_MAPPINGS[controlId] || [];
|
|
287
|
+
}
|