sentinelayer-cli 0.4.4 → 0.6.2
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 +996 -998
- package/bin/create-sentinelayer.js +5 -5
- package/bin/sentinelayer-cli.js +4 -4
- package/bin/sl.js +5 -5
- package/package.json +63 -63
- package/src/agents/jules/config/definition.js +160 -209
- package/src/agents/jules/config/system-prompt.js +182 -175
- package/src/agents/jules/error-intake.js +51 -51
- package/src/agents/jules/fix-cycle.js +17 -377
- package/src/agents/jules/loop.js +450 -367
- package/src/agents/jules/pulse.js +10 -327
- package/src/agents/jules/stream.js +186 -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 +309 -308
- package/src/agents/jules/tools/aidenid-email.js +189 -0
- package/src/agents/jules/tools/auth-audit.js +1691 -557
- package/src/agents/jules/tools/dispatch.js +335 -327
- package/src/agents/jules/tools/file-edit.js +2 -180
- package/src/agents/jules/tools/file-read.js +2 -100
- package/src/agents/jules/tools/frontend-analyze.js +570 -570
- package/src/agents/jules/tools/glob.js +2 -168
- package/src/agents/jules/tools/grep.js +2 -228
- package/src/agents/jules/tools/index.js +29 -29
- package/src/agents/jules/tools/path-guards.js +2 -161
- package/src/agents/jules/tools/runtime-audit.js +507 -503
- package/src/agents/jules/tools/shell.js +2 -383
- package/src/agents/jules/tools/url-policy.js +100 -100
- package/src/agents/persona-visuals.js +61 -0
- package/src/agents/shared-tools/dispatch-core.js +315 -0
- package/src/agents/shared-tools/file-edit.js +180 -0
- package/src/agents/shared-tools/file-read.js +100 -0
- package/src/agents/shared-tools/glob.js +168 -0
- package/src/agents/shared-tools/grep.js +228 -0
- package/src/agents/shared-tools/index.js +46 -0
- package/src/agents/shared-tools/path-guards.js +161 -0
- package/src/agents/shared-tools/shell.js +383 -0
- package/src/ai/aidenid.js +1009 -972
- package/src/ai/client.js +553 -508
- package/src/ai/domain-target-store.js +268 -268
- package/src/ai/identity-store.js +270 -270
- package/src/ai/proxy.js +137 -0
- 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 +371 -126
- package/src/auth/http.js +611 -270
- package/src/auth/service.js +1106 -891
- package/src/auth/session-store.js +813 -359
- package/src/cli.js +252 -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 +1166 -1166
- package/src/commands/auth.js +419 -375
- package/src/commands/chat.js +191 -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 +10 -10
- package/src/commands/mcp.js +461 -461
- package/src/commands/omargate.js +29 -21
- package/src/commands/persona.js +20 -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 +872 -866
- package/src/commands/spec.js +716 -716
- package/src/commands/swarm.js +651 -651
- package/src/commands/telemetry.js +202 -202
- package/src/commands/watch.js +511 -510
- 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/cost/budget.js +235 -235
- package/src/cost/history.js +188 -188
- package/src/cost/tracker.js +171 -171
- package/src/daemon/artifact-lineage.js +534 -534
- package/src/daemon/assignment-ledger.js +770 -770
- 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 +626 -626
- package/src/daemon/fix-cycle.js +377 -0
- package/src/daemon/hybrid-mapper.js +929 -929
- package/src/daemon/jira-lifecycle.js +632 -632
- package/src/daemon/operator-control.js +657 -657
- package/src/daemon/pulse.js +327 -0
- package/src/daemon/reliability-lane.js +471 -471
- package/src/daemon/watchdog.js +971 -971
- package/src/guide/generator.js +316 -316
- package/src/ingest/engine.js +918 -918
- package/src/interactive/index.js +97 -95
- package/src/legacy-cli.js +2994 -2592
- package/src/mcp/registry.js +695 -695
- package/src/memory/blackboard.js +301 -301
- package/src/memory/retrieval.js +581 -581
- package/src/plugin/manifest.js +553 -553
- package/src/policy/packs.js +144 -144
- package/src/prompt/generator.js +118 -118
- package/src/review/ai-review.js +679 -669
- package/src/review/local-review.js +1305 -1295
- package/src/review/omargate-interactive.js +68 -0
- package/src/review/omargate-orchestrator.js +300 -0
- package/src/review/persona-prompts.js +296 -0
- package/src/review/replay.js +235 -235
- package/src/review/report.js +664 -664
- package/src/review/scan-modes.js +42 -0
- 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/spec/generator.js +519 -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 +576 -576
- package/src/swarm/scenario-dsl.js +272 -272
- package/src/telemetry/ledger.js +302 -302
- package/src/telemetry/session-tracker.js +234 -118
- package/src/telemetry/sync.js +203 -199
- package/src/ui/command-hints.js +13 -0
- package/src/ui/markdown.js +220 -220
package/src/scan/gh-secrets.js
CHANGED
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
|
-
import process from "node:process";
|
|
3
|
-
import fs from "node:fs";
|
|
4
|
-
|
|
5
|
-
function getGhCommand() {
|
|
6
|
-
return String(process.env.SENTINELAYER_GH_BIN || "").trim() || "gh";
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function normalizeRepoSlug(value) {
|
|
10
|
-
return String(value || "").trim().replace(/\.git$/i, "");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function isValidRepoSlug(value) {
|
|
14
|
-
return /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(normalizeRepoSlug(value));
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function isValidSecretName(value) {
|
|
18
|
-
return /^[A-Z][A-Z0-9_]{1,127}$/.test(String(value || "").trim());
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function ensureGhCliAvailable(ghCommand) {
|
|
22
|
-
const ghVersion = spawnSync(ghCommand, ["--version"], { encoding: "utf-8" });
|
|
23
|
-
if (ghVersion.status !== 0) {
|
|
24
|
-
throw new Error("GitHub CLI (gh) is not installed or not in PATH.");
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function detectRepoSlug(cwd) {
|
|
29
|
-
const ghCommand = getGhCommand();
|
|
30
|
-
const result = spawnSync(ghCommand, ["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"], {
|
|
31
|
-
cwd,
|
|
32
|
-
encoding: "utf-8",
|
|
33
|
-
});
|
|
34
|
-
if (result.status === 0 && result.stdout) {
|
|
35
|
-
return String(result.stdout).trim();
|
|
36
|
-
}
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function setupSecrets({ repoSlug, secretName, secretValue, dryRun }) {
|
|
41
|
-
const normalizedRepo = normalizeRepoSlug(repoSlug);
|
|
42
|
-
const ghCommand = getGhCommand();
|
|
43
|
-
|
|
44
|
-
if (!isValidRepoSlug(normalizedRepo)) {
|
|
45
|
-
return { ok: false, reason: "Invalid repo format. Use owner/repo." };
|
|
46
|
-
}
|
|
47
|
-
if (!isValidSecretName(secretName)) {
|
|
48
|
-
return { ok: false, reason: `Invalid secret name: ${secretName}. Must match /^[A-Z][A-Z0-9_]{1,127}$/.` };
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (dryRun) {
|
|
52
|
-
return {
|
|
53
|
-
ok: true,
|
|
54
|
-
dryRun: true,
|
|
55
|
-
repo: normalizedRepo,
|
|
56
|
-
secretName,
|
|
57
|
-
instructions: [
|
|
58
|
-
`gh secret set ${secretName} --repo ${normalizedRepo}`,
|
|
59
|
-
`# Paste your SentinelLayer token when prompted`,
|
|
60
|
-
`gh secret list --repo ${normalizedRepo}`,
|
|
61
|
-
`# Verify ${secretName} appears in the list`,
|
|
62
|
-
],
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const secretSinkFile = String(process.env.SENTINELAYER_SECRET_SINK_FILE || "").trim();
|
|
67
|
-
if (secretSinkFile) {
|
|
68
|
-
try {
|
|
69
|
-
fs.appendFileSync(secretSinkFile, `${normalizedRepo}|${secretName}|${secretValue}\n`, "utf-8");
|
|
70
|
-
return { ok: true, repo: normalizedRepo, secretName, method: "sink-file" };
|
|
71
|
-
} catch (error) {
|
|
72
|
-
return { ok: false, reason: `Failed to write SENTINELAYER_SECRET_SINK_FILE: ${error instanceof Error ? error.message : String(error)}` };
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
try {
|
|
77
|
-
ensureGhCliAvailable(ghCommand);
|
|
78
|
-
} catch (error) {
|
|
79
|
-
return { ok: false, reason: error instanceof Error ? error.message : String(error) };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const result = spawnSync(ghCommand, ["secret", "set", secretName, "--repo", normalizedRepo], {
|
|
83
|
-
encoding: "utf-8",
|
|
84
|
-
input: `${secretValue}\n`,
|
|
85
|
-
});
|
|
86
|
-
if (result.status !== 0) {
|
|
87
|
-
return { ok: false, reason: String(result.stderr || result.stdout || "gh secret set failed").trim() };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const verifyResult = spawnSync(ghCommand, ["secret", "list", "--repo", normalizedRepo], {
|
|
91
|
-
encoding: "utf-8",
|
|
92
|
-
});
|
|
93
|
-
if (verifyResult.status !== 0) {
|
|
94
|
-
return { ok: false, reason: String(verifyResult.stderr || verifyResult.stdout || "gh secret list failed").trim() };
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const listedSecrets = String(verifyResult.stdout || "");
|
|
98
|
-
const escapedSecretName = String(secretName || "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
99
|
-
const secretRegex = new RegExp(`(^|\\r?\\n)\\s*${escapedSecretName}(\\s|$)`, "m");
|
|
100
|
-
if (!secretRegex.test(listedSecrets)) {
|
|
101
|
-
return { ok: false, reason: `Secret '${secretName}' was not visible in gh secret list output after injection.` };
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return { ok: true, repo: normalizedRepo, secretName, method: "gh-cli" };
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export { detectRepoSlug };
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
|
|
5
|
+
function getGhCommand() {
|
|
6
|
+
return String(process.env.SENTINELAYER_GH_BIN || "").trim() || "gh";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function normalizeRepoSlug(value) {
|
|
10
|
+
return String(value || "").trim().replace(/\.git$/i, "");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function isValidRepoSlug(value) {
|
|
14
|
+
return /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(normalizeRepoSlug(value));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isValidSecretName(value) {
|
|
18
|
+
return /^[A-Z][A-Z0-9_]{1,127}$/.test(String(value || "").trim());
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function ensureGhCliAvailable(ghCommand) {
|
|
22
|
+
const ghVersion = spawnSync(ghCommand, ["--version"], { encoding: "utf-8" });
|
|
23
|
+
if (ghVersion.status !== 0) {
|
|
24
|
+
throw new Error("GitHub CLI (gh) is not installed or not in PATH.");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function detectRepoSlug(cwd) {
|
|
29
|
+
const ghCommand = getGhCommand();
|
|
30
|
+
const result = spawnSync(ghCommand, ["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"], {
|
|
31
|
+
cwd,
|
|
32
|
+
encoding: "utf-8",
|
|
33
|
+
});
|
|
34
|
+
if (result.status === 0 && result.stdout) {
|
|
35
|
+
return String(result.stdout).trim();
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function setupSecrets({ repoSlug, secretName, secretValue, dryRun }) {
|
|
41
|
+
const normalizedRepo = normalizeRepoSlug(repoSlug);
|
|
42
|
+
const ghCommand = getGhCommand();
|
|
43
|
+
|
|
44
|
+
if (!isValidRepoSlug(normalizedRepo)) {
|
|
45
|
+
return { ok: false, reason: "Invalid repo format. Use owner/repo." };
|
|
46
|
+
}
|
|
47
|
+
if (!isValidSecretName(secretName)) {
|
|
48
|
+
return { ok: false, reason: `Invalid secret name: ${secretName}. Must match /^[A-Z][A-Z0-9_]{1,127}$/.` };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (dryRun) {
|
|
52
|
+
return {
|
|
53
|
+
ok: true,
|
|
54
|
+
dryRun: true,
|
|
55
|
+
repo: normalizedRepo,
|
|
56
|
+
secretName,
|
|
57
|
+
instructions: [
|
|
58
|
+
`gh secret set ${secretName} --repo ${normalizedRepo}`,
|
|
59
|
+
`# Paste your SentinelLayer token when prompted`,
|
|
60
|
+
`gh secret list --repo ${normalizedRepo}`,
|
|
61
|
+
`# Verify ${secretName} appears in the list`,
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const secretSinkFile = String(process.env.SENTINELAYER_SECRET_SINK_FILE || "").trim();
|
|
67
|
+
if (secretSinkFile) {
|
|
68
|
+
try {
|
|
69
|
+
fs.appendFileSync(secretSinkFile, `${normalizedRepo}|${secretName}|${secretValue}\n`, "utf-8");
|
|
70
|
+
return { ok: true, repo: normalizedRepo, secretName, method: "sink-file" };
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return { ok: false, reason: `Failed to write SENTINELAYER_SECRET_SINK_FILE: ${error instanceof Error ? error.message : String(error)}` };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
ensureGhCliAvailable(ghCommand);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
return { ok: false, reason: error instanceof Error ? error.message : String(error) };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const result = spawnSync(ghCommand, ["secret", "set", secretName, "--repo", normalizedRepo], {
|
|
83
|
+
encoding: "utf-8",
|
|
84
|
+
input: `${secretValue}\n`,
|
|
85
|
+
});
|
|
86
|
+
if (result.status !== 0) {
|
|
87
|
+
return { ok: false, reason: String(result.stderr || result.stdout || "gh secret set failed").trim() };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const verifyResult = spawnSync(ghCommand, ["secret", "list", "--repo", normalizedRepo], {
|
|
91
|
+
encoding: "utf-8",
|
|
92
|
+
});
|
|
93
|
+
if (verifyResult.status !== 0) {
|
|
94
|
+
return { ok: false, reason: String(verifyResult.stderr || verifyResult.stdout || "gh secret list failed").trim() };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const listedSecrets = String(verifyResult.stdout || "");
|
|
98
|
+
const escapedSecretName = String(secretName || "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
99
|
+
const secretRegex = new RegExp(`(^|\\r?\\n)\\s*${escapedSecretName}(\\s|$)`, "m");
|
|
100
|
+
if (!secretRegex.test(listedSecrets)) {
|
|
101
|
+
return { ok: false, reason: `Secret '${secretName}' was not visible in gh secret list output after injection.` };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return { ok: true, repo: normalizedRepo, secretName, method: "gh-cli" };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export { detectRepoSlug };
|