vaspera 2.8.0 → 2.9.0
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/CHANGELOG.md +55 -0
- package/README.md +111 -7
- package/dist/__tests__/agents/adversary/tactics/api.test.d.ts +5 -0
- package/dist/__tests__/agents/adversary/tactics/api.test.d.ts.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/api.test.js +369 -0
- package/dist/__tests__/agents/adversary/tactics/api.test.js.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/llm.test.d.ts +5 -0
- package/dist/__tests__/agents/adversary/tactics/llm.test.d.ts.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/llm.test.js +409 -0
- package/dist/__tests__/agents/adversary/tactics/llm.test.js.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/registry.test.d.ts +7 -0
- package/dist/__tests__/agents/adversary/tactics/registry.test.d.ts.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/registry.test.js +74 -0
- package/dist/__tests__/agents/adversary/tactics/registry.test.js.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/web-app.test.d.ts +7 -0
- package/dist/__tests__/agents/adversary/tactics/web-app.test.d.ts.map +1 -0
- package/dist/__tests__/agents/adversary/tactics/web-app.test.js +374 -0
- package/dist/__tests__/agents/adversary/tactics/web-app.test.js.map +1 -0
- package/dist/__tests__/compliance-bundle.test.d.ts +9 -0
- package/dist/__tests__/compliance-bundle.test.d.ts.map +1 -0
- package/dist/__tests__/compliance-bundle.test.js +344 -0
- package/dist/__tests__/compliance-bundle.test.js.map +1 -0
- package/dist/__tests__/healthcare-compliance.test.d.ts +9 -0
- package/dist/__tests__/healthcare-compliance.test.d.ts.map +1 -0
- package/dist/__tests__/healthcare-compliance.test.js +233 -0
- package/dist/__tests__/healthcare-compliance.test.js.map +1 -0
- package/dist/action/diff-mode.d.ts +124 -8
- package/dist/action/diff-mode.d.ts.map +1 -1
- package/dist/action/diff-mode.js +384 -65
- package/dist/action/diff-mode.js.map +1 -1
- package/dist/action/diff-mode.test.js +3 -3
- package/dist/action/diff-mode.test.js.map +1 -1
- package/dist/action/pr-comment.test.js +1 -0
- package/dist/action/pr-comment.test.js.map +1 -1
- package/dist/action/sarif-upload.test.js +1 -0
- package/dist/action/sarif-upload.test.js.map +1 -1
- package/dist/agents/adversary/config.d.ts +25 -4
- package/dist/agents/adversary/config.d.ts.map +1 -1
- package/dist/agents/adversary/config.js +38 -8
- package/dist/agents/adversary/config.js.map +1 -1
- package/dist/agents/adversary/index.d.ts +7 -0
- package/dist/agents/adversary/index.d.ts.map +1 -1
- package/dist/agents/adversary/index.js +83 -1
- package/dist/agents/adversary/index.js.map +1 -1
- package/dist/agents/adversary/reporting/compliance-mapper.d.ts +108 -0
- package/dist/agents/adversary/reporting/compliance-mapper.d.ts.map +1 -0
- package/dist/agents/adversary/reporting/compliance-mapper.js +391 -0
- package/dist/agents/adversary/reporting/compliance-mapper.js.map +1 -0
- package/dist/agents/adversary/reporting/index.d.ts +10 -0
- package/dist/agents/adversary/reporting/index.d.ts.map +1 -0
- package/dist/agents/adversary/reporting/index.js +10 -0
- package/dist/agents/adversary/reporting/index.js.map +1 -0
- package/dist/agents/adversary/reporting/poc-generator.d.ts +44 -0
- package/dist/agents/adversary/reporting/poc-generator.d.ts.map +1 -0
- package/dist/agents/adversary/reporting/poc-generator.js +308 -0
- package/dist/agents/adversary/reporting/poc-generator.js.map +1 -0
- package/dist/agents/adversary/tactics/api.d.ts +13 -0
- package/dist/agents/adversary/tactics/api.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/api.js +815 -0
- package/dist/agents/adversary/tactics/api.js.map +1 -0
- package/dist/agents/adversary/tactics/auth.d.ts +13 -0
- package/dist/agents/adversary/tactics/auth.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/auth.js +676 -0
- package/dist/agents/adversary/tactics/auth.js.map +1 -0
- package/dist/agents/adversary/tactics/index.d.ts +129 -0
- package/dist/agents/adversary/tactics/index.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/index.js +199 -0
- package/dist/agents/adversary/tactics/index.js.map +1 -0
- package/dist/agents/adversary/tactics/infra.d.ts +13 -0
- package/dist/agents/adversary/tactics/infra.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/infra.js +827 -0
- package/dist/agents/adversary/tactics/infra.js.map +1 -0
- package/dist/agents/adversary/tactics/injection.d.ts +12 -0
- package/dist/agents/adversary/tactics/injection.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/injection.js +549 -0
- package/dist/agents/adversary/tactics/injection.js.map +1 -0
- package/dist/agents/adversary/tactics/llm.d.ts +13 -0
- package/dist/agents/adversary/tactics/llm.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/llm.js +767 -0
- package/dist/agents/adversary/tactics/llm.js.map +1 -0
- package/dist/agents/adversary/tactics/web-app.d.ts +13 -0
- package/dist/agents/adversary/tactics/web-app.d.ts.map +1 -0
- package/dist/agents/adversary/tactics/web-app.js +717 -0
- package/dist/agents/adversary/tactics/web-app.js.map +1 -0
- package/dist/agents/adversary/types.d.ts +66 -10
- package/dist/agents/adversary/types.d.ts.map +1 -1
- package/dist/agents/zero-day-hunter.d.ts +1 -1
- package/dist/agents/zero-day-hunter.d.ts.map +1 -1
- package/dist/analysis/data-flow.d.ts +154 -0
- package/dist/analysis/data-flow.d.ts.map +1 -0
- package/dist/analysis/data-flow.js +393 -0
- package/dist/analysis/data-flow.js.map +1 -0
- package/dist/analysis/index.d.ts +9 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +9 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/badge-service/index.d.ts +144 -0
- package/dist/badge-service/index.d.ts.map +1 -0
- package/dist/badge-service/index.js +206 -0
- package/dist/badge-service/index.js.map +1 -0
- package/dist/certification/types.d.ts +1 -1
- package/dist/certification/types.d.ts.map +1 -1
- package/dist/certification/types.js.map +1 -1
- package/dist/commands/certification/certify.d.ts.map +1 -1
- package/dist/commands/certification/certify.js +18 -4
- package/dist/commands/certification/certify.js.map +1 -1
- package/dist/compliance/attestation.d.ts +39 -0
- package/dist/compliance/attestation.d.ts.map +1 -0
- package/dist/compliance/attestation.js +364 -0
- package/dist/compliance/attestation.js.map +1 -0
- package/dist/compliance/cfr42-part2.d.ts +42 -0
- package/dist/compliance/cfr42-part2.d.ts.map +1 -0
- package/dist/compliance/cfr42-part2.js +408 -0
- package/dist/compliance/cfr42-part2.js.map +1 -0
- package/dist/compliance/compliance-bundle.d.ts +100 -0
- package/dist/compliance/compliance-bundle.d.ts.map +1 -0
- package/dist/compliance/compliance-bundle.js +210 -0
- package/dist/compliance/compliance-bundle.js.map +1 -0
- package/dist/compliance/healthcare-bundle.d.ts +68 -0
- package/dist/compliance/healthcare-bundle.d.ts.map +1 -0
- package/dist/compliance/healthcare-bundle.js +104 -0
- package/dist/compliance/healthcare-bundle.js.map +1 -0
- package/dist/compliance/hipaa.d.ts.map +1 -1
- package/dist/compliance/hipaa.js +14 -11
- package/dist/compliance/hipaa.js.map +1 -1
- package/dist/compliance/index.d.ts +10 -2
- package/dist/compliance/index.d.ts.map +1 -1
- package/dist/compliance/index.js +9 -3
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/mapper.d.ts.map +1 -1
- package/dist/compliance/mapper.js +3 -17
- package/dist/compliance/mapper.js.map +1 -1
- package/dist/compliance/nist-800-53.d.ts +22 -6
- package/dist/compliance/nist-800-53.d.ts.map +1 -1
- package/dist/compliance/nist-800-53.js +264 -272
- package/dist/compliance/nist-800-53.js.map +1 -1
- package/dist/compliance/report.d.ts +31 -2
- package/dist/compliance/report.d.ts.map +1 -1
- package/dist/compliance/report.js +255 -4
- package/dist/compliance/report.js.map +1 -1
- package/dist/compliance/types.d.ts +1 -1
- package/dist/compliance/types.d.ts.map +1 -1
- package/dist/config/flags.d.ts +12 -12
- package/dist/cost/index.d.ts +1 -1
- package/dist/cost/index.d.ts.map +1 -1
- package/dist/cost/index.js +1 -1
- package/dist/cost/index.js.map +1 -1
- package/dist/cost/tracker.d.ts +64 -0
- package/dist/cost/tracker.d.ts.map +1 -1
- package/dist/cost/tracker.js +165 -0
- package/dist/cost/tracker.js.map +1 -1
- package/dist/eval/fixtures/healthcare/audit-gaps.d.ts +28 -0
- package/dist/eval/fixtures/healthcare/audit-gaps.d.ts.map +1 -0
- package/dist/eval/fixtures/healthcare/audit-gaps.js +90 -0
- package/dist/eval/fixtures/healthcare/audit-gaps.js.map +1 -0
- package/dist/eval/fixtures/healthcare/consent-bypass.d.ts +31 -0
- package/dist/eval/fixtures/healthcare/consent-bypass.d.ts.map +1 -0
- package/dist/eval/fixtures/healthcare/consent-bypass.js +61 -0
- package/dist/eval/fixtures/healthcare/consent-bypass.js.map +1 -0
- package/dist/eval/fixtures/healthcare/phi-in-logs.d.ts +24 -0
- package/dist/eval/fixtures/healthcare/phi-in-logs.d.ts.map +1 -0
- package/dist/eval/fixtures/healthcare/phi-in-logs.js +41 -0
- package/dist/eval/fixtures/healthcare/phi-in-logs.js.map +1 -0
- package/dist/evidence/collector.d.ts +21 -0
- package/dist/evidence/collector.d.ts.map +1 -0
- package/dist/evidence/collector.js +340 -0
- package/dist/evidence/collector.js.map +1 -0
- package/dist/evidence/index.d.ts +11 -0
- package/dist/evidence/index.d.ts.map +1 -0
- package/dist/evidence/index.js +12 -0
- package/dist/evidence/index.js.map +1 -0
- package/dist/evidence/store.d.ts +39 -0
- package/dist/evidence/store.d.ts.map +1 -0
- package/dist/evidence/store.js +173 -0
- package/dist/evidence/store.js.map +1 -0
- package/dist/evidence/types.d.ts +175 -0
- package/dist/evidence/types.d.ts.map +1 -0
- package/dist/evidence/types.js +9 -0
- package/dist/evidence/types.js.map +1 -0
- package/dist/exporters/checkmarx.d.ts +18 -0
- package/dist/exporters/checkmarx.d.ts.map +1 -0
- package/dist/exporters/checkmarx.js +203 -0
- package/dist/exporters/checkmarx.js.map +1 -0
- package/dist/exporters/index.d.ts +22 -0
- package/dist/exporters/index.d.ts.map +1 -0
- package/dist/exporters/index.js +41 -0
- package/dist/exporters/index.js.map +1 -0
- package/dist/exporters/snyk.d.ts +18 -0
- package/dist/exporters/snyk.d.ts.map +1 -0
- package/dist/exporters/snyk.js +119 -0
- package/dist/exporters/snyk.js.map +1 -0
- package/dist/exporters/sonarqube.d.ts +18 -0
- package/dist/exporters/sonarqube.d.ts.map +1 -0
- package/dist/exporters/sonarqube.js +125 -0
- package/dist/exporters/sonarqube.js.map +1 -0
- package/dist/exporters/types.d.ts +190 -0
- package/dist/exporters/types.d.ts.map +1 -0
- package/dist/exporters/types.js +9 -0
- package/dist/exporters/types.js.map +1 -0
- package/dist/frontier/index.d.ts +12 -0
- package/dist/frontier/index.d.ts.map +1 -0
- package/dist/frontier/index.js +12 -0
- package/dist/frontier/index.js.map +1 -0
- package/dist/frontier/orchestrator.d.ts +73 -0
- package/dist/frontier/orchestrator.d.ts.map +1 -0
- package/dist/frontier/orchestrator.js +312 -0
- package/dist/frontier/orchestrator.js.map +1 -0
- package/dist/frontier/providers/stub.d.ts +32 -0
- package/dist/frontier/providers/stub.d.ts.map +1 -0
- package/dist/frontier/providers/stub.js +66 -0
- package/dist/frontier/providers/stub.js.map +1 -0
- package/dist/frontier/types.d.ts +318 -0
- package/dist/frontier/types.d.ts.map +1 -0
- package/dist/frontier/types.js +27 -0
- package/dist/frontier/types.js.map +1 -0
- package/dist/history/index.d.ts +13 -0
- package/dist/history/index.d.ts.map +1 -0
- package/dist/history/index.js +15 -0
- package/dist/history/index.js.map +1 -0
- package/dist/history/store.d.ts +74 -0
- package/dist/history/store.d.ts.map +1 -0
- package/dist/history/store.js +399 -0
- package/dist/history/store.js.map +1 -0
- package/dist/history/types.d.ts +282 -0
- package/dist/history/types.d.ts.map +1 -0
- package/dist/history/types.js +41 -0
- package/dist/history/types.js.map +1 -0
- package/dist/history/verify.d.ts +44 -0
- package/dist/history/verify.d.ts.map +1 -0
- package/dist/history/verify.js +230 -0
- package/dist/history/verify.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +431 -18
- package/dist/index.js.map +1 -1
- package/dist/multimodel/index.d.ts +1 -0
- package/dist/multimodel/index.d.ts.map +1 -1
- package/dist/multimodel/index.js +2 -0
- package/dist/multimodel/index.js.map +1 -1
- package/dist/multimodel/leaderboard.d.ts +116 -0
- package/dist/multimodel/leaderboard.d.ts.map +1 -0
- package/dist/multimodel/leaderboard.js +262 -0
- package/dist/multimodel/leaderboard.js.map +1 -0
- package/dist/observability/otel.d.ts.map +1 -1
- package/dist/observability/otel.js +1 -3
- package/dist/observability/otel.js.map +1 -1
- package/dist/plugins/loader.js +1 -1
- package/dist/plugins/loader.js.map +1 -1
- package/dist/scanners/agent/agent-chain-analysis.d.ts +152 -0
- package/dist/scanners/agent/agent-chain-analysis.d.ts.map +1 -0
- package/dist/scanners/agent/agent-chain-analysis.js +438 -0
- package/dist/scanners/agent/agent-chain-analysis.js.map +1 -0
- package/dist/scanners/agent/payloads/index.d.ts +2 -1
- package/dist/scanners/agent/payloads/index.d.ts.map +1 -1
- package/dist/scanners/agent/payloads/index.js +25 -6
- package/dist/scanners/agent/payloads/index.js.map +1 -1
- package/dist/scanners/agent/prompt-injection-fuzzer.d.ts.map +1 -1
- package/dist/scanners/agent/prompt-injection-fuzzer.js +14 -0
- package/dist/scanners/agent/prompt-injection-fuzzer.js.map +1 -1
- package/dist/scanners/agent/types.d.ts +5 -5
- package/dist/scanners/agent/types.d.ts.map +1 -1
- package/dist/scanners/agent/types.js.map +1 -1
- package/dist/scanners/cache.d.ts +156 -0
- package/dist/scanners/cache.d.ts.map +1 -0
- package/dist/scanners/cache.js +462 -0
- package/dist/scanners/cache.js.map +1 -0
- package/dist/scanners/dependencies.js +4 -4
- package/dist/scanners/dependencies.js.map +1 -1
- package/dist/scanners/gosec.d.ts.map +1 -1
- package/dist/scanners/gosec.js +47 -9
- package/dist/scanners/gosec.js.map +1 -1
- package/dist/scanners/healthcare.d.ts +29 -0
- package/dist/scanners/healthcare.d.ts.map +1 -0
- package/dist/scanners/healthcare.js +526 -0
- package/dist/scanners/healthcare.js.map +1 -0
- package/dist/scanners/index.d.ts +1 -0
- package/dist/scanners/index.d.ts.map +1 -1
- package/dist/scanners/index.js +33 -0
- package/dist/scanners/index.js.map +1 -1
- package/dist/scanners/index.test.js +6 -6
- package/dist/scanners/index.test.js.map +1 -1
- package/dist/scanners/secrets.js +4 -4
- package/dist/scanners/secrets.js.map +1 -1
- package/dist/scanners/semgrep.js +5 -5
- package/dist/scanners/semgrep.js.map +1 -1
- package/dist/scanners/types.d.ts +1 -1
- package/dist/scanners/types.d.ts.map +1 -1
- package/dist/scanners/types.js +1 -0
- package/dist/scanners/types.js.map +1 -1
- package/dist/scanners/typescript.test.js +1 -1
- package/dist/scanners/typescript.test.js.map +1 -1
- package/dist/telemetry/index.d.ts +10 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +10 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/registry.d.ts +178 -0
- package/dist/telemetry/registry.d.ts.map +1 -0
- package/dist/telemetry/registry.js +297 -0
- package/dist/telemetry/registry.js.map +1 -0
- package/dist/telemetry/usage.d.ts +197 -0
- package/dist/telemetry/usage.d.ts.map +1 -0
- package/dist/telemetry/usage.js +244 -0
- package/dist/telemetry/usage.js.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,13 +30,22 @@ import { getAIFrameworkControls, AI_FRAMEWORKS_METADATA, } from "./compliance/fr
|
|
|
30
30
|
// Evaluation harness
|
|
31
31
|
import { runEvaluation, runStabilityTest, calculateMetrics, calculateStabilityMetrics, meetsTargets, generateEvaluationReport, formatReportAsMarkdown, generateCompactSummary, generateReadmeBadges, getFixtureStats, ALL_FIXTURES, TARGET_METRICS, } from "./eval/index.js";
|
|
32
32
|
// Compliance frameworks
|
|
33
|
-
import { generateComplianceReport, generateMultiFrameworkReport, formatComplianceReportAsMarkdown, formatMultiFrameworkReportAsMarkdown, generateCompactComplianceSummary, getControlsForFramework,
|
|
33
|
+
import { generateComplianceReport, generateMultiFrameworkReport, formatComplianceReportAsMarkdown, formatMultiFrameworkReportAsMarkdown, generateCompactComplianceSummary, getControlsForFramework,
|
|
34
|
+
// Healthcare compliance
|
|
35
|
+
runHealthcareComplianceAssessment, generateHealthcareComplianceSummary,
|
|
36
|
+
// Universal audit-defensible compliance
|
|
37
|
+
runSingleFrameworkAssessment, runComplianceAssessment, generateComplianceSummary, } from "./compliance/index.js";
|
|
38
|
+
// Evidence collection and audit trail verification
|
|
39
|
+
import { collectEvidence, storeEvidenceBundle, formatEvidenceBundleAsMarkdown, } from "./evidence/index.js";
|
|
40
|
+
import { verifyHistoryIntegrity, formatVerificationResultAsMarkdown, } from "./history/verify.js";
|
|
34
41
|
// SBOM, Provenance, and Sigstore Signing (uses @sigstore/sign for real signing)
|
|
35
42
|
import { generateSBOM, generateSBOMSummary, generateProvenance, generateProvenanceSummary, verifyProvenance, signContent, isSigningAvailable, generateSigningSummary, detectCIEnvironment, } from "./sbom/index.js";
|
|
36
43
|
// Cost tracking
|
|
37
44
|
import { getTracker, formatCost, formatTokens, estimateCost, getSupportedModels, MODEL_PRICING, } from "./cost/index.js";
|
|
38
45
|
// Multi-model consensus
|
|
39
46
|
import { getRunner, DEFAULT_MODELS, formatProvider, } from "./multimodel/index.js";
|
|
47
|
+
// Path validation utilities
|
|
48
|
+
import { validateProjectPath, PathValidationError } from "./util/paths.js";
|
|
40
49
|
// ---------------------------------------------------------------------------
|
|
41
50
|
// Config
|
|
42
51
|
// ---------------------------------------------------------------------------
|
|
@@ -221,7 +230,17 @@ server.registerTool("hardening_install", {
|
|
|
221
230
|
openWorldHint: false,
|
|
222
231
|
},
|
|
223
232
|
}, async ({ project_path }) => {
|
|
224
|
-
|
|
233
|
+
// Validate path to prevent traversal attacks
|
|
234
|
+
let validatedPath;
|
|
235
|
+
try {
|
|
236
|
+
validatedPath = await validateProjectPath(project_path);
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
if (error instanceof PathValidationError) {
|
|
240
|
+
return {
|
|
241
|
+
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
225
244
|
return {
|
|
226
245
|
content: [
|
|
227
246
|
{
|
|
@@ -232,7 +251,7 @@ server.registerTool("hardening_install", {
|
|
|
232
251
|
};
|
|
233
252
|
}
|
|
234
253
|
try {
|
|
235
|
-
const commandsDir = join(
|
|
254
|
+
const commandsDir = join(validatedPath, ".claude", "commands");
|
|
236
255
|
await mkdir(commandsDir, { recursive: true });
|
|
237
256
|
const installed = [];
|
|
238
257
|
const errors = [];
|
|
@@ -248,7 +267,7 @@ server.registerTool("hardening_install", {
|
|
|
248
267
|
}
|
|
249
268
|
}
|
|
250
269
|
const output = {
|
|
251
|
-
project:
|
|
270
|
+
project: validatedPath,
|
|
252
271
|
commands_dir: commandsDir,
|
|
253
272
|
installed_commands: installed,
|
|
254
273
|
errors: errors.length > 0 ? errors : undefined,
|
|
@@ -295,7 +314,17 @@ server.registerTool("hardening_install_all", {
|
|
|
295
314
|
},
|
|
296
315
|
}, async ({ base_dir, dry_run = true }) => {
|
|
297
316
|
const dir = base_dir || DEFAULT_PROJECTS_DIR;
|
|
298
|
-
|
|
317
|
+
// Validate path to prevent traversal attacks
|
|
318
|
+
let validatedDir;
|
|
319
|
+
try {
|
|
320
|
+
validatedDir = await validateProjectPath(dir);
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
if (error instanceof PathValidationError) {
|
|
324
|
+
return {
|
|
325
|
+
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
326
|
+
};
|
|
327
|
+
}
|
|
299
328
|
return {
|
|
300
329
|
content: [
|
|
301
330
|
{
|
|
@@ -306,7 +335,7 @@ server.registerTool("hardening_install_all", {
|
|
|
306
335
|
};
|
|
307
336
|
}
|
|
308
337
|
try {
|
|
309
|
-
const projects = await discoverProjects(
|
|
338
|
+
const projects = await discoverProjects(validatedDir);
|
|
310
339
|
const commandCount = Object.keys(COMMANDS).length;
|
|
311
340
|
const results = [];
|
|
312
341
|
for (const projectPath of projects) {
|
|
@@ -347,7 +376,7 @@ server.registerTool("hardening_install_all", {
|
|
|
347
376
|
}
|
|
348
377
|
const output = {
|
|
349
378
|
mode: dry_run ? "dry-run" : "applied",
|
|
350
|
-
base_dir:
|
|
379
|
+
base_dir: validatedDir,
|
|
351
380
|
projects_scanned: projects.length,
|
|
352
381
|
commands_per_project: commandCount,
|
|
353
382
|
projects_updated: dry_run ? 0 : results.filter((r) => !r.error && r.commands_installed).length,
|
|
@@ -1247,6 +1276,87 @@ server.registerTool("agent_complete", {
|
|
|
1247
1276
|
};
|
|
1248
1277
|
});
|
|
1249
1278
|
// ---------------------------------------------------------------------------
|
|
1279
|
+
// Tool: Batch Submit Findings (for subagent JSON output)
|
|
1280
|
+
// ---------------------------------------------------------------------------
|
|
1281
|
+
server.registerTool("agent_batch_submit", {
|
|
1282
|
+
title: "Batch Submit Agent Findings",
|
|
1283
|
+
description: `Submit multiple findings from a subagent's JSON output. Use this when certification agents run as subagents (via Task tool) and output JSON instead of calling agent_submit_finding directly. Parses the agent's JSON output and submits all findings at once.`,
|
|
1284
|
+
inputSchema: {
|
|
1285
|
+
project_path: z.string().describe("Absolute path to the project root"),
|
|
1286
|
+
certification_id: z.string().describe("Certification ID"),
|
|
1287
|
+
agent: z.enum(["security", "reliability", "typesafety", "performance", "quality", "redteam"]),
|
|
1288
|
+
findings: z.array(z.object({
|
|
1289
|
+
id: z.string().describe("Finding ID (e.g., sec-001)"),
|
|
1290
|
+
severity: z.enum(["critical", "high", "medium", "low", "info"]),
|
|
1291
|
+
category: z.string().describe("Category of the finding"),
|
|
1292
|
+
file: z.string().optional().describe("File path where issue found"),
|
|
1293
|
+
line: z.number().optional().describe("Line number"),
|
|
1294
|
+
description: z.string().describe("Description of the issue"),
|
|
1295
|
+
evidence: z.string().describe("Evidence supporting the finding"),
|
|
1296
|
+
confidence: z.number().min(0).max(100).describe("Confidence score 0-100"),
|
|
1297
|
+
})).describe("Array of findings from subagent JSON output"),
|
|
1298
|
+
summary: z.object({
|
|
1299
|
+
total_findings: z.number(),
|
|
1300
|
+
by_severity: z.object({
|
|
1301
|
+
critical: z.number(),
|
|
1302
|
+
high: z.number(),
|
|
1303
|
+
medium: z.number(),
|
|
1304
|
+
low: z.number(),
|
|
1305
|
+
info: z.number(),
|
|
1306
|
+
}),
|
|
1307
|
+
confidence_score: z.number().min(0).max(100),
|
|
1308
|
+
coverage_areas: z.array(z.string()),
|
|
1309
|
+
notes: z.string().optional(),
|
|
1310
|
+
}).optional().describe("Optional summary to complete the agent run"),
|
|
1311
|
+
},
|
|
1312
|
+
annotations: {
|
|
1313
|
+
readOnlyHint: false,
|
|
1314
|
+
destructiveHint: false,
|
|
1315
|
+
idempotentHint: false,
|
|
1316
|
+
openWorldHint: false,
|
|
1317
|
+
},
|
|
1318
|
+
}, async ({ project_path, certification_id, agent, findings, summary }) => {
|
|
1319
|
+
const certLogger = createChildLogger({ certId: certification_id, agent });
|
|
1320
|
+
// Ensure agent is started
|
|
1321
|
+
let agentFindings = await getAgentFindings(project_path, certification_id, agent);
|
|
1322
|
+
if (!agentFindings) {
|
|
1323
|
+
certLogger.info("agent.started");
|
|
1324
|
+
agentFindings = await startAgent(project_path, certification_id, agent);
|
|
1325
|
+
}
|
|
1326
|
+
// Submit all findings
|
|
1327
|
+
const submitted = [];
|
|
1328
|
+
for (const finding of findings) {
|
|
1329
|
+
await submitFinding(project_path, certification_id, agent, finding);
|
|
1330
|
+
submitted.push({ id: finding.id, severity: finding.severity });
|
|
1331
|
+
certLogger.info("finding.submitted", {
|
|
1332
|
+
findingId: finding.id,
|
|
1333
|
+
severity: finding.severity,
|
|
1334
|
+
confidence: finding.confidence,
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
// Complete agent if summary provided
|
|
1338
|
+
let completionResult = null;
|
|
1339
|
+
if (summary) {
|
|
1340
|
+
completionResult = await completeAgent(project_path, certification_id, agent, summary);
|
|
1341
|
+
certLogger.info("agent.completed", {
|
|
1342
|
+
totalFindings: summary.total_findings,
|
|
1343
|
+
confidenceScore: summary.confidence_score,
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
return {
|
|
1347
|
+
content: [{
|
|
1348
|
+
type: "text",
|
|
1349
|
+
text: JSON.stringify({
|
|
1350
|
+
agent,
|
|
1351
|
+
findingsSubmitted: submitted.length,
|
|
1352
|
+
findings: submitted,
|
|
1353
|
+
completed: !!summary,
|
|
1354
|
+
summary: completionResult?.summary,
|
|
1355
|
+
}, null, 2),
|
|
1356
|
+
}],
|
|
1357
|
+
};
|
|
1358
|
+
});
|
|
1359
|
+
// ---------------------------------------------------------------------------
|
|
1250
1360
|
// Tool: Cross-Verify Finding
|
|
1251
1361
|
// ---------------------------------------------------------------------------
|
|
1252
1362
|
server.registerTool("agent_cross_verify", {
|
|
@@ -2142,13 +2252,17 @@ server.registerTool("certification_eval_fixtures", {
|
|
|
2142
2252
|
// ---------------------------------------------------------------------------
|
|
2143
2253
|
server.registerTool("compliance_report", {
|
|
2144
2254
|
title: "Generate Compliance Report",
|
|
2145
|
-
description: `Generate a compliance report mapping certification findings to framework controls (SOC 2, ISO 27001
|
|
2255
|
+
description: `Generate a compliance report mapping certification findings to framework controls. Supports all major frameworks (SOC 2, ISO 27001, PCI-DSS, HIPAA, 42 CFR Part 2, GDPR, NIST 800-53, CIS). Enable audit-defensibility options for evidence collection and audit trail verification.`,
|
|
2146
2256
|
inputSchema: {
|
|
2147
2257
|
project_path: z.string().describe("Absolute path to the project root"),
|
|
2148
2258
|
certification_id: z.string().describe("Certification ID to assess"),
|
|
2149
2259
|
framework: z
|
|
2150
|
-
.enum(["SOC2", "ISO27001"])
|
|
2260
|
+
.enum(["SOC2", "ISO27001", "PCI-DSS", "HIPAA", "42-CFR-PART-2", "GDPR", "NIST-800-53", "CIS"])
|
|
2151
2261
|
.describe("Compliance framework to assess"),
|
|
2262
|
+
collect_evidence: z.boolean().optional().describe("Collect evidence bundle for audit defensibility. Default: false"),
|
|
2263
|
+
verify_audit_trail: z.boolean().optional().describe("Verify audit trail integrity. Default: false"),
|
|
2264
|
+
store_evidence: z.boolean().optional().describe("Store evidence bundle to disk. Default: true if collecting"),
|
|
2265
|
+
include_attestation: z.boolean().optional().describe("Include attestation section with methodology and scope. Default: true when audit features enabled"),
|
|
2152
2266
|
output_format: z
|
|
2153
2267
|
.enum(["markdown", "json", "summary"])
|
|
2154
2268
|
.optional()
|
|
@@ -2160,7 +2274,7 @@ server.registerTool("compliance_report", {
|
|
|
2160
2274
|
idempotentHint: true,
|
|
2161
2275
|
openWorldHint: false,
|
|
2162
2276
|
},
|
|
2163
|
-
}, async ({ project_path, certification_id, framework, output_format }) => {
|
|
2277
|
+
}, async ({ project_path, certification_id, framework, collect_evidence, verify_audit_trail, store_evidence, include_attestation, output_format }) => {
|
|
2164
2278
|
const certification = await getCertification(project_path, certification_id);
|
|
2165
2279
|
if (!certification) {
|
|
2166
2280
|
return errorResponse(`Certification ${certification_id} not found`);
|
|
@@ -2172,6 +2286,46 @@ server.registerTool("compliance_report", {
|
|
|
2172
2286
|
if (allFindings.length === 0) {
|
|
2173
2287
|
return errorResponse("No findings to assess. Run certification agents first.");
|
|
2174
2288
|
}
|
|
2289
|
+
// Check if audit-defensibility features are requested
|
|
2290
|
+
const useAuditFeatures = collect_evidence || verify_audit_trail;
|
|
2291
|
+
if (useAuditFeatures) {
|
|
2292
|
+
// Use the full compliance bundle for audit-defensible reports
|
|
2293
|
+
const result = await runSingleFrameworkAssessment({
|
|
2294
|
+
projectPath: project_path,
|
|
2295
|
+
findings: allFindings,
|
|
2296
|
+
framework: framework,
|
|
2297
|
+
certificationId: certification_id,
|
|
2298
|
+
collectEvidence: collect_evidence ?? false,
|
|
2299
|
+
verifyAuditTrail: verify_audit_trail ?? false,
|
|
2300
|
+
storeEvidence: store_evidence !== false,
|
|
2301
|
+
includeAttestation: include_attestation !== false,
|
|
2302
|
+
});
|
|
2303
|
+
if (output_format === "json") {
|
|
2304
|
+
return jsonResponse({
|
|
2305
|
+
status: result.status,
|
|
2306
|
+
complianceScore: result.report.status.complianceScore,
|
|
2307
|
+
riskScore: result.report.status.riskScore,
|
|
2308
|
+
auditVerification: result.auditVerification ? {
|
|
2309
|
+
verified: result.auditVerification.verified,
|
|
2310
|
+
chainIntegrity: result.auditVerification.chainIntegrity,
|
|
2311
|
+
} : undefined,
|
|
2312
|
+
evidenceBundle: result.evidenceBundle ? {
|
|
2313
|
+
id: result.evidenceBundle.id,
|
|
2314
|
+
bundleDigest: result.evidenceBundle.bundleDigest,
|
|
2315
|
+
signed: !!result.evidenceBundle.signature,
|
|
2316
|
+
} : undefined,
|
|
2317
|
+
evidencePath: result.evidencePath,
|
|
2318
|
+
report: result.report,
|
|
2319
|
+
});
|
|
2320
|
+
}
|
|
2321
|
+
else if (output_format === "summary") {
|
|
2322
|
+
return textResponse(generateCompactComplianceSummary(result.report));
|
|
2323
|
+
}
|
|
2324
|
+
else {
|
|
2325
|
+
return textResponse(result.markdownReport);
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
// Standard report without audit features
|
|
2175
2329
|
const report = generateComplianceReport(allFindings, framework, project_path, certification_id);
|
|
2176
2330
|
if (output_format === "json") {
|
|
2177
2331
|
return jsonResponse(report);
|
|
@@ -2188,16 +2342,20 @@ server.registerTool("compliance_report", {
|
|
|
2188
2342
|
// ---------------------------------------------------------------------------
|
|
2189
2343
|
server.registerTool("compliance_multi_report", {
|
|
2190
2344
|
title: "Multi-Framework Compliance Report",
|
|
2191
|
-
description: `Generate a compliance report across multiple frameworks (SOC 2
|
|
2345
|
+
description: `Generate a compliance report across multiple frameworks. Supports all major frameworks (SOC 2, ISO 27001, PCI-DSS, HIPAA, 42 CFR Part 2, GDPR, NIST 800-53, CIS). Shows comparative status and prioritized recommendations. Enable audit-defensibility options for evidence collection and audit trail verification.`,
|
|
2192
2346
|
inputSchema: {
|
|
2193
2347
|
project_path: z.string().describe("Absolute path to the project root"),
|
|
2194
2348
|
certification_id: z.string().describe("Certification ID to assess"),
|
|
2195
2349
|
frameworks: z
|
|
2196
|
-
.array(z.enum(["SOC2", "ISO27001"]))
|
|
2350
|
+
.array(z.enum(["SOC2", "ISO27001", "PCI-DSS", "HIPAA", "42-CFR-PART-2", "GDPR", "NIST-800-53", "CIS"]))
|
|
2197
2351
|
.optional()
|
|
2198
|
-
.describe("Frameworks to assess. Default:
|
|
2352
|
+
.describe("Frameworks to assess. Default: SOC2, ISO27001"),
|
|
2353
|
+
collect_evidence: z.boolean().optional().describe("Collect evidence bundle for audit defensibility. Default: false"),
|
|
2354
|
+
verify_audit_trail: z.boolean().optional().describe("Verify audit trail integrity. Default: false"),
|
|
2355
|
+
store_evidence: z.boolean().optional().describe("Store evidence bundle to disk. Default: true if collecting"),
|
|
2356
|
+
include_attestation: z.boolean().optional().describe("Include attestation section with methodology and scope. Default: true when audit features enabled"),
|
|
2199
2357
|
output_format: z
|
|
2200
|
-
.enum(["markdown", "json"])
|
|
2358
|
+
.enum(["markdown", "json", "summary"])
|
|
2201
2359
|
.optional()
|
|
2202
2360
|
.describe("Output format. Default: markdown"),
|
|
2203
2361
|
},
|
|
@@ -2207,7 +2365,7 @@ server.registerTool("compliance_multi_report", {
|
|
|
2207
2365
|
idempotentHint: true,
|
|
2208
2366
|
openWorldHint: false,
|
|
2209
2367
|
},
|
|
2210
|
-
}, async ({ project_path, certification_id, frameworks, output_format }) => {
|
|
2368
|
+
}, async ({ project_path, certification_id, frameworks, collect_evidence, verify_audit_trail, store_evidence, include_attestation, output_format }) => {
|
|
2211
2369
|
const certification = await getCertification(project_path, certification_id);
|
|
2212
2370
|
if (!certification) {
|
|
2213
2371
|
return errorResponse(`Certification ${certification_id} not found`);
|
|
@@ -2219,6 +2377,53 @@ server.registerTool("compliance_multi_report", {
|
|
|
2219
2377
|
return errorResponse("No findings to assess. Run certification agents first.");
|
|
2220
2378
|
}
|
|
2221
2379
|
const selectedFrameworks = (frameworks || ["SOC2", "ISO27001"]);
|
|
2380
|
+
// Check if audit-defensibility features are requested
|
|
2381
|
+
const useAuditFeatures = collect_evidence || verify_audit_trail;
|
|
2382
|
+
if (useAuditFeatures) {
|
|
2383
|
+
// Use the full compliance bundle for audit-defensible reports
|
|
2384
|
+
const result = await runComplianceAssessment({
|
|
2385
|
+
projectPath: project_path,
|
|
2386
|
+
findings: allFindings,
|
|
2387
|
+
frameworks: selectedFrameworks,
|
|
2388
|
+
certificationId: certification_id,
|
|
2389
|
+
collectEvidence: collect_evidence ?? false,
|
|
2390
|
+
verifyAuditTrail: verify_audit_trail ?? false,
|
|
2391
|
+
storeEvidence: store_evidence !== false,
|
|
2392
|
+
includeAttestation: include_attestation !== false,
|
|
2393
|
+
});
|
|
2394
|
+
if (output_format === "json") {
|
|
2395
|
+
return jsonResponse({
|
|
2396
|
+
status: result.status,
|
|
2397
|
+
combinedScore: result.combinedScore,
|
|
2398
|
+
frameworks: Object.fromEntries(Object.entries(result.reports).map(([fw, report]) => [
|
|
2399
|
+
fw,
|
|
2400
|
+
report ? {
|
|
2401
|
+
complianceScore: report.status.complianceScore,
|
|
2402
|
+
riskScore: report.status.riskScore,
|
|
2403
|
+
controlsNonCompliant: report.status.controlsNonCompliant,
|
|
2404
|
+
} : null,
|
|
2405
|
+
])),
|
|
2406
|
+
auditVerification: result.auditVerification ? {
|
|
2407
|
+
verified: result.auditVerification.verified,
|
|
2408
|
+
chainIntegrity: result.auditVerification.chainIntegrity,
|
|
2409
|
+
} : undefined,
|
|
2410
|
+
evidenceBundle: result.evidenceBundle ? {
|
|
2411
|
+
id: result.evidenceBundle.id,
|
|
2412
|
+
bundleDigest: result.evidenceBundle.bundleDigest,
|
|
2413
|
+
signed: !!result.evidenceBundle.signature,
|
|
2414
|
+
} : undefined,
|
|
2415
|
+
evidencePath: result.evidencePath,
|
|
2416
|
+
multiFrameworkReport: result.multiFrameworkReport,
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2419
|
+
else if (output_format === "summary") {
|
|
2420
|
+
return textResponse(generateComplianceSummary(result));
|
|
2421
|
+
}
|
|
2422
|
+
else {
|
|
2423
|
+
return textResponse(result.markdownReport);
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
// Standard report without audit features
|
|
2222
2427
|
const report = generateMultiFrameworkReport(allFindings, selectedFrameworks, project_path, certification_id);
|
|
2223
2428
|
if (output_format === "json") {
|
|
2224
2429
|
return jsonResponse(report);
|
|
@@ -2232,10 +2437,10 @@ server.registerTool("compliance_multi_report", {
|
|
|
2232
2437
|
// ---------------------------------------------------------------------------
|
|
2233
2438
|
server.registerTool("compliance_controls", {
|
|
2234
2439
|
title: "List Compliance Controls",
|
|
2235
|
-
description: `List available compliance controls for a framework. Use to understand what controls are assessed and their mapping to finding categories.`,
|
|
2440
|
+
description: `List available compliance controls for a framework. Use to understand what controls are assessed and their mapping to finding categories. Supports all major frameworks.`,
|
|
2236
2441
|
inputSchema: {
|
|
2237
2442
|
framework: z
|
|
2238
|
-
.enum(["SOC2", "ISO27001"])
|
|
2443
|
+
.enum(["SOC2", "ISO27001", "PCI-DSS", "HIPAA", "42-CFR-PART-2", "GDPR", "NIST-800-53", "CIS"])
|
|
2239
2444
|
.describe("Compliance framework"),
|
|
2240
2445
|
category: z
|
|
2241
2446
|
.string()
|
|
@@ -2253,7 +2458,8 @@ server.registerTool("compliance_controls", {
|
|
|
2253
2458
|
if (category) {
|
|
2254
2459
|
controls = controls.filter((c) => c.category === category);
|
|
2255
2460
|
}
|
|
2256
|
-
|
|
2461
|
+
// Get unique categories from controls
|
|
2462
|
+
const categories = [...new Set(controls.map((c) => c.category))].sort();
|
|
2257
2463
|
return jsonResponse({
|
|
2258
2464
|
framework,
|
|
2259
2465
|
totalControls: controls.length,
|
|
@@ -2269,6 +2475,213 @@ server.registerTool("compliance_controls", {
|
|
|
2269
2475
|
});
|
|
2270
2476
|
});
|
|
2271
2477
|
// ---------------------------------------------------------------------------
|
|
2478
|
+
// Tool: Healthcare Compliance Scan (HIPAA + 42 CFR Part 2)
|
|
2479
|
+
// ---------------------------------------------------------------------------
|
|
2480
|
+
server.registerTool("healthcare_compliance_scan", {
|
|
2481
|
+
title: "Healthcare Compliance Assessment",
|
|
2482
|
+
description: `Run a combined HIPAA and 42 CFR Part 2 compliance assessment. Generates audit-defensible reports with evidence collection and audit trail verification. Designed for SUD (Substance Use Disorder) and healthcare applications.`,
|
|
2483
|
+
inputSchema: {
|
|
2484
|
+
project_path: z.string().describe("Absolute path to the project root"),
|
|
2485
|
+
certification_id: z.string().optional().describe("Certification ID to use findings from"),
|
|
2486
|
+
collect_evidence: z.boolean().optional().describe("Collect evidence bundle. Default: true"),
|
|
2487
|
+
verify_audit_trail: z.boolean().optional().describe("Verify audit trail integrity. Default: true"),
|
|
2488
|
+
store_evidence: z.boolean().optional().describe("Store evidence bundle to disk. Default: true"),
|
|
2489
|
+
output_format: z.enum(["markdown", "json", "summary"]).optional().describe("Output format. Default: markdown"),
|
|
2490
|
+
},
|
|
2491
|
+
annotations: {
|
|
2492
|
+
readOnlyHint: true,
|
|
2493
|
+
destructiveHint: false,
|
|
2494
|
+
idempotentHint: true,
|
|
2495
|
+
openWorldHint: false,
|
|
2496
|
+
},
|
|
2497
|
+
}, async ({ project_path, certification_id, collect_evidence, verify_audit_trail, store_evidence, output_format }) => {
|
|
2498
|
+
try {
|
|
2499
|
+
const validatedPath = await validateProjectPath(project_path);
|
|
2500
|
+
const allFindings = [];
|
|
2501
|
+
const certId = certification_id || undefined;
|
|
2502
|
+
let certificationToUse;
|
|
2503
|
+
if (certId) {
|
|
2504
|
+
certificationToUse = await getCertification(validatedPath, certId);
|
|
2505
|
+
}
|
|
2506
|
+
else {
|
|
2507
|
+
certificationToUse = await getLatestCertification(validatedPath);
|
|
2508
|
+
}
|
|
2509
|
+
if (certificationToUse) {
|
|
2510
|
+
const agents = Object.keys(certificationToUse.agents);
|
|
2511
|
+
for (const agent of agents) {
|
|
2512
|
+
const agentData = certificationToUse.agents[agent];
|
|
2513
|
+
if (agentData?.findings) {
|
|
2514
|
+
// Cast to any to avoid type conflicts between local and imported types
|
|
2515
|
+
allFindings.push(...agentData.findings);
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
// Run healthcare compliance assessment
|
|
2520
|
+
const result = await runHealthcareComplianceAssessment({
|
|
2521
|
+
projectPath: validatedPath,
|
|
2522
|
+
// Healthcare bundle expects Finding[] from certification/types
|
|
2523
|
+
findings: allFindings,
|
|
2524
|
+
certificationId: certificationToUse?.metadata.id,
|
|
2525
|
+
collectEvidence: collect_evidence !== false,
|
|
2526
|
+
verifyAuditTrail: verify_audit_trail !== false,
|
|
2527
|
+
storeEvidence: store_evidence !== false,
|
|
2528
|
+
});
|
|
2529
|
+
if (output_format === "json") {
|
|
2530
|
+
return jsonResponse({
|
|
2531
|
+
status: result.status,
|
|
2532
|
+
combinedScore: result.combinedScore,
|
|
2533
|
+
hipaaScore: result.hipaaReport.status.complianceScore,
|
|
2534
|
+
cfr42Score: result.cfr42Report.status.complianceScore,
|
|
2535
|
+
hipaaControls: {
|
|
2536
|
+
total: result.hipaaReport.status.totalControls,
|
|
2537
|
+
compliant: result.hipaaReport.status.controlsCovered,
|
|
2538
|
+
atRisk: result.hipaaReport.status.controlsAtRisk,
|
|
2539
|
+
nonCompliant: result.hipaaReport.status.controlsNonCompliant,
|
|
2540
|
+
},
|
|
2541
|
+
cfr42Controls: {
|
|
2542
|
+
total: result.cfr42Report.status.totalControls,
|
|
2543
|
+
compliant: result.cfr42Report.status.controlsCovered,
|
|
2544
|
+
atRisk: result.cfr42Report.status.controlsAtRisk,
|
|
2545
|
+
nonCompliant: result.cfr42Report.status.controlsNonCompliant,
|
|
2546
|
+
},
|
|
2547
|
+
auditTrailVerified: result.auditVerification?.verified,
|
|
2548
|
+
evidenceBundleId: result.evidenceBundle?.id,
|
|
2549
|
+
evidencePath: result.evidencePath,
|
|
2550
|
+
});
|
|
2551
|
+
}
|
|
2552
|
+
else if (output_format === "summary") {
|
|
2553
|
+
return textResponse(generateHealthcareComplianceSummary(result));
|
|
2554
|
+
}
|
|
2555
|
+
return textResponse(result.markdownReport);
|
|
2556
|
+
}
|
|
2557
|
+
catch (error) {
|
|
2558
|
+
if (error instanceof PathValidationError) {
|
|
2559
|
+
return errorResponse(error.message);
|
|
2560
|
+
}
|
|
2561
|
+
return errorResponse(`Healthcare compliance scan failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2562
|
+
}
|
|
2563
|
+
});
|
|
2564
|
+
// ---------------------------------------------------------------------------
|
|
2565
|
+
// Tool: Verify Audit Trail
|
|
2566
|
+
// ---------------------------------------------------------------------------
|
|
2567
|
+
server.registerTool("verify_audit_trail", {
|
|
2568
|
+
title: "Verify Audit Trail Integrity",
|
|
2569
|
+
description: `Verify the tamper-evident audit trail by checking hash chains. Detects if any historical entries have been modified. Critical for healthcare compliance (HIPAA, 42 CFR Part 2) audit defensibility.`,
|
|
2570
|
+
inputSchema: {
|
|
2571
|
+
project_path: z.string().describe("Absolute path to the project root"),
|
|
2572
|
+
output_format: z.enum(["markdown", "json"]).optional().describe("Output format. Default: markdown"),
|
|
2573
|
+
},
|
|
2574
|
+
annotations: {
|
|
2575
|
+
readOnlyHint: true,
|
|
2576
|
+
destructiveHint: false,
|
|
2577
|
+
idempotentHint: true,
|
|
2578
|
+
openWorldHint: false,
|
|
2579
|
+
},
|
|
2580
|
+
}, async ({ project_path, output_format }) => {
|
|
2581
|
+
try {
|
|
2582
|
+
const validatedPath = await validateProjectPath(project_path);
|
|
2583
|
+
const result = await verifyHistoryIntegrity(validatedPath);
|
|
2584
|
+
if (output_format === "json") {
|
|
2585
|
+
return jsonResponse({
|
|
2586
|
+
verified: result.verified,
|
|
2587
|
+
projectPath: result.projectPath,
|
|
2588
|
+
verifiedAt: result.verifiedAt,
|
|
2589
|
+
totalEntries: result.totalEntries,
|
|
2590
|
+
entriesVerified: result.entriesVerified,
|
|
2591
|
+
entriesPassed: result.entriesPassed,
|
|
2592
|
+
entriesFailed: result.entriesFailed,
|
|
2593
|
+
chainIntegrity: result.chainIntegrity,
|
|
2594
|
+
genesisHash: result.genesisHash,
|
|
2595
|
+
headHash: result.headHash,
|
|
2596
|
+
failures: result.failures,
|
|
2597
|
+
});
|
|
2598
|
+
}
|
|
2599
|
+
return textResponse(formatVerificationResultAsMarkdown(result));
|
|
2600
|
+
}
|
|
2601
|
+
catch (error) {
|
|
2602
|
+
if (error instanceof PathValidationError) {
|
|
2603
|
+
return errorResponse(error.message);
|
|
2604
|
+
}
|
|
2605
|
+
return errorResponse(`Audit trail verification failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2606
|
+
}
|
|
2607
|
+
});
|
|
2608
|
+
// ---------------------------------------------------------------------------
|
|
2609
|
+
// Tool: Collect Evidence Bundle
|
|
2610
|
+
// ---------------------------------------------------------------------------
|
|
2611
|
+
server.registerTool("collect_evidence_bundle", {
|
|
2612
|
+
title: "Collect Evidence Bundle",
|
|
2613
|
+
description: `Collect and package audit evidence for compliance. Creates a cryptographically attested bundle of scan results, compliance reports, SBOM, and history snapshots. Essential for audit defensibility.`,
|
|
2614
|
+
inputSchema: {
|
|
2615
|
+
project_path: z.string().describe("Absolute path to the project root"),
|
|
2616
|
+
certification_id: z.string().optional().describe("Certification ID to associate with"),
|
|
2617
|
+
frameworks: z
|
|
2618
|
+
.array(z.enum(["HIPAA", "42-CFR-PART-2", "SOC2", "ISO27001", "PCI-DSS", "GDPR", "NIST-800-53", "CIS"]))
|
|
2619
|
+
.optional()
|
|
2620
|
+
.describe("Compliance frameworks to include reports for"),
|
|
2621
|
+
include_sbom: z.boolean().optional().describe("Include SBOM. Default: true"),
|
|
2622
|
+
include_history: z.boolean().optional().describe("Include history snapshot. Default: true"),
|
|
2623
|
+
include_scans: z.boolean().optional().describe("Include scan results. Default: true"),
|
|
2624
|
+
store: z.boolean().optional().describe("Store bundle to disk. Default: true"),
|
|
2625
|
+
output_format: z.enum(["markdown", "json"]).optional().describe("Output format. Default: markdown"),
|
|
2626
|
+
},
|
|
2627
|
+
annotations: {
|
|
2628
|
+
readOnlyHint: true,
|
|
2629
|
+
destructiveHint: false,
|
|
2630
|
+
idempotentHint: true,
|
|
2631
|
+
openWorldHint: false,
|
|
2632
|
+
},
|
|
2633
|
+
}, async ({ project_path, certification_id, frameworks, include_sbom, include_history, include_scans, store, output_format }) => {
|
|
2634
|
+
try {
|
|
2635
|
+
const validatedPath = await validateProjectPath(project_path);
|
|
2636
|
+
const result = await collectEvidence({
|
|
2637
|
+
projectPath: validatedPath,
|
|
2638
|
+
certificationId: certification_id,
|
|
2639
|
+
frameworks: frameworks,
|
|
2640
|
+
includeSbom: include_sbom !== false,
|
|
2641
|
+
includeHistory: include_history !== false,
|
|
2642
|
+
includeScanResults: include_scans !== false,
|
|
2643
|
+
});
|
|
2644
|
+
if (!result.success || !result.bundle) {
|
|
2645
|
+
return errorResponse(result.error || "Evidence collection failed");
|
|
2646
|
+
}
|
|
2647
|
+
let storedPath;
|
|
2648
|
+
if (store !== false) {
|
|
2649
|
+
storedPath = await storeEvidenceBundle(validatedPath, result.bundle);
|
|
2650
|
+
}
|
|
2651
|
+
if (output_format === "json") {
|
|
2652
|
+
return jsonResponse({
|
|
2653
|
+
success: true,
|
|
2654
|
+
bundleId: result.bundle.id,
|
|
2655
|
+
createdAt: result.bundle.createdAt,
|
|
2656
|
+
artifactCount: result.bundle.artifacts.length,
|
|
2657
|
+
bundleDigest: result.bundle.bundleDigest,
|
|
2658
|
+
storedPath,
|
|
2659
|
+
warnings: result.warnings,
|
|
2660
|
+
artifacts: result.bundle.artifacts.map((a) => ({
|
|
2661
|
+
type: a.type,
|
|
2662
|
+
name: a.name,
|
|
2663
|
+
sizeBytes: a.sizeBytes,
|
|
2664
|
+
digest: a.contentDigest,
|
|
2665
|
+
})),
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
let output = formatEvidenceBundleAsMarkdown(result.bundle);
|
|
2669
|
+
if (storedPath) {
|
|
2670
|
+
output += `\n\n**Stored at:** \`${storedPath}\``;
|
|
2671
|
+
}
|
|
2672
|
+
if (result.warnings.length > 0) {
|
|
2673
|
+
output += `\n\n**Warnings:**\n${result.warnings.map((w) => `- ${w}`).join("\n")}`;
|
|
2674
|
+
}
|
|
2675
|
+
return textResponse(output);
|
|
2676
|
+
}
|
|
2677
|
+
catch (error) {
|
|
2678
|
+
if (error instanceof PathValidationError) {
|
|
2679
|
+
return errorResponse(error.message);
|
|
2680
|
+
}
|
|
2681
|
+
return errorResponse(`Evidence collection failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2682
|
+
}
|
|
2683
|
+
});
|
|
2684
|
+
// ---------------------------------------------------------------------------
|
|
2272
2685
|
// Tool: Generate SBOM
|
|
2273
2686
|
// ---------------------------------------------------------------------------
|
|
2274
2687
|
server.registerTool("sbom_generate", {
|