iso27001-mcp 0.7.9 → 0.8.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.
Files changed (36) hide show
  1. package/README.md +201 -33
  2. package/dist/index.js +2034 -838
  3. package/dist/seed/evidence-templates/access_review_attestation.md +63 -0
  4. package/dist/seed/evidence-templates/bcp_test_report.md +139 -0
  5. package/dist/seed/evidence-templates/incident_post_mortem.md +142 -0
  6. package/dist/seed/evidence-templates/risk_treatment_sign_off.md +112 -0
  7. package/dist/seed/evidence-templates/supplier_security_questionnaire.md +146 -0
  8. package/dist/seed/evidence-templates/training_acknowledgement.md +75 -0
  9. package/dist/seed/partials/approver_signature.md +31 -0
  10. package/dist/seed/partials/org_header.md +14 -0
  11. package/dist/seed/partials/revision_block.md +7 -0
  12. package/dist/seed/policy-templates/acceptable_use.md +15 -11
  13. package/dist/seed/policy-templates/access_control.md +15 -11
  14. package/dist/seed/policy-templates/asset_management.md +16 -11
  15. package/dist/seed/policy-templates/business_continuity.md +14 -11
  16. package/dist/seed/policy-templates/cryptography.md +13 -11
  17. package/dist/seed/policy-templates/data_classification.md +12 -11
  18. package/dist/seed/policy-templates/incident_response.md +15 -11
  19. package/dist/seed/policy-templates/information_security.md +15 -11
  20. package/dist/seed/policy-templates/physical_security.md +16 -11
  21. package/dist/seed/policy-templates/risk_management.md +14 -11
  22. package/dist/seed/policy-templates/secure_development.md +14 -11
  23. package/dist/seed/policy-templates/supplier_security.md +15 -11
  24. package/dist/seed/procedure-templates/access_provisioning.md +17 -12
  25. package/dist/seed/procedure-templates/asset_onboarding_offboarding.md +16 -12
  26. package/dist/seed/procedure-templates/audit_log_review.md +18 -12
  27. package/dist/seed/procedure-templates/backup_restore.md +15 -12
  28. package/dist/seed/procedure-templates/bcp_testing.md +15 -12
  29. package/dist/seed/procedure-templates/change_management.md +16 -12
  30. package/dist/seed/procedure-templates/cryptographic_key_management.md +18 -12
  31. package/dist/seed/procedure-templates/data_classification_handling.md +17 -12
  32. package/dist/seed/procedure-templates/incident_handling.md +14 -12
  33. package/dist/seed/procedure-templates/secure_development_workflow.md +18 -12
  34. package/dist/seed/procedure-templates/supplier_onboarding.md +15 -12
  35. package/dist/seed/procedure-templates/vulnerability_management.md +18 -12
  36. package/package.json +2 -3
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # iso27001-mcp
2
2
 
3
- [![Socket Badge](https://badge.socket.dev/npm/package/iso27001-mcp/0.7.9)](https://socket.dev/npm/package/iso27001-mcp/overview/0.7.9)
3
+ [![Socket Badge](https://badge.socket.dev/npm/package/iso27001-mcp/0.8.1)](https://socket.dev/npm/package/iso27001-mcp/overview/0.8.1)
4
4
  [![npm version](https://img.shields.io/npm/v/iso27001-mcp.svg)](https://npmjs.com/package/iso27001-mcp)
5
5
  [![Live Demo](https://img.shields.io/badge/demo-live-blue)](https://sushegaad.github.io/MCP-Server-for-ISO27001/)
6
6
 
@@ -31,6 +31,20 @@ Claude ──MCP──► iso27001-mcp ──► encrypted SQLite (isms.db)
31
31
  - [Configuration](#configuration)
32
32
  - [Connecting to Claude](#connecting-to-claude)
33
33
  - [Tools Reference](#tools-reference)
34
+ - [Group 1 — Control Registry](#group-1--control-registry-minimum-role-viewer)
35
+ - [Group 2 — Gap Analysis](#group-2--gap-analysis-reads-viewer-writes-analyst)
36
+ - [Group 3 — Risk Management](#group-3--risk-management-reads-viewer-writes-analyst)
37
+ - [Group 4 — Policy Management](#group-4--policy-management-reads-viewer-create-analyst-update-admin)
38
+ - [Group 5 — Statement of Applicability](#group-5--statement-of-applicability-minimum-role-analyst)
39
+ - [Group 6 — Audit Management](#group-6--audit-management-reads-viewer-writes-admin)
40
+ - [Group 7 — Evidence Tracking](#group-7--evidence-tracking-reads-viewer-writes-analyst)
41
+ - [Group 8 — Server Info](#group-8--server-info-minimum-role-viewer)
42
+ - [Group 9 — Admin & Key Management](#group-9--admin--key-management-minimum-role-admin)
43
+ - [Group 10 — Organisation Profile](#group-10--organisation-profile-minimum-role-admin-for-writes-viewer-for-reads)
44
+ - [Group 11 — Procedure Management](#group-11--procedure-management-reads-viewer-createexport-analyst-update-admin)
45
+ - [Group 12 — Management Review](#group-12--management-review-reads-viewer-writes-admin--clause-93)
46
+ - [Group 13 — Improvement Plan](#group-13--improvement-plan-reads-viewer-writes-analyst--clause-101)
47
+ - [Group 14 — Evidence Templates](#group-14--evidence-templates-reads-viewer-generate-analyst)
34
48
  - [MCP Resources](#mcp-resources)
35
49
  - [Architecture](#architecture)
36
50
  - [Modes](#modes)
@@ -90,7 +104,7 @@ iso27001-mcp keygen --label "Me" --role admin
90
104
 
91
105
  The raw key (`iso27001_...`) is printed **once** and never stored in plaintext. Copy it immediately.
92
106
 
93
- > Three roles are available: `viewer` (25 read-only tools), `analyst` (40 tools), `admin` (all 50 tools). Use `admin` for your personal key.
107
+ > Three roles are available: `viewer` (31 read-only tools), `analyst` (49 tools), `admin` (all 63 tools). Use `admin` for your personal key.
94
108
 
95
109
  ### Step 4 — Add to Claude Desktop
96
110
 
@@ -121,7 +135,7 @@ Add the following block, substituting your values from Steps 2 and 3:
121
135
 
122
136
  ### Step 5 — Restart Claude Desktop and verify
123
137
 
124
- Fully quit and reopen Claude Desktop. You should see 50 tools in the MCP tools panel (hammer icon). Then ask Claude:
138
+ Fully quit and reopen Claude Desktop. You should see 63 tools in the MCP tools panel (hammer icon). Then ask Claude:
125
139
 
126
140
  > *"Use get_server_info to check the server is running."*
127
141
 
@@ -287,7 +301,7 @@ Full variable reference:
287
301
  | `HMAC_SECRET` | ✅ | — | 32-byte hex secret for HMAC-signing API keys |
288
302
  | `DB_ENCRYPTION_KEY` | ✅ | — | 32-byte hex key for AES-256 SQLite encryption |
289
303
  | `DB_PATH` | | `./isms.db` | Path to the encrypted database file |
290
- | `AUDIT_LOG_PATH` | | `./audit.log` | Path for the append-only JSON-L audit log |
304
+ | `AUDIT_LOG_PATH` | | `./audit.jsonl` | Path for the append-only JSON-L audit log (`.jsonl` or `.log` only) |
291
305
  | `RATE_LIMIT_RPM` | | `500` | Tool calls per minute per API key |
292
306
  | `SESSION_TTL_HOURS` | | `4` | SSE session TTL (hosted/team modes) |
293
307
  | `SSE_PORT` | | `3000` | Port for the SSE server (hosted/team modes) |
@@ -307,10 +321,10 @@ The server requires an API key on every tool call. Generate one for yourself:
307
321
  # Viewer — read-only access to 25 tools
308
322
  iso27001-mcp keygen --label "Alice" --role viewer
309
323
 
310
- # Analyst — read + write for gap/risk/policy/procedure/evidence tools (40 tools)
324
+ # Analyst — read + write for gap/risk/policy/procedure/evidence tools (49 tools)
311
325
  iso27001-mcp keygen --label "Bob" --role analyst --expires 90d
312
326
 
313
- # Admin — all 50 tools including audit log and key management
327
+ # Admin — all 63 tools including audit log and key management
314
328
  iso27001-mcp keygen --label "CISO" --role admin --expires 1y
315
329
  ```
316
330
 
@@ -375,7 +389,7 @@ export DB_PATH=$HOME/.iso27001/isms.db
375
389
 
376
390
  ## Tools Reference
377
391
 
378
- The server exposes **50 tools** across 11 groups. All tools require a valid API key. The minimum role required is noted per group; `✅` marks required parameters, `—` marks optional ones.
392
+ The server exposes **63 tools** across 14 groups. All tools require a valid API key. The minimum role required is noted per group; `✅` marks required parameters, `—` marks optional ones.
379
393
 
380
394
  ---
381
395
 
@@ -913,6 +927,147 @@ Export a procedure as Markdown or JSON.
913
927
 
914
928
  ---
915
929
 
930
+ ### Group 12 — Management Review *(reads: viewer+, writes: admin)* — Clause 9.3
931
+
932
+ #### `create_management_review`
933
+ Schedule a management review meeting.
934
+
935
+ | Parameter | Req | Type | Values / Notes |
936
+ |-----------|-----|------|----------------|
937
+ | `title` | ✅ | string | Review title |
938
+ | `review_date` | ✅ | string | `YYYY-MM-DD` |
939
+ | `chair` | ✅ | string | Review chair / CISO name |
940
+ | `attendees` | — | array | List of attendee names |
941
+ | `agenda` | — | string | Meeting agenda |
942
+
943
+ #### `record_review_input`
944
+ Record an input item to a management review (e.g. audit results, risk summary, performance metrics).
945
+
946
+ | Parameter | Req | Type | Values / Notes |
947
+ |-----------|-----|------|----------------|
948
+ | `review_id` | ✅ | string (UUID) | |
949
+ | `input_type` | ✅ | enum | `audit_results` \| `risk_summary` \| `objective_performance` \| `nonconformities` \| `previous_actions` \| `changes` \| `resources` \| `stakeholder_feedback` \| `other` |
950
+ | `summary` | ✅ | string | |
951
+ | `detail` | — | string | Supporting detail |
952
+
953
+ #### `record_review_output`
954
+ Record a decision or action item from a management review.
955
+
956
+ | Parameter | Req | Type | Values / Notes |
957
+ |-----------|-----|------|----------------|
958
+ | `review_id` | ✅ | string (UUID) | |
959
+ | `output_type` | ✅ | enum | `improvement_opportunity` \| `resource_decision` \| `policy_change` \| `objective_change` \| `other` |
960
+ | `description` | ✅ | string | |
961
+ | `owner` | — | string | |
962
+ | `due_date` | — | string | `YYYY-MM-DD` |
963
+
964
+ #### `complete_management_review`
965
+ Mark a management review as complete and record the outcome.
966
+
967
+ | Parameter | Req | Type | Values / Notes |
968
+ |-----------|-----|------|----------------|
969
+ | `review_id` | ✅ | string (UUID) | |
970
+ | `outcome_summary` | ✅ | string | |
971
+
972
+ #### `get_management_review`
973
+ Fetch a management review with all inputs, outputs, and status.
974
+
975
+ | Parameter | Req | Type | Values / Notes |
976
+ |-----------|-----|------|----------------|
977
+ | `review_id` | ✅ | string (UUID) | |
978
+
979
+ #### `list_management_reviews`
980
+ List management reviews with optional status filter.
981
+
982
+ | Parameter | Req | Type | Values / Notes |
983
+ |-----------|-----|------|----------------|
984
+ | `status` | — | enum | `scheduled` \| `in_progress` \| `completed` |
985
+ | `limit` | — | integer | Default: `20`, max `100` |
986
+ | `offset` | — | integer | Default: `0` |
987
+
988
+ ---
989
+
990
+ ### Group 13 — Improvement Plan *(reads: viewer+, writes: analyst+)* — Clause 10.1
991
+
992
+ #### `create_improvement_opportunity`
993
+ Register an improvement opportunity, typically identified during a management review or audit.
994
+
995
+ | Parameter | Req | Type | Values / Notes |
996
+ |-----------|-----|------|----------------|
997
+ | `title` | ✅ | string | |
998
+ | `description` | ✅ | string | |
999
+ | `source` | ✅ | enum | `audit` \| `management_review` \| `incident` \| `risk_assessment` \| `self_assessment` \| `other` |
1000
+ | `priority` | — | enum | `low` \| `medium` \| `high` \| `critical` — default: `medium` |
1001
+ | `owner` | — | string | |
1002
+ | `due_date` | — | string | `YYYY-MM-DD` |
1003
+ | `related_controls` | — | array | Control IDs |
1004
+ | `review_id` | — | string (UUID) | Link to a management review output |
1005
+
1006
+ #### `update_improvement_opportunity`
1007
+ Update the status, owner, or due date of an improvement opportunity.
1008
+
1009
+ | Parameter | Req | Type | Values / Notes |
1010
+ |-----------|-----|------|----------------|
1011
+ | `opportunity_id` | ✅ | string (UUID) | |
1012
+ | `status` | — | enum | `open` \| `in_progress` \| `completed` \| `cancelled` |
1013
+ | `owner` | — | string | |
1014
+ | `due_date` | — | string | `YYYY-MM-DD` |
1015
+ | `resolution_notes` | — | string | Required when closing |
1016
+
1017
+ #### `get_improvement_opportunity`
1018
+ Fetch a single improvement opportunity by ID.
1019
+
1020
+ | Parameter | Req | Type | Values / Notes |
1021
+ |-----------|-----|------|----------------|
1022
+ | `opportunity_id` | ✅ | string (UUID) | |
1023
+
1024
+ #### `list_improvement_opportunities`
1025
+ List improvement opportunities with optional filters.
1026
+
1027
+ | Parameter | Req | Type | Values / Notes |
1028
+ |-----------|-----|------|----------------|
1029
+ | `status` | — | enum | `open` \| `in_progress` \| `completed` \| `cancelled` |
1030
+ | `priority` | — | enum | `low` \| `medium` \| `high` \| `critical` |
1031
+ | `source` | — | enum | Any source enum value above |
1032
+ | `limit` | — | integer | Default: `50`, max `100` |
1033
+ | `offset` | — | integer | Default: `0` |
1034
+
1035
+ ---
1036
+
1037
+ ### Group 14 — Evidence Templates *(reads: viewer+, generate: analyst+)*
1038
+
1039
+ #### `generate_evidence_document`
1040
+ Render a Mustache evidence template and store it. The document is dual-written to both the `evidence` table and the `generated_evidence` table for tracking and version history.
1041
+
1042
+ | Parameter | Req | Type | Values / Notes |
1043
+ |-----------|-----|------|----------------|
1044
+ | `template_type` | ✅ | enum | `access_review_attestation` \| `bcp_test_report` \| `incident_post_mortem` \| `risk_treatment_sign_off` \| `supplier_security_questionnaire` \| `training_acknowledgement` |
1045
+ | `title` | ✅ | string | Document title |
1046
+ | `generated_by` | ✅ | string | Author or system that generated the document |
1047
+ | `organisation_name` | — | string | Auto-injected from org profile if set |
1048
+ | `control_id` | — | string | Link to a specific control (default: `general`) |
1049
+ | `vars` | — | object | Additional Mustache template variables |
1050
+
1051
+ #### `get_evidence_document`
1052
+ Fetch a generated evidence document by ID, including rendered content and clause/control mappings.
1053
+
1054
+ | Parameter | Req | Type | Values / Notes |
1055
+ |-----------|-----|------|----------------|
1056
+ | `document_id` | ✅ | string (UUID) | |
1057
+
1058
+ #### `list_evidence_documents`
1059
+ List generated evidence documents with optional filters.
1060
+
1061
+ | Parameter | Req | Type | Values / Notes |
1062
+ |-----------|-----|------|----------------|
1063
+ | `template_type` | — | enum | Filter to a specific template type |
1064
+ | `generated_by` | — | string | Filter by author |
1065
+ | `control_id` | — | string | Filter by linked control |
1066
+ | `limit` | — | integer | Default: `20`, max `100` |
1067
+ | `offset` | — | integer | Default: `0` |
1068
+
1069
+ ---
1070
+
916
1071
  ## MCP Resources
917
1072
 
918
1073
  In addition to tools, the server exposes ISMS artefacts as browseable **MCP Resources** under the `iso27001://` URI scheme. Claude can reference these directly without a tool call — ideal for inline document review, cross-referencing controls, and long-context analysis.
@@ -967,34 +1122,37 @@ Resources are read-only. Write operations always go through tools (which enforce
967
1122
  │ Claude (LLM) │
968
1123
  └──────────┬───────────────────────────────┬──────────────┘
969
1124
  │ MCP Tools (read/write) │ MCP Resources (read-only)
970
- 50 tools, RBAC enforced │ 12 iso27001:// URIs
1125
+ 63 tools, RBAC enforced │ 12 iso27001:// URIs
971
1126
  ┌──────────▼───────────────────────────────▼──────────────┐
972
1127
  │ iso27001-mcp server │
973
1128
  │ │
974
1129
  │ ┌─────────────────────────────────────────────────┐ │
975
- │ │ 9-Step Security Pipeline │ │
1130
+ │ │ 7-Step Security Pipeline │ │
976
1131
  │ │ │ │
977
- │ │ 1. Extract API key (meta or MCP_API_KEY env) │ │
978
- │ │ 2. validateKey() HMAC-SHA256, timing-safe │ │
1132
+ │ │ 1. Extract credential (_meta.apiKey / env) │ │
1133
+ │ │ 2. Auth — session token OR validateKey() │ │
1134
+ │ │ SSE sessions use opaque token (no raw key) │ │
979
1135
  │ │ 3. checkRateLimit() sliding 60s window (RPM) │ │
980
- │ │ 4. loadRole() viewer | analyst | admin │ │
981
- │ │ 5. assertPermission() RBAC check │ │
982
- │ │ 6. sanitiseParams() strip injection patterns │ │
983
- │ │ 7. Domain handler business logic │ │
984
- │ │ 8. writeAuditEvent() tamper-evident row_hash │ │
985
- │ │ 9. Return result or structured McpError │ │
1136
+ │ │ 4. assertPermission() RBAC check │ │
1137
+ │ │ 5. sanitiseParams() strip injection patterns │ │
1138
+ │ │ 6. Domain handler business logic │ │
1139
+ │ │ 7. writeAuditEvent() HMAC chain + row_hash │ │
986
1140
  │ └─────────────────────────────────────────────────┘ │
987
1141
  │ │
988
1142
  │ ┌─────────────┐ ┌──────────┐ ┌────────────────────┐ │
989
1143
  │ │ Controls │ │ Risks │ │ Policies & │ │
990
1144
  │ │ Gap Assess │ │ Register │ │ Procedures │ │
991
- │ │ SoA │ │ Treatmts │ │ (Mustache tmpl) │ │
1145
+ │ │ SoA │ │ Treatmts │ │ (Mustache+partls) │ │
992
1146
  │ └─────────────┘ └──────────┘ └────────────────────┘ │
993
1147
  │ ┌─────────────┐ ┌──────────┐ ┌────────────────────┐ │
994
- │ │ Audits │ │ Evidence │ │ Org Profile & │ │
995
- │ │ Findings │ │ Jira/GH │ │ Audit Log │ │
996
- │ │ CARs │ │ Gaps │ │ (tamper-evident) │ │
1148
+ │ │ Audits │ │ Evidence │ │ Mgmt Review & │ │
1149
+ │ │ Findings │ │ Jira/GH │ │ Improvement Plan │ │
1150
+ │ │ CARs │ │ Tmplts │ │ (Clauses 9.3/10.1)│ │
997
1151
  │ └─────────────┘ └──────────┘ └────────────────────┘ │
1152
+ │ ┌─────────────────────────────────────────────────┐ │
1153
+ │ │ Org Profile · Audit Log (HMAC-SHA256 chain) │ │
1154
+ │ │ Session Token Store · API Key RBAC (63 tools) │ │
1155
+ │ └─────────────────────────────────────────────────┘ │
998
1156
  │ │
999
1157
  │ ┌─────────────────────────────────────────────────┐ │
1000
1158
  │ │ AES-256 encrypted SQLite (isms.db) │ │
@@ -1006,11 +1164,14 @@ Resources are read-only. Write operations always go through tools (which enforce
1006
1164
 
1007
1165
  ### Database
1008
1166
 
1009
- All data is stored in a single encrypted SQLite file (`isms.db`) using AES-256 via `better-sqlite3-multiple-ciphers`. The schema is managed by three SQL migrations applied automatically on first startup:
1167
+ All data is stored in a single encrypted SQLite file (`isms.db`) using AES-256 via `better-sqlite3-multiple-ciphers`. The schema is managed by six SQL migrations applied automatically on first startup:
1010
1168
 
1011
1169
  - `0001_initial.sql` — 17 tables covering every ISMS domain (controls, gap assessments, risks, policies, audits, evidence, API keys, audit log, and more)
1012
1170
  - `0002_fts_index.sql` — FTS5 full-text search index on controls, plus 12 performance indexes
1013
1171
  - `0003_org_profile_procedures.sql` — `organization_profile` singleton table, `procedures` table, and `procedure_versions` history table
1172
+ - `0004_management_review_improvement.sql` — `management_reviews`, `review_inputs`, `review_outputs`, and `improvement_opportunities` tables (Clauses 9.3 and 10.1)
1173
+ - `0005_evidence_documents.sql` — `generated_evidence` table for Mustache-rendered evidence documents with dual-write to `evidence`
1174
+ - `0006_audit_log_hmac.sql` — adds `prev_hash` column to `audit_log` for HMAC chain integrity
1014
1175
 
1015
1176
  ### Seed Data
1016
1177
 
@@ -1023,7 +1184,7 @@ On first startup, `seedAll()` inserts all ISO 27001 reference data and verifies
1023
1184
 
1024
1185
  ### Security Pipeline
1025
1186
 
1026
- Every tool call passes through the same 9-step pipeline before any business logic runs. Audit events are always written — including on authentication failure and RBAC denial — so the log is a complete record of all attempts, not just successful ones.
1187
+ Every tool call passes through the same 7-step pipeline before any business logic runs. SSE sessions use an opaque session token so the raw API key is never retained in server memory after the initial `/sse` handshake. Audit events are always written — including on authentication failure and RBAC denial — so the log is a complete record of all attempts, not just successful ones.
1027
1188
 
1028
1189
  ### Business Rules Enforced
1029
1190
 
@@ -1044,9 +1205,9 @@ Three roles with strict hierarchy. A key can only call tools at or below its ass
1044
1205
 
1045
1206
  | Role | Tools available | Typical user |
1046
1207
  |------|----------------|--------------|
1047
- | `viewer` | 25 (all read-only tools) | Auditor, stakeholder |
1048
- | `analyst` | 40 (reads + gap/risk/policy/procedure/evidence writes) | ISMS practitioner, consultant |
1049
- | `admin` | 50 (all tools, including org profile, audit log and key management) | CISO, ISMS owner |
1208
+ | `viewer` | 31 (all read-only tools) | Auditor, stakeholder |
1209
+ | `analyst` | 49 (reads + gap/risk/policy/procedure/evidence/improvement writes) | ISMS practitioner, consultant |
1210
+ | `admin` | 63 (all tools, including org profile, audit management, audit log and key management) | CISO, ISMS owner |
1050
1211
 
1051
1212
  ---
1052
1213
 
@@ -1123,7 +1284,7 @@ npm run typecheck
1123
1284
  # Build dist/
1124
1285
  npm run build
1125
1286
 
1126
- # Run all tests (404 unit + integration tests)
1287
+ # Run all tests (470 unit + integration tests)
1127
1288
  npm test
1128
1289
 
1129
1290
  # Watch mode
@@ -1147,12 +1308,13 @@ src/
1147
1308
  ├── server.ts McpServer factory — registers tools + resources
1148
1309
  ├── auth/
1149
1310
  │ ├── api-key.ts Key generation, HMAC validation, expiry, revocation
1150
- └── rbac.ts Permission matrix (50 tools × 3 roles)
1311
+ ├── rbac.ts Permission matrix (63 tools × 3 roles)
1312
+ │ └── session-store.ts SSE session token store (opaque token → keyHash + role)
1151
1313
  ├── security/
1152
1314
  │ ├── sanitise.ts Prompt-injection stripping for free-text fields
1153
1315
  │ ├── rate-limiter.ts Sliding-window RPM counter per key hash
1154
1316
  │ ├── secrets.ts Env var validation (fail-fast on startup)
1155
- │ └── validate.ts Zod schemas for all 50 tool inputs
1317
+ │ └── validate.ts Zod schemas for all 63 tool inputs
1156
1318
  ├── audit/
1157
1319
  │ └── logger.ts Tamper-evident audit event writer
1158
1320
  ├── db/
@@ -1166,7 +1328,9 @@ src/
1166
1328
  │ ├── version-mapping.json 125 cross-version mappings
1167
1329
  │ ├── clause-requirements.json 41 clause requirements (clauses 4–10)
1168
1330
  │ ├── policy-templates/ 12 Mustache .md policy templates
1169
- └── procedure-templates/ 12 Mustache .md procedure templates
1331
+ ├── procedure-templates/ 12 Mustache .md procedure templates
1332
+ │ ├── evidence-templates/ 6 Mustache .md evidence document templates
1333
+ │ └── partials/ Shared Mustache partials (org_header, revision_block, approver_signature)
1170
1334
  ├── tools/
1171
1335
  │ ├── index.ts Tool registry and security pipeline
1172
1336
  │ ├── controls.ts Group 1: Control Registry (7 tools)
@@ -1179,7 +1343,10 @@ src/
1179
1343
  │ ├── server-info.ts Group 8: Server Info (1 tool)
1180
1344
  │ ├── org-profile.ts Group 10: Organisation Profile (2 tools) + loadOrgProfileDefaults helper
1181
1345
  │ ├── procedures.ts Group 11: Procedure Management (5 tools)
1182
- └── template-utils.ts Shared loadTemplate / stripFrontmatter helpers
1346
+ ├── management-review.ts Group 12: Management Review — Clause 9.3 (6 tools)
1347
+ │ ├── improvement-plan.ts Group 13: Improvement Plan — Clause 10.1 (4 tools)
1348
+ │ ├── evidence-templates.ts Group 14: Evidence Templates (3 tools)
1349
+ │ └── template-utils.ts Shared loadTemplate / stripFrontmatter / loadPartials helpers
1183
1350
  ├── resources/
1184
1351
  │ ├── index.ts Registers all 12 MCP Resources
1185
1352
  │ ├── resource-auth.ts Slim auth helper for resource callbacks
@@ -1225,10 +1392,11 @@ The SQLite database (`isms.db`) is encrypted at rest using AES-256 via `better-s
1225
1392
  Every tool call writes a row to `audit_log` with a `row_hash` computed as:
1226
1393
 
1227
1394
  ```
1228
- SHA-256(timestamp | tool | key_hash | outcome)
1395
+ HMAC-SHA256(HMAC_SECRET, id | timestamp | tool | key_hash | role |
1396
+ params_json | outcome | error_message | duration_ms | prev_hash)
1229
1397
  ```
1230
1398
 
1231
- Any modification to an audit row after insertion will cause `verifyRowHash()` to fail. The same events are also appended in JSON-L format to `AUDIT_LOG_PATH` for off-database retention and SIEM ingestion.
1399
+ The `prev_hash` field chains each row to its predecessor — insertion, deletion, or reordering of rows is detectable via `verifyRowHash()` and `verifyChain()`. The same events are appended in JSON-L format to `AUDIT_LOG_PATH` for off-database retention and SIEM ingestion. The log path is validated on write to reject paths inside system directories (`/etc`, `/proc`, `/sys`, `/dev`).
1232
1400
 
1233
1401
  ### Production Checklist
1234
1402