sentinelayer-cli 0.6.2 → 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.
- package/README.md +1009 -996
- package/bin/create-sentinelayer.js +5 -5
- package/bin/sentinelayer-cli.js +4 -4
- package/bin/sl.js +5 -5
- package/package.json +64 -63
- package/src/agents/ai-governance/index.js +12 -0
- package/src/agents/ai-governance/tools/base.js +171 -0
- package/src/agents/ai-governance/tools/eval-regression.js +47 -0
- package/src/agents/ai-governance/tools/hitl-audit.js +81 -0
- package/src/agents/ai-governance/tools/index.js +52 -0
- package/src/agents/ai-governance/tools/prompt-drift.js +42 -0
- package/src/agents/ai-governance/tools/provenance-check.js +69 -0
- package/src/agents/backend/index.js +12 -0
- package/src/agents/backend/tools/base.js +189 -0
- package/src/agents/backend/tools/circuit-breaker-check.js +123 -0
- package/src/agents/backend/tools/idempotency-audit.js +105 -0
- package/src/agents/backend/tools/index.js +87 -0
- package/src/agents/backend/tools/retry-audit.js +132 -0
- package/src/agents/backend/tools/timeout-audit.js +144 -0
- package/src/agents/code-quality/index.js +12 -0
- package/src/agents/code-quality/tools/base.js +159 -0
- package/src/agents/code-quality/tools/complexity-measure.js +197 -0
- package/src/agents/code-quality/tools/coupling-analysis.js +81 -0
- package/src/agents/code-quality/tools/cycle-detect.js +49 -0
- package/src/agents/code-quality/tools/dep-graph.js +196 -0
- package/src/agents/code-quality/tools/index.js +89 -0
- package/src/agents/data-layer/index.js +12 -0
- package/src/agents/data-layer/tools/base.js +181 -0
- package/src/agents/data-layer/tools/index-audit.js +165 -0
- package/src/agents/data-layer/tools/index.js +83 -0
- package/src/agents/data-layer/tools/migration-scan.js +135 -0
- package/src/agents/data-layer/tools/query-explain.js +120 -0
- package/src/agents/data-layer/tools/tenancy-scan.js +166 -0
- package/src/agents/documentation/index.js +12 -0
- package/src/agents/documentation/tools/api-diff.js +91 -0
- package/src/agents/documentation/tools/base.js +151 -0
- package/src/agents/documentation/tools/dead-link-check.js +58 -0
- package/src/agents/documentation/tools/docstring-coverage.js +78 -0
- package/src/agents/documentation/tools/index.js +52 -0
- package/src/agents/documentation/tools/readme-freshness.js +61 -0
- package/src/agents/envelope/fix-cycle.js +45 -0
- package/src/agents/envelope/index.js +31 -0
- package/src/agents/envelope/loop.js +150 -0
- package/src/agents/envelope/pulse.js +18 -0
- package/src/agents/envelope/stream.js +40 -0
- package/src/agents/infrastructure/index.js +12 -0
- package/src/agents/infrastructure/tools/base.js +171 -0
- package/src/agents/infrastructure/tools/checkov-run.js +32 -0
- package/src/agents/infrastructure/tools/drift-detect.js +59 -0
- package/src/agents/infrastructure/tools/iam-least-priv-check.js +78 -0
- package/src/agents/infrastructure/tools/index.js +52 -0
- package/src/agents/infrastructure/tools/tflint-run.js +31 -0
- package/src/agents/jules/config/definition.js +160 -160
- package/src/agents/jules/config/system-prompt.js +182 -182
- package/src/agents/jules/error-intake.js +51 -51
- package/src/agents/jules/fix-cycle.js +17 -17
- package/src/agents/jules/loop.js +460 -450
- package/src/agents/jules/pulse.js +10 -10
- package/src/agents/jules/stream.js +187 -186
- package/src/agents/jules/swarm/file-scanner.js +74 -74
- package/src/agents/jules/swarm/index.js +11 -11
- package/src/agents/jules/swarm/orchestrator.js +362 -362
- package/src/agents/jules/swarm/pattern-hunter.js +123 -123
- package/src/agents/jules/swarm/sub-agent.js +315 -309
- package/src/agents/jules/tools/aidenid-email.js +189 -189
- package/src/agents/jules/tools/auth-audit.js +1708 -1691
- package/src/agents/jules/tools/dispatch.js +340 -335
- package/src/agents/jules/tools/file-edit.js +2 -2
- package/src/agents/jules/tools/file-read.js +2 -2
- package/src/agents/jules/tools/frontend-analyze.js +570 -570
- package/src/agents/jules/tools/glob.js +2 -2
- package/src/agents/jules/tools/grep.js +2 -2
- package/src/agents/jules/tools/index.js +29 -29
- package/src/agents/jules/tools/path-guards.js +2 -2
- package/src/agents/jules/tools/runtime-audit.js +507 -507
- package/src/agents/jules/tools/shell.js +2 -2
- package/src/agents/jules/tools/url-policy.js +100 -100
- package/src/agents/mode.js +113 -0
- package/src/agents/observability/index.js +12 -0
- package/src/agents/observability/tools/alert-audit.js +39 -0
- package/src/agents/observability/tools/base.js +181 -0
- package/src/agents/observability/tools/dashboard-gap.js +42 -0
- package/src/agents/observability/tools/index.js +54 -0
- package/src/agents/observability/tools/log-schema-check.js +74 -0
- package/src/agents/observability/tools/span-coverage.js +74 -0
- package/src/agents/persona-visuals.js +102 -61
- package/src/agents/release/index.js +12 -0
- package/src/agents/release/tools/base.js +181 -0
- package/src/agents/release/tools/changelog-diff.js +86 -0
- package/src/agents/release/tools/feature-flag-audit.js +126 -0
- package/src/agents/release/tools/index.js +61 -0
- package/src/agents/release/tools/rollback-verify.js +129 -0
- package/src/agents/release/tools/semver-check.js +109 -0
- package/src/agents/reliability/index.js +12 -0
- package/src/agents/reliability/tools/backpressure-check.js +129 -0
- package/src/agents/reliability/tools/base.js +181 -0
- package/src/agents/reliability/tools/chaos-probe.js +109 -0
- package/src/agents/reliability/tools/graceful-degradation-check.js +114 -0
- package/src/agents/reliability/tools/health-check-audit.js +111 -0
- package/src/agents/reliability/tools/index.js +87 -0
- package/src/agents/run-persona.js +109 -0
- package/src/agents/security/index.js +12 -0
- package/src/agents/security/tools/authz-audit.js +134 -0
- package/src/agents/security/tools/base.js +190 -0
- package/src/agents/security/tools/crypto-review.js +175 -0
- package/src/agents/security/tools/index.js +97 -0
- package/src/agents/security/tools/sast-scan.js +175 -0
- package/src/agents/security/tools/secrets-scan.js +216 -0
- package/src/agents/shared-tools/dispatch-core.js +320 -315
- package/src/agents/shared-tools/file-edit.js +180 -180
- package/src/agents/shared-tools/file-read.js +100 -100
- package/src/agents/shared-tools/glob.js +168 -168
- package/src/agents/shared-tools/grep.js +228 -228
- package/src/agents/shared-tools/index.js +46 -46
- package/src/agents/shared-tools/path-guards.js +161 -161
- package/src/agents/shared-tools/shell.js +383 -383
- package/src/agents/supply-chain/index.js +12 -0
- package/src/agents/supply-chain/tools/attestation-check.js +42 -0
- package/src/agents/supply-chain/tools/base.js +151 -0
- package/src/agents/supply-chain/tools/index.js +52 -0
- package/src/agents/supply-chain/tools/lockfile-integrity.js +73 -0
- package/src/agents/supply-chain/tools/package-verify.js +56 -0
- package/src/agents/supply-chain/tools/sbom-diff.js +34 -0
- package/src/agents/testing/index.js +12 -0
- package/src/agents/testing/tools/base.js +202 -0
- package/src/agents/testing/tools/coverage-gap.js +144 -0
- package/src/agents/testing/tools/flake-detect.js +125 -0
- package/src/agents/testing/tools/index.js +85 -0
- package/src/agents/testing/tools/mutation-test.js +143 -0
- package/src/agents/testing/tools/snapshot-diff.js +103 -0
- package/src/ai/aidenid.js +1021 -1009
- package/src/ai/client.js +553 -553
- package/src/ai/domain-target-store.js +268 -268
- package/src/ai/identity-store.js +270 -270
- package/src/ai/proxy.js +137 -137
- package/src/ai/site-store.js +145 -145
- package/src/audit/agents/architecture.js +180 -180
- package/src/audit/agents/compliance.js +179 -179
- package/src/audit/agents/documentation.js +165 -165
- package/src/audit/agents/performance.js +145 -145
- package/src/audit/agents/security.js +215 -215
- package/src/audit/agents/testing.js +172 -172
- package/src/audit/orchestrator.js +557 -557
- package/src/audit/package.js +204 -204
- package/src/audit/registry.js +284 -284
- package/src/audit/replay.js +103 -103
- package/src/auth/gate.js +428 -371
- package/src/auth/http.js +681 -611
- package/src/auth/service.js +1106 -1106
- package/src/auth/session-store.js +813 -813
- package/src/cli.js +257 -252
- package/src/commands/ai/identity-lifecycle.js +1338 -1338
- package/src/commands/ai/provision-governance.js +1272 -1272
- package/src/commands/ai/shared.js +147 -147
- package/src/commands/ai.js +11 -11
- package/src/commands/apply.js +12 -12
- package/src/commands/audit.js +1171 -1166
- package/src/commands/auth.js +419 -419
- package/src/commands/chat.js +184 -191
- package/src/commands/config.js +184 -184
- package/src/commands/cost.js +311 -311
- package/src/commands/daemon/core.js +850 -850
- package/src/commands/daemon/extended.js +1048 -1048
- package/src/commands/daemon/shared.js +213 -213
- package/src/commands/daemon.js +11 -11
- package/src/commands/guide.js +174 -174
- package/src/commands/ingest.js +58 -58
- package/src/commands/init.js +55 -55
- package/src/commands/legacy-args.js +20 -10
- package/src/commands/mcp.js +461 -461
- package/src/commands/omargate.js +63 -29
- package/src/commands/persona.js +65 -20
- package/src/commands/plugin.js +260 -260
- package/src/commands/policy.js +132 -132
- package/src/commands/prompt.js +238 -238
- package/src/commands/review.js +704 -704
- package/src/commands/scan.js +865 -872
- package/src/commands/session.js +1238 -0
- package/src/commands/spec.js +771 -716
- package/src/commands/swarm.js +651 -651
- package/src/commands/telemetry.js +202 -202
- package/src/commands/watch.js +511 -511
- package/src/config/agent-dictionary.js +182 -182
- package/src/config/io.js +56 -56
- package/src/config/paths.js +18 -18
- package/src/config/schema.js +55 -55
- package/src/config/service.js +184 -184
- package/src/coord/events-log.js +141 -0
- package/src/coord/handshake.js +719 -0
- package/src/coord/index.js +35 -0
- package/src/coord/paths.js +84 -0
- package/src/coord/priority.js +62 -0
- package/src/coord/tarjan.js +157 -0
- package/src/cost/budget.js +235 -235
- package/src/cost/history.js +188 -188
- package/src/cost/tokenizer.js +160 -0
- package/src/cost/tracker.js +232 -171
- package/src/daemon/artifact-lineage.js +896 -534
- package/src/daemon/assignment-ledger.js +1083 -770
- package/src/daemon/ast-drift.js +496 -0
- package/src/daemon/ast-parser-layer.js +258 -258
- package/src/daemon/budget-governor.js +633 -633
- package/src/daemon/callgraph-overlay.js +646 -646
- package/src/daemon/error-worker.js +1209 -626
- package/src/daemon/fix-cycle.js +384 -377
- package/src/daemon/hybrid-mapper.js +929 -929
- package/src/daemon/ingest-refresh.js +79 -11
- package/src/daemon/jira-lifecycle.js +767 -632
- package/src/daemon/operator-control.js +657 -657
- package/src/daemon/pulse.js +327 -327
- package/src/daemon/reliability-lane.js +471 -471
- package/src/daemon/scope-engine.js +1068 -0
- package/src/daemon/watchdog.js +971 -971
- package/src/events/schema.js +190 -0
- package/src/guide/generator.js +316 -316
- package/src/ingest/engine.js +933 -918
- package/src/ingest/ownership.js +380 -0
- package/src/interactive/index.js +97 -97
- package/src/legacy-cli.js +3228 -2994
- package/src/mcp/registry.js +695 -695
- package/src/memory/blackboard.js +301 -301
- package/src/memory/retrieval.js +581 -581
- package/src/orchestrator/kai-chen.js +126 -0
- package/src/plugin/manifest.js +553 -553
- package/src/policy/packs.js +144 -144
- package/src/prompt/generator.js +136 -118
- package/src/review/ai-review.js +672 -679
- package/src/review/compliance-pack.js +389 -0
- package/src/review/investor-dd-config.js +54 -0
- package/src/review/investor-dd-file-loop.js +303 -0
- package/src/review/investor-dd-file-router.js +406 -0
- package/src/review/investor-dd-html-report.js +233 -0
- package/src/review/investor-dd-notification.js +120 -0
- package/src/review/investor-dd-orchestrator.js +405 -0
- package/src/review/investor-dd-persona-runner.js +275 -0
- package/src/review/live-validator.js +253 -0
- package/src/review/local-review.js +1351 -1305
- package/src/review/omargate-interactive.js +68 -68
- package/src/review/omargate-orchestrator.js +492 -300
- package/src/review/persona-prompts.js +484 -296
- package/src/review/reconciliation-rules.js +329 -0
- package/src/review/replay.js +235 -235
- package/src/review/report.js +664 -664
- package/src/review/reproducibility-chain.js +136 -0
- package/src/review/scan-modes.js +147 -42
- package/src/review/spec-binding.js +487 -487
- package/src/scaffold/generator.js +67 -67
- package/src/scaffold/templates.js +150 -150
- package/src/scan/generator.js +418 -418
- package/src/scan/gh-secrets.js +107 -107
- package/src/session/agent-registry.js +359 -0
- package/src/session/analytics.js +479 -0
- package/src/session/daemon.js +1396 -0
- package/src/session/file-locks.js +666 -0
- package/src/session/paths.js +37 -0
- package/src/session/recap.js +567 -0
- package/src/session/redact.js +82 -0
- package/src/session/runtime-bridge.js +762 -0
- package/src/session/scoring.js +406 -0
- package/src/session/setup-guides.js +304 -0
- package/src/session/store.js +704 -0
- package/src/session/stream.js +333 -0
- package/src/session/sync.js +753 -0
- package/src/session/tasks.js +1054 -0
- package/src/session/templates.js +188 -0
- package/src/spec/generator.js +619 -519
- package/src/spec/regenerate.js +237 -237
- package/src/spec/templates.js +91 -91
- package/src/swarm/dashboard.js +247 -247
- package/src/swarm/factory.js +363 -363
- package/src/swarm/pentest.js +934 -934
- package/src/swarm/registry.js +419 -419
- package/src/swarm/report.js +158 -158
- package/src/swarm/runtime.js +569 -576
- package/src/swarm/scenario-dsl.js +272 -272
- package/src/telemetry/ledger.js +302 -302
- package/src/telemetry/session-tracker.js +234 -234
- package/src/telemetry/sync.js +203 -203
- package/src/ui/command-hints.js +13 -13
- package/src/ui/markdown.js +220 -220
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compliance pack — SOC 2 / ISO 27001 / GDPR-CCPA / HIPAA / license / DR
|
|
3
|
+
* (#investor-dd-20..24).
|
|
4
|
+
*
|
|
5
|
+
* Runs as a persona-adjacent dispatch under the investor-DD umbrella.
|
|
6
|
+
* Leila Farouk owns this lane: she cross-reads every file in the repo
|
|
7
|
+
* against standards-oriented checklists and emits a compliance-gap
|
|
8
|
+
* table. Each gap has the control id, the expected artifact, what was
|
|
9
|
+
* searched for, whether it was found, and (if found) where.
|
|
10
|
+
*
|
|
11
|
+
* The pack is artifact-driven — no LLM. It reads the repo, looks for
|
|
12
|
+
* documented controls, and reports gaps. Downstream PRs may layer an
|
|
13
|
+
* LLM review on top, but the ground-truth floor is deterministic so an
|
|
14
|
+
* acquirer's auditor can re-run it and get the same gap table.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import fsp from "node:fs/promises";
|
|
18
|
+
import path from "node:path";
|
|
19
|
+
|
|
20
|
+
export const COMPLIANCE_PACK_VERSION = "1.0.0";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Walk a repo and collect file list (skips known noise dirs). Produces
|
|
24
|
+
* the same walker output as the orchestrator so the pack can reuse
|
|
25
|
+
* artifacts when run inside a larger investor-DD flow.
|
|
26
|
+
*/
|
|
27
|
+
async function walkFiles(rootPath) {
|
|
28
|
+
const SKIP = new Set([
|
|
29
|
+
"node_modules",
|
|
30
|
+
".git",
|
|
31
|
+
"dist",
|
|
32
|
+
"build",
|
|
33
|
+
"coverage",
|
|
34
|
+
".sentinelayer",
|
|
35
|
+
".next",
|
|
36
|
+
"__pycache__",
|
|
37
|
+
]);
|
|
38
|
+
const out = [];
|
|
39
|
+
async function walk(abs, rel) {
|
|
40
|
+
let entries;
|
|
41
|
+
try {
|
|
42
|
+
entries = await fsp.readdir(abs, { withFileTypes: true });
|
|
43
|
+
} catch {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
for (const e of entries) {
|
|
47
|
+
if (e.name.startsWith(".") && e.name !== ".github" && e.name !== ".gitignore") continue;
|
|
48
|
+
if (e.isDirectory() && SKIP.has(e.name)) continue;
|
|
49
|
+
const absPath = path.join(abs, e.name);
|
|
50
|
+
const relPath = rel ? `${rel}/${e.name}` : e.name;
|
|
51
|
+
if (e.isDirectory()) {
|
|
52
|
+
await walk(absPath, relPath);
|
|
53
|
+
} else if (e.isFile()) {
|
|
54
|
+
out.push({ relPath, absPath });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
await walk(rootPath, "");
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function fileExistsAnyName(files, patterns) {
|
|
63
|
+
for (const { relPath } of files) {
|
|
64
|
+
for (const p of patterns) {
|
|
65
|
+
if (relPath.toLowerCase().includes(p.toLowerCase())) return relPath;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function fileContentContains(files, regex) {
|
|
72
|
+
for (const { relPath, absPath } of files) {
|
|
73
|
+
try {
|
|
74
|
+
const stat = await fsp.stat(absPath);
|
|
75
|
+
if (stat.size > 1024 * 1024) continue; // skip > 1MB
|
|
76
|
+
const text = await fsp.readFile(absPath, "utf-8");
|
|
77
|
+
if (regex.test(text)) return { file: relPath, match: true };
|
|
78
|
+
} catch {
|
|
79
|
+
// unreadable file; skip
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return { file: null, match: false };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* SOC 2 Trust Service Criteria coverage. Focus: the controls whose
|
|
87
|
+
* evidence is typically in-repo (logging, backups, access control,
|
|
88
|
+
* change management). Operational controls that live outside the repo
|
|
89
|
+
* (personnel security, facilities) are out of scope for a code-level
|
|
90
|
+
* audit.
|
|
91
|
+
*/
|
|
92
|
+
const SOC2_CHECKLIST = Object.freeze([
|
|
93
|
+
{
|
|
94
|
+
controlId: "CC6.1",
|
|
95
|
+
title: "Logical access controls enforced",
|
|
96
|
+
expected: "Auth middleware / route guards in code",
|
|
97
|
+
searchPaths: ["auth", "middleware", "guard"],
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
controlId: "CC6.6",
|
|
101
|
+
title: "Transmission of confidential data is encrypted",
|
|
102
|
+
expected: "HTTPS + TLS config references",
|
|
103
|
+
searchRegex: /(https:\/\/|tls|ssl|cert)/i,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
controlId: "CC7.1",
|
|
107
|
+
title: "Configuration management and change tracking",
|
|
108
|
+
expected: "CHANGELOG or release notes",
|
|
109
|
+
searchPaths: ["CHANGELOG", "RELEASES"],
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
controlId: "CC7.2",
|
|
113
|
+
title: "System monitoring and alerting",
|
|
114
|
+
expected: "Observability config, dashboards, or alerts",
|
|
115
|
+
searchPaths: ["monitor", "alert", "dashboard", "grafana", "datadog", "sentry"],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
controlId: "CC7.3",
|
|
119
|
+
title: "Anomaly / incident detection",
|
|
120
|
+
expected: "Security incident playbook or runbook",
|
|
121
|
+
searchPaths: ["incident", "runbook", "playbook", "SECURITY.md"],
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
controlId: "CC8.1",
|
|
125
|
+
title: "Data backups and restoration tested",
|
|
126
|
+
expected: "Backup policy or DR runbook",
|
|
127
|
+
searchPaths: ["backup", "disaster-recovery", "dr-", "restore"],
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
controlId: "A1.2",
|
|
131
|
+
title: "Availability — RTO/RPO documented",
|
|
132
|
+
expected: "RTO/RPO mentions in docs",
|
|
133
|
+
searchRegex: /\b(rto|rpo|recovery[\s-]time|recovery[\s-]point)\b/i,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
controlId: "P2.1",
|
|
137
|
+
title: "Privacy notice provided to users",
|
|
138
|
+
expected: "PRIVACY.md or privacy-policy",
|
|
139
|
+
searchPaths: ["PRIVACY", "privacy-policy", "privacy_policy"],
|
|
140
|
+
},
|
|
141
|
+
]);
|
|
142
|
+
|
|
143
|
+
const ISO27001_CHECKLIST = Object.freeze([
|
|
144
|
+
{
|
|
145
|
+
controlId: "A.5.1",
|
|
146
|
+
title: "Information security policy documented",
|
|
147
|
+
expected: "SECURITY.md",
|
|
148
|
+
searchPaths: ["SECURITY.md"],
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
controlId: "A.8.1",
|
|
152
|
+
title: "Asset inventory",
|
|
153
|
+
expected: "SBOM or dependency manifest",
|
|
154
|
+
searchPaths: ["sbom", "package.json", "requirements.txt", "go.mod", "Cargo.toml"],
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
controlId: "A.9.2",
|
|
158
|
+
title: "User access management",
|
|
159
|
+
expected: "User / role / permission definitions",
|
|
160
|
+
searchPaths: ["role", "permission", "rbac"],
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
controlId: "A.12.4",
|
|
164
|
+
title: "Event logging",
|
|
165
|
+
expected: "Logging library usage",
|
|
166
|
+
searchRegex: /\b(log(ger)?|structlog|winston|bunyan|pino)\b/i,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
controlId: "A.13.1",
|
|
170
|
+
title: "Network security controls",
|
|
171
|
+
expected: "Ingress / firewall / VPC / security-group config",
|
|
172
|
+
searchPaths: ["ingress", "firewall", "security-group", "security_group", "vpc"],
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
controlId: "A.14.2",
|
|
176
|
+
title: "Secure development process",
|
|
177
|
+
expected: "CI workflow with linting / testing / security scan",
|
|
178
|
+
searchPaths: [".github/workflows", "azure-pipelines", ".gitlab-ci", "jenkinsfile"],
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
controlId: "A.16.1",
|
|
182
|
+
title: "Incident management procedures",
|
|
183
|
+
expected: "Incident response runbook",
|
|
184
|
+
searchPaths: ["incident", "runbook", "postmortem"],
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
controlId: "A.17.1",
|
|
188
|
+
title: "Business continuity",
|
|
189
|
+
expected: "Failover / DR runbook",
|
|
190
|
+
searchPaths: ["disaster-recovery", "dr-", "failover", "business-continuity"],
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
controlId: "A.18.1",
|
|
194
|
+
title: "Compliance with legal requirements",
|
|
195
|
+
expected: "LICENSE file",
|
|
196
|
+
searchPaths: ["LICENSE", "LICENCE"],
|
|
197
|
+
},
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
const GDPR_CCPA_CHECKLIST = Object.freeze([
|
|
201
|
+
{
|
|
202
|
+
controlId: "GDPR.DS-Rights",
|
|
203
|
+
title: "Data subject rights endpoints (access / deletion / export)",
|
|
204
|
+
expected: "User deletion or data-export endpoints",
|
|
205
|
+
searchRegex: /(delete[_-]?user|user[_-]?delete|right[_-]?to[_-]?be[_-]?forgotten|data[_-]?export)/i,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
controlId: "GDPR.Consent",
|
|
209
|
+
title: "Consent capture / ledger",
|
|
210
|
+
expected: "Consent tracking code or schema",
|
|
211
|
+
searchRegex: /\bconsent\b.*\b(given|captured|record)/i,
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
controlId: "GDPR.LawfulBasis",
|
|
215
|
+
title: "Lawful basis documentation",
|
|
216
|
+
expected: "Privacy policy with legal basis",
|
|
217
|
+
searchRegex: /legitimate[\s-]?interest|legal[\s-]?basis|lawful[\s-]?basis/i,
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
controlId: "GDPR.DPA",
|
|
221
|
+
title: "Data Processing Agreement template",
|
|
222
|
+
expected: "DPA.md or data-processing-agreement",
|
|
223
|
+
searchPaths: ["DPA", "data-processing-agreement"],
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
controlId: "CCPA.DoNotSell",
|
|
227
|
+
title: "Do-Not-Sell / Opt-Out endpoint",
|
|
228
|
+
expected: "Do-not-sell link or endpoint",
|
|
229
|
+
searchRegex: /do[\s-]?not[\s-]?sell|opt[\s-]?out[\s-]?of[\s-]?sale/i,
|
|
230
|
+
},
|
|
231
|
+
]);
|
|
232
|
+
|
|
233
|
+
const HIPAA_CHECKLIST = Object.freeze([
|
|
234
|
+
{
|
|
235
|
+
controlId: "HIPAA.PHI",
|
|
236
|
+
title: "PHI field identification in schema",
|
|
237
|
+
expected: "Fields tagged as PHI or PII",
|
|
238
|
+
searchRegex: /\b(phi|ssn|dob|diagnosis|icd10|mrn|health[\s_-]?record)\b/i,
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
controlId: "HIPAA.Encryption",
|
|
242
|
+
title: "Encryption at rest",
|
|
243
|
+
expected: "Database encryption config",
|
|
244
|
+
searchRegex: /encryption[\s_-]?at[\s_-]?rest|kms[\s_-]?key|aes[\s_-]?256/i,
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
controlId: "HIPAA.AuditLog",
|
|
248
|
+
title: "PHI access audit log",
|
|
249
|
+
expected: "Access log table or middleware",
|
|
250
|
+
searchRegex: /audit[\s_-]?log|phi[\s_-]?access[\s_-]?log/i,
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
controlId: "HIPAA.BAA",
|
|
254
|
+
title: "Business Associate Agreement references",
|
|
255
|
+
expected: "BAA.md or BAA template",
|
|
256
|
+
searchPaths: ["BAA", "business-associate"],
|
|
257
|
+
},
|
|
258
|
+
]);
|
|
259
|
+
|
|
260
|
+
const LICENSE_CHECKLIST = Object.freeze([
|
|
261
|
+
{
|
|
262
|
+
controlId: "LIC.Root",
|
|
263
|
+
title: "Root LICENSE file present",
|
|
264
|
+
expected: "LICENSE",
|
|
265
|
+
searchPaths: ["LICENSE", "LICENCE", "LICENSE.md"],
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
controlId: "LIC.Manifest",
|
|
269
|
+
title: "License declared in package manifest",
|
|
270
|
+
expected: "license field in package.json / pyproject.toml",
|
|
271
|
+
searchRegex: /"license"\s*:\s*"|^license\s*=\s*"/m,
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
controlId: "LIC.SBOM",
|
|
275
|
+
title: "SBOM artifact",
|
|
276
|
+
expected: "SBOM or sbom.json / sbom.spdx.json",
|
|
277
|
+
searchPaths: ["sbom", "SBOM"],
|
|
278
|
+
},
|
|
279
|
+
]);
|
|
280
|
+
|
|
281
|
+
const DR_CHECKLIST = Object.freeze([
|
|
282
|
+
{
|
|
283
|
+
controlId: "DR.RTO",
|
|
284
|
+
title: "Documented RTO",
|
|
285
|
+
searchRegex: /\brto\b/i,
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
controlId: "DR.RPO",
|
|
289
|
+
title: "Documented RPO",
|
|
290
|
+
searchRegex: /\brpo\b/i,
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
controlId: "DR.Runbook",
|
|
294
|
+
title: "Disaster-recovery runbook",
|
|
295
|
+
searchPaths: ["disaster-recovery", "dr-runbook", "runbook/recovery"],
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
controlId: "DR.BackupTest",
|
|
299
|
+
title: "Evidence of backup restore test",
|
|
300
|
+
searchRegex: /restore[\s_-]?test|backup[\s_-]?verified|test[\s_-]?restore/i,
|
|
301
|
+
},
|
|
302
|
+
]);
|
|
303
|
+
|
|
304
|
+
const PACKS = Object.freeze({
|
|
305
|
+
soc2: SOC2_CHECKLIST,
|
|
306
|
+
iso27001: ISO27001_CHECKLIST,
|
|
307
|
+
gdpr: GDPR_CCPA_CHECKLIST,
|
|
308
|
+
ccpa: GDPR_CCPA_CHECKLIST,
|
|
309
|
+
hipaa: HIPAA_CHECKLIST,
|
|
310
|
+
license: LICENSE_CHECKLIST,
|
|
311
|
+
dr: DR_CHECKLIST,
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
export const COMPLIANCE_PACK_CATALOG = Object.freeze(Object.keys(PACKS));
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Evaluate one checklist item against the repo. Returns a gap record
|
|
318
|
+
* whether the control was satisfied or not — the consumer interprets
|
|
319
|
+
* `status` to produce a final report.
|
|
320
|
+
*/
|
|
321
|
+
async function evaluateChecklistItem(item, files) {
|
|
322
|
+
let foundFile = null;
|
|
323
|
+
if (Array.isArray(item.searchPaths) && item.searchPaths.length > 0) {
|
|
324
|
+
foundFile = fileExistsAnyName(files, item.searchPaths);
|
|
325
|
+
}
|
|
326
|
+
if (!foundFile && item.searchRegex) {
|
|
327
|
+
const contentHit = await fileContentContains(files, item.searchRegex);
|
|
328
|
+
if (contentHit.match) foundFile = contentHit.file;
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
controlId: item.controlId,
|
|
332
|
+
title: item.title,
|
|
333
|
+
expected: item.expected || "",
|
|
334
|
+
status: foundFile ? "covered" : "gap",
|
|
335
|
+
evidenceFile: foundFile,
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Run one compliance pack against the repo.
|
|
341
|
+
*
|
|
342
|
+
* @param {string} packId - e.g., "soc2", "iso27001", "gdpr", ...
|
|
343
|
+
* @param {{rootPath: string, files?: Array<{relPath: string, absPath: string}>}} params
|
|
344
|
+
* @returns {Promise<{packId: string, items: Array, covered: number, gaps: number}>}
|
|
345
|
+
*/
|
|
346
|
+
export async function runCompliancePack(packId, { rootPath, files } = {}) {
|
|
347
|
+
const checklist = PACKS[packId];
|
|
348
|
+
if (!checklist) throw new Error(`Unknown compliance pack: ${packId}`);
|
|
349
|
+
if (!rootPath) throw new TypeError("runCompliancePack requires rootPath");
|
|
350
|
+
const walked = files || (await walkFiles(rootPath));
|
|
351
|
+
|
|
352
|
+
const items = [];
|
|
353
|
+
let covered = 0;
|
|
354
|
+
let gaps = 0;
|
|
355
|
+
for (const item of checklist) {
|
|
356
|
+
const record = await evaluateChecklistItem(item, walked);
|
|
357
|
+
items.push(record);
|
|
358
|
+
if (record.status === "covered") covered += 1;
|
|
359
|
+
else gaps += 1;
|
|
360
|
+
}
|
|
361
|
+
return { packId, items, covered, gaps };
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Run the full compliance pack suite.
|
|
366
|
+
*
|
|
367
|
+
* @param {object} params
|
|
368
|
+
* @param {string} params.rootPath
|
|
369
|
+
* @param {string[]} [params.packs] - Subset of pack IDs (default all).
|
|
370
|
+
* @returns {Promise<{packs: Record<string, object>, totalCovered: number, totalGaps: number}>}
|
|
371
|
+
*/
|
|
372
|
+
export async function runFullCompliancePack({
|
|
373
|
+
rootPath,
|
|
374
|
+
packs = COMPLIANCE_PACK_CATALOG,
|
|
375
|
+
} = {}) {
|
|
376
|
+
if (!rootPath) throw new TypeError("runFullCompliancePack requires rootPath");
|
|
377
|
+
const files = await walkFiles(rootPath);
|
|
378
|
+
const results = {};
|
|
379
|
+
let totalCovered = 0;
|
|
380
|
+
let totalGaps = 0;
|
|
381
|
+
for (const packId of packs) {
|
|
382
|
+
if (!PACKS[packId]) continue;
|
|
383
|
+
const result = await runCompliancePack(packId, { rootPath, files });
|
|
384
|
+
results[packId] = result;
|
|
385
|
+
totalCovered += result.covered;
|
|
386
|
+
totalGaps += result.gaps;
|
|
387
|
+
}
|
|
388
|
+
return { packs: results, totalCovered, totalGaps };
|
|
389
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// Investor-DD mode configuration scaffold.
|
|
2
|
+
//
|
|
3
|
+
// Subsequent PRs in the docs/INVESTOR_DD_ARCHITECTURE.md sequence consume
|
|
4
|
+
// these constants. Keeping them in a dedicated module so future PRs can
|
|
5
|
+
// extend without touching the command definition or the legacy dispatch.
|
|
6
|
+
|
|
7
|
+
export const INVESTOR_DD_VERSION = "1.0.0";
|
|
8
|
+
|
|
9
|
+
// Budget defaults — see architecture doc "Cost model" section.
|
|
10
|
+
export const INVESTOR_DD_DEFAULT_MAX_COST_USD = 25.0;
|
|
11
|
+
export const INVESTOR_DD_DEFAULT_MAX_RUNTIME_MINUTES = 45;
|
|
12
|
+
export const INVESTOR_DD_DEFAULT_MAX_PARALLEL = 3;
|
|
13
|
+
|
|
14
|
+
// Lower concurrency than /omargate deep (4) — each persona now runs a
|
|
15
|
+
// multi-turn per-file loop rather than a single-shot call, so concurrent
|
|
16
|
+
// file I/O + LLM calls compete for the same rate-limit pool.
|
|
17
|
+
|
|
18
|
+
// Compliance pack opt-in flags. HIPAA is opt-in because surfacing PHI
|
|
19
|
+
// requires customer consent; SOC 2 / ISO 27001 / GDPR run by default
|
|
20
|
+
// once the pack scaffolds land (Batch 6).
|
|
21
|
+
export const INVESTOR_DD_SUPPORTED_COMPLIANCE_PACKS = Object.freeze([
|
|
22
|
+
"soc2", // Trust Service Criteria 2017 + 2022
|
|
23
|
+
"iso27001", // Annex A relevant controls
|
|
24
|
+
"gdpr", // Data-subject rights + lawful basis
|
|
25
|
+
"ccpa", // California equivalents
|
|
26
|
+
"hipaa", // Opt-in, requires --compliance-pack hipaa
|
|
27
|
+
"license", // SPDX + SBOM parity
|
|
28
|
+
"dr", // Disaster recovery / RPO-RTO / failover
|
|
29
|
+
]);
|
|
30
|
+
|
|
31
|
+
// Artifact directory inside the run's root. Each PR in Batch 5 writes a
|
|
32
|
+
// specific file here (plan.json, stream.ndjson, report.md, etc.).
|
|
33
|
+
export const INVESTOR_DD_ARTIFACT_SUBDIR = "investor-dd";
|
|
34
|
+
|
|
35
|
+
// Slash command token. Consumers should reference this constant rather
|
|
36
|
+
// than a string literal so renaming stays deterministic.
|
|
37
|
+
export const INVESTOR_DD_COMMAND_TOKEN = "investor-dd";
|
|
38
|
+
|
|
39
|
+
export function resolveInvestorDdBudget(options = {}) {
|
|
40
|
+
const maxCostUsd = Number(options.maxCostUsd);
|
|
41
|
+
const maxRuntimeMinutes = Number(options.maxRuntimeMinutes);
|
|
42
|
+
const maxParallel = Number(options.maxParallel);
|
|
43
|
+
return {
|
|
44
|
+
maxCostUsd: Number.isFinite(maxCostUsd) && maxCostUsd > 0
|
|
45
|
+
? maxCostUsd
|
|
46
|
+
: INVESTOR_DD_DEFAULT_MAX_COST_USD,
|
|
47
|
+
maxRuntimeMinutes: Number.isFinite(maxRuntimeMinutes) && maxRuntimeMinutes > 0
|
|
48
|
+
? Math.floor(maxRuntimeMinutes)
|
|
49
|
+
: INVESTOR_DD_DEFAULT_MAX_RUNTIME_MINUTES,
|
|
50
|
+
maxParallel: Number.isFinite(maxParallel) && maxParallel > 0
|
|
51
|
+
? Math.floor(maxParallel)
|
|
52
|
+
: INVESTOR_DD_DEFAULT_MAX_PARALLEL,
|
|
53
|
+
};
|
|
54
|
+
}
|