codiedev 0.10.0-beta.3 → 0.10.0-beta.5
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 +7 -1
- package/assets/tui-brand-plugin.tsx +73 -0
- package/dist/backup/cache.js +1 -5
- package/dist/backup/match.js +0 -6
- package/dist/backup/run.js +3 -35
- package/dist/captureExclusions.js +0 -12
- package/dist/captureLog.js +0 -28
- package/dist/captureReadiness.js +0 -58
- package/dist/captureSignals.js +66 -3
- package/dist/cli.js +41 -18
- package/dist/codexHookTrust.js +61 -5
- package/dist/codexLimitScan.js +2 -109
- package/dist/codie.js +41 -56
- package/dist/codieBrandInstall.js +80 -0
- package/dist/codieLauncher.js +59 -59
- package/dist/codieRuntime.js +19 -23
- package/dist/codieRuntimeInstall.js +108 -23
- package/dist/codieStartup.js +0 -3
- package/dist/codieUsage.js +181 -0
- package/dist/commands/ask.js +0 -3
- package/dist/commands/capture.js +0 -2
- package/dist/commands/createTicket.js +0 -10
- package/dist/commands/doctor.js +41 -82
- package/dist/commands/inbox.js +0 -2
- package/dist/commands/library.js +0 -3
- package/dist/commands/pack.js +573 -0
- package/dist/commands/ping.js +0 -2
- package/dist/commands/pull.js +6 -10
- package/dist/commands/push.js +2 -12
- package/dist/commands/react.js +0 -2
- package/dist/commands/reverseTicket.js +0 -33
- package/dist/commands/search.js +0 -4
- package/dist/commands/send.js +0 -5
- package/dist/commands/share.js +0 -4
- package/dist/commands/shared.js +0 -35
- package/dist/commands/traces.js +280 -0
- package/dist/configDir.js +0 -10
- package/dist/connect.js +21 -77
- package/dist/connectFlow.js +0 -9
- package/dist/copilotHooks.js +395 -0
- package/dist/copilotInstallation.js +64 -0
- package/dist/cursorHooks.js +40 -17
- package/dist/cursorLifecycle.js +109 -0
- package/dist/detection.js +0 -30
- package/dist/harnessDirs.js +73 -0
- package/dist/hook.js +193 -316
- package/dist/inboxFormat.js +0 -24
- package/dist/launchContext.js +150 -0
- package/dist/launcher.js +140 -0
- package/dist/limitEvent.js +41 -35
- package/dist/limitEventReporter.js +1 -1
- package/dist/mcp.js +3 -77
- package/dist/nativeSteering.js +24 -0
- package/dist/packs/codie.js +182 -0
- package/dist/packs/harnesses.js +374 -0
- package/dist/packs/hookGate.js +256 -0
- package/dist/packs/install.js +285 -0
- package/dist/packs/manifest.js +126 -0
- package/dist/packs/paths.js +81 -0
- package/dist/packs/shim.js +214 -0
- package/dist/packs/store.js +155 -0
- package/dist/packs/sync.js +170 -0
- package/dist/prUrl.js +0 -5
- package/dist/repoResolver.js +0 -19
- package/dist/secret.js +0 -3
- package/dist/security.js +0 -20
- package/dist/securityDeepScan.js +1 -14
- package/dist/securityDoctor.js +0 -2
- package/dist/securityFeature.js +0 -1
- package/dist/securityInstall.js +6 -13
- package/dist/securityInventory.js +23 -13
- package/dist/securityPilot.js +0 -2
- package/dist/securityPolicy.js +0 -7
- package/dist/selfUpdate.js +331 -0
- package/dist/skillMarker.js +23 -0
- package/dist/subagents.js +135 -0
- package/dist/teamSkillContext.js +10 -0
- package/dist/transcriptModels.js +6 -8
- package/dist/upgradeNudge.js +0 -30
- package/dist/utils.js +286 -733
- package/dist/version.js +0 -10
- package/dist/versionCheck.js +0 -33
- package/package.json +8 -7
- package/dist/backup/cache.d.ts +0 -14
- package/dist/backup/match.d.ts +0 -2
- package/dist/backup/run.d.ts +0 -25
- package/dist/captureExclusions.d.ts +0 -30
- package/dist/captureLog.d.ts +0 -20
- package/dist/captureReadiness.d.ts +0 -65
- package/dist/captureSignals.d.ts +0 -19
- package/dist/cli.d.ts +0 -16
- package/dist/codexHookTrust.d.ts +0 -34
- package/dist/codexLimitScan.d.ts +0 -64
- package/dist/codie.d.ts +0 -2
- package/dist/codieLauncher.d.ts +0 -53
- package/dist/codieRuntime.d.ts +0 -29
- package/dist/codieRuntimeInstall.d.ts +0 -28
- package/dist/codieStartup.d.ts +0 -26
- package/dist/commands/ask.d.ts +0 -1
- package/dist/commands/capture.d.ts +0 -14
- package/dist/commands/createTicket.d.ts +0 -27
- package/dist/commands/delete.d.ts +0 -1
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/inbox.d.ts +0 -3
- package/dist/commands/library.d.ts +0 -2
- package/dist/commands/note.d.ts +0 -1
- package/dist/commands/ping.d.ts +0 -1
- package/dist/commands/promote.d.ts +0 -1
- package/dist/commands/pull.d.ts +0 -2
- package/dist/commands/push.d.ts +0 -33
- package/dist/commands/react.d.ts +0 -2
- package/dist/commands/reverseTicket.d.ts +0 -2
- package/dist/commands/search.d.ts +0 -2
- package/dist/commands/security.d.ts +0 -1
- package/dist/commands/send.d.ts +0 -2
- package/dist/commands/share.d.ts +0 -2
- package/dist/commands/shared.d.ts +0 -64
- package/dist/configDir.d.ts +0 -1
- package/dist/connect.d.ts +0 -1
- package/dist/connectFlow.d.ts +0 -13
- package/dist/cursorHooks.d.ts +0 -23
- package/dist/detection.d.ts +0 -30
- package/dist/hook.d.ts +0 -6
- package/dist/inboxFormat.d.ts +0 -38
- package/dist/limitEvent.d.ts +0 -16
- package/dist/limitEventReporter.d.ts +0 -21
- package/dist/mcp.d.ts +0 -12
- package/dist/prUrl.d.ts +0 -9
- package/dist/repoResolver.d.ts +0 -17
- package/dist/secret.d.ts +0 -1
- package/dist/security.d.ts +0 -102
- package/dist/securityDeepScan.d.ts +0 -41
- package/dist/securityDoctor.d.ts +0 -32
- package/dist/securityFeature.d.ts +0 -5
- package/dist/securityInstall.d.ts +0 -63
- package/dist/securityInventory.d.ts +0 -54
- package/dist/securityPilot.d.ts +0 -19
- package/dist/securityPolicy.d.ts +0 -33
- package/dist/securitySession.d.ts +0 -6
- package/dist/transcriptModels.d.ts +0 -18
- package/dist/upgradeNudge.d.ts +0 -25
- package/dist/utils.d.ts +0 -346
- package/dist/version.d.ts +0 -1
- package/dist/versionCheck.d.ts +0 -68
package/dist/securityDeepScan.js
CHANGED
|
@@ -39,9 +39,6 @@ const child_process_1 = require("child_process");
|
|
|
39
39
|
const fs = __importStar(require("fs"));
|
|
40
40
|
const os = __importStar(require("os"));
|
|
41
41
|
const path = __importStar(require("path"));
|
|
42
|
-
/** Adds component-addressable OSS scanner findings to the uploadable inventory.
|
|
43
|
-
* Workspace-level findings (for example OSV dependency results) stay in the
|
|
44
|
-
* deep-scan report because they do not identify one agent component. */
|
|
45
42
|
function mergeDeepScanFindings(report, deep) {
|
|
46
43
|
const byComponent = new Map();
|
|
47
44
|
for (const finding of deep.findings) {
|
|
@@ -102,8 +99,6 @@ function collectFindingObjects(value, scanner, componentKey) {
|
|
|
102
99
|
return;
|
|
103
100
|
const row = child;
|
|
104
101
|
const ruleId = row.rule_id ?? row.ruleId ?? row.id ?? row.code;
|
|
105
|
-
// Do not import scanner messages/descriptions: several engines include the
|
|
106
|
-
// matched source snippet there. Titles and rule names are bounded metadata.
|
|
107
102
|
const title = row.title ?? row.rule_name ?? row.ruleName ?? row.name ??
|
|
108
103
|
(ruleId !== undefined ? `Scanner finding ${String(ruleId)}` : undefined);
|
|
109
104
|
const severityValue = row.severity ?? row.level ?? row.risk;
|
|
@@ -145,7 +140,7 @@ function runJsonScanner(args) {
|
|
|
145
140
|
try {
|
|
146
141
|
parsed = JSON.parse(stdout.slice(start, end + 1));
|
|
147
142
|
}
|
|
148
|
-
catch {
|
|
143
|
+
catch { }
|
|
149
144
|
}
|
|
150
145
|
}
|
|
151
146
|
}
|
|
@@ -171,11 +166,6 @@ function pathsFor(report, kind, homeDir, workspace) {
|
|
|
171
166
|
.map((component) => ({ component, filePath: actualPath(component.source, homeDir, workspace) }))
|
|
172
167
|
.filter((item) => Boolean(item.filePath && fs.existsSync(item.filePath)));
|
|
173
168
|
}
|
|
174
|
-
/**
|
|
175
|
-
* Runs optional open-source scanners. No scanner is downloaded implicitly.
|
|
176
|
-
* MCP server connection is a separate opt-in because scanning a live stdio
|
|
177
|
-
* server starts third-party code; the normal deep scan remains static.
|
|
178
|
-
*/
|
|
179
169
|
function runDeepSecurityScan(report, options = {}) {
|
|
180
170
|
const homeDir = path.resolve(options.homeDir ?? os.homedir());
|
|
181
171
|
const workspace = path.resolve(options.workspace ?? process.cwd());
|
|
@@ -184,9 +174,6 @@ function runDeepSecurityScan(report, options = {}) {
|
|
|
184
174
|
const runs = [];
|
|
185
175
|
const skillPaths = pathsFor(report, "skill", homeDir, workspace);
|
|
186
176
|
for (const { component, filePath } of skillPaths) {
|
|
187
|
-
// Cisco's scanner is preferred when present; ATR is the lightweight
|
|
188
|
-
// fallback. The current ATR CLI does not expose its internal detection
|
|
189
|
-
// lanes, so only high/critical findings are imported for review.
|
|
190
177
|
const cisco = runJsonScanner({
|
|
191
178
|
scanner: "cisco-skill-scanner", command: "skill-scanner",
|
|
192
179
|
commandArgs: ["scan", filePath, "--format", "json"], componentKey: component.componentKey,
|
package/dist/securityDoctor.js
CHANGED
|
@@ -5,7 +5,6 @@ exports.securityDoctorChecks = securityDoctorChecks;
|
|
|
5
5
|
const securityInstall_1 = require("./securityInstall");
|
|
6
6
|
const securityPilot_1 = require("./securityPilot");
|
|
7
7
|
const securityPolicy_1 = require("./securityPolicy");
|
|
8
|
-
/** One security-health model shared by `doctor` and its legacy alias. */
|
|
9
8
|
function collectSecurityDoctorReport(companyId) {
|
|
10
9
|
const manifest = (0, securityInstall_1.readSecurityInstallManifest)();
|
|
11
10
|
const integrity = (0, securityInstall_1.verifySecurityInstallManifest)(manifest);
|
|
@@ -27,7 +26,6 @@ function collectSecurityDoctorReport(companyId) {
|
|
|
27
26
|
policySelfTest: { ok: pilot.ok, cases: pilot.cases.length },
|
|
28
27
|
};
|
|
29
28
|
}
|
|
30
|
-
/** Convert security health into the same compact rows used by core doctor. */
|
|
31
29
|
function securityDoctorChecks(report) {
|
|
32
30
|
const checks = [
|
|
33
31
|
{
|
package/dist/securityFeature.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isAgentSecurityEnabled = isAgentSecurityEnabled;
|
|
4
|
-
/** Security is opt-in per company. Missing/stale entitlement data is dormant. */
|
|
5
4
|
function isAgentSecurityEnabled(config) {
|
|
6
5
|
return config?.agentSecurityEnabled === true;
|
|
7
6
|
}
|
package/dist/securityInstall.js
CHANGED
|
@@ -47,6 +47,8 @@ const configDir_1 = require("./configDir");
|
|
|
47
47
|
const detection_1 = require("./detection");
|
|
48
48
|
const codexHookTrust_1 = require("./codexHookTrust");
|
|
49
49
|
const version_1 = require("./version");
|
|
50
|
+
const copilotInstallation_1 = require("./copilotInstallation");
|
|
51
|
+
const harnessDirs_1 = require("./harnessDirs");
|
|
50
52
|
const MANIFEST_FILE = "security-install.json";
|
|
51
53
|
function sha256File(filePath) {
|
|
52
54
|
return crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
|
|
@@ -55,11 +57,6 @@ function safeSnapshotName(index, filePath) {
|
|
|
55
57
|
const digest = crypto.createHash("sha256").update(filePath).digest("hex").slice(0, 12);
|
|
56
58
|
return `${String(index + 1).padStart(2, "0")}-${digest}-${path.basename(filePath)}`;
|
|
57
59
|
}
|
|
58
|
-
/**
|
|
59
|
-
* Capture the exact pre-update hook configuration. This function never removes
|
|
60
|
-
* or restores anything; it creates the evidence needed for an explicit,
|
|
61
|
-
* administrator-approved rollback later.
|
|
62
|
-
*/
|
|
63
60
|
function createSecurityInstallSnapshot(configPaths, stateDir = (0, configDir_1.codiedevStateDir)(), now = Date.now) {
|
|
64
61
|
const timestamp = now();
|
|
65
62
|
const id = `${timestamp}-${process.pid}`;
|
|
@@ -124,11 +121,6 @@ function verifySecurityInstallManifest(manifest) {
|
|
|
124
121
|
detail: `v${manifest.cliVersion}; rollback snapshot ${manifest.rollbackSnapshotId} available`,
|
|
125
122
|
};
|
|
126
123
|
}
|
|
127
|
-
/**
|
|
128
|
-
* Restore only files recorded in the selected install manifest. The snapshot
|
|
129
|
-
* location is validated before any write and each replacement is atomic, so a
|
|
130
|
-
* partial copy cannot leave a hook configuration truncated.
|
|
131
|
-
*/
|
|
132
124
|
function restoreSecurityInstallSnapshot(manifest) {
|
|
133
125
|
if (!manifest)
|
|
134
126
|
throw new Error("security install manifest is missing");
|
|
@@ -215,14 +207,15 @@ function inspectJsonSurface(surface, filePath, codexConfigPath) {
|
|
|
215
207
|
}
|
|
216
208
|
function inspectSecurityInstallation(paths = {}) {
|
|
217
209
|
const home = os.homedir();
|
|
218
|
-
const claude = paths.claudeSettingsPath ?? path.join(
|
|
219
|
-
const codex = paths.codexHooksPath ?? path.join(
|
|
210
|
+
const claude = paths.claudeSettingsPath ?? path.join((0, harnessDirs_1.claudeConfigDir)(), "settings.json");
|
|
211
|
+
const codex = paths.codexHooksPath ?? path.join((0, harnessDirs_1.codexHome)(), "hooks.json");
|
|
220
212
|
const cursor = paths.cursorHooksPath ?? path.join(home, ".cursor", "hooks.json");
|
|
221
|
-
const codie = paths.codiePluginPath ?? path.join(
|
|
213
|
+
const codie = paths.codiePluginPath ?? path.join((0, harnessDirs_1.openCodeConfigDir)(), "plugins", "codiedev.js");
|
|
222
214
|
const results = [
|
|
223
215
|
inspectJsonSurface("claude-code", claude),
|
|
224
216
|
inspectJsonSurface("codex", codex, paths.codexConfigPath),
|
|
225
217
|
inspectJsonSurface("cursor", cursor),
|
|
218
|
+
{ surface: "copilot", ...(0, copilotInstallation_1.inspectCopilotHooks)(paths.copilotHooksPath, true) },
|
|
226
219
|
];
|
|
227
220
|
if (!fs.existsSync(codie)) {
|
|
228
221
|
results.push({ surface: "codie-harness", status: "not-installed", detail: `${codie} not found` });
|
|
@@ -43,6 +43,8 @@ const fs = __importStar(require("fs"));
|
|
|
43
43
|
const http = __importStar(require("http"));
|
|
44
44
|
const https = __importStar(require("https"));
|
|
45
45
|
const os = __importStar(require("os"));
|
|
46
|
+
const copilotHooks_1 = require("./copilotHooks");
|
|
47
|
+
const harnessDirs_1 = require("./harnessDirs");
|
|
46
48
|
const path = __importStar(require("path"));
|
|
47
49
|
const child_process_1 = require("child_process");
|
|
48
50
|
const configDir_1 = require("./configDir");
|
|
@@ -89,8 +91,6 @@ function displayPath(filePath, homeDir, workspace) {
|
|
|
89
91
|
if (resolved.startsWith(`${resolvedHome}${path.sep}`)) {
|
|
90
92
|
return `~/${path.relative(resolvedHome, resolved)}`;
|
|
91
93
|
}
|
|
92
|
-
// Never upload arbitrary absolute paths. The basename plus a short digest is
|
|
93
|
-
// enough to distinguish two external locations without exposing usernames.
|
|
94
94
|
return `[external:${hash(resolved).slice(0, 10)}]/${path.basename(resolved)}`;
|
|
95
95
|
}
|
|
96
96
|
function fileScope(filePath, workspace) {
|
|
@@ -197,8 +197,6 @@ function jsoncToJson(text) {
|
|
|
197
197
|
}
|
|
198
198
|
output += char;
|
|
199
199
|
}
|
|
200
|
-
// JSONC permits trailing commas. Comments are already gone, so remove a
|
|
201
|
-
// comma only when the next non-whitespace token closes an array or object.
|
|
202
200
|
let withoutTrailingCommas = "";
|
|
203
201
|
inString = false;
|
|
204
202
|
escaped = false;
|
|
@@ -441,44 +439,56 @@ function securityInventoryDue(stateDir = (0, configDir_1.codiedevStateDir)(), ma
|
|
|
441
439
|
}
|
|
442
440
|
function buildSecurityInventory(options = {}) {
|
|
443
441
|
const homeDir = path.resolve(options.homeDir ?? os.homedir());
|
|
442
|
+
const copilotDir = options.homeDir ? path.join(homeDir, ".copilot") : (0, copilotHooks_1.copilotHome)();
|
|
443
|
+
const claudeDir = options.homeDir ? path.join(homeDir, ".claude") : (0, harnessDirs_1.claudeConfigDir)();
|
|
444
|
+
const claudeJson = options.homeDir ? path.join(homeDir, ".claude.json") : (0, harnessDirs_1.claudeUserConfigPath)();
|
|
445
|
+
const codexDir = options.homeDir ? path.join(homeDir, ".codex") : (0, harnessDirs_1.codexHome)();
|
|
446
|
+
const openCodeDir = options.homeDir ? path.join(homeDir, ".config", "opencode") : (0, harnessDirs_1.openCodeConfigDir)();
|
|
444
447
|
const workspace = path.resolve(options.workspace ?? process.cwd());
|
|
445
448
|
const stateDir = options.stateDir ?? (0, configDir_1.codiedevStateDir)();
|
|
446
449
|
const components = [];
|
|
447
450
|
const jsonConfigs = [
|
|
448
|
-
|
|
449
|
-
path.join(
|
|
450
|
-
path.join(homeDir, ".cursor", "mcp.json"), path.join(
|
|
451
|
-
path.join(
|
|
451
|
+
claudeJson, path.join(claudeDir, "settings.json"),
|
|
452
|
+
path.join(claudeDir, "settings.local.json"),
|
|
453
|
+
path.join(homeDir, ".cursor", "mcp.json"), path.join(openCodeDir, "opencode.json"),
|
|
454
|
+
path.join(openCodeDir, "opencode.jsonc"),
|
|
452
455
|
path.join(homeDir, ".config", "Code", "User", "mcp.json"),
|
|
453
456
|
path.join(homeDir, ".config", "Cursor", "User", "mcp.json"),
|
|
454
|
-
path.join(
|
|
457
|
+
path.join(codexDir, "hooks.json"),
|
|
458
|
+
path.join(homeDir, ".cursor", "hooks.json"),
|
|
459
|
+
...walkFiles(path.join(copilotDir, "hooks"), (_file, name) => name.endsWith(".json"), 1),
|
|
455
460
|
path.join(homeDir, "Library", "Application Support", "Code", "User", "mcp.json"),
|
|
456
461
|
path.join(homeDir, "Library", "Application Support", "Cursor", "User", "mcp.json"),
|
|
457
462
|
path.join(homeDir, "Library", "Application Support", "Claude", "claude_desktop_config.json"),
|
|
458
463
|
path.join(workspace, ".mcp.json"), path.join(workspace, ".cursor", "mcp.json"),
|
|
459
464
|
path.join(workspace, ".vscode", "mcp.json"),
|
|
460
465
|
path.join(workspace, ".codex", "hooks.json"),
|
|
466
|
+
path.join(workspace, ".cursor", "hooks.json"),
|
|
467
|
+
...walkFiles(path.join(workspace, ".github", "hooks"), (_file, name) => name.endsWith(".json"), 1),
|
|
461
468
|
path.join(workspace, ".claude", "settings.json"), path.join(workspace, ".claude", "settings.local.json"),
|
|
462
469
|
path.join(workspace, "opencode.json"), path.join(workspace, "opencode.jsonc"),
|
|
463
470
|
];
|
|
464
471
|
for (const filePath of jsonConfigs)
|
|
465
472
|
collectJsonConfig(filePath, homeDir, workspace, components);
|
|
466
|
-
for (const filePath of [path.join(
|
|
473
|
+
for (const filePath of [path.join(codexDir, "config.toml"), path.join(workspace, ".codex", "config.toml")]) {
|
|
467
474
|
collectCodexToml(filePath, homeDir, workspace, components);
|
|
468
475
|
}
|
|
469
476
|
collectSkills([
|
|
470
|
-
path.join(
|
|
477
|
+
path.join(claudeDir, "skills"), path.join(codexDir, "skills"),
|
|
471
478
|
path.join(homeDir, ".agents", "skills"), path.join(homeDir, ".cursor", "skills"),
|
|
479
|
+
path.join(copilotDir, "skills"), path.join(workspace, ".github", "skills"),
|
|
472
480
|
path.join(workspace, ".claude", "skills"), path.join(workspace, ".codex", "skills"),
|
|
473
481
|
path.join(workspace, ".agents", "skills"), path.join(workspace, ".cursor", "skills"),
|
|
474
482
|
], homeDir, workspace, components);
|
|
475
483
|
collectExtensions([
|
|
476
484
|
path.join(homeDir, ".vscode", "extensions"), path.join(homeDir, ".cursor", "extensions"),
|
|
477
485
|
], homeDir, workspace, components);
|
|
478
|
-
const pluginDirs = [path.join(
|
|
486
|
+
const pluginDirs = [path.join(openCodeDir, "plugins"), path.join(workspace, ".opencode", "plugins")];
|
|
479
487
|
collectLooseFiles(pluginDirs.flatMap((dir) => walkFiles(dir, (_file, name) => /\.(?:js|mjs|cjs|ts)$/.test(name), 2)), "plugin", homeDir, workspace, components);
|
|
480
488
|
collectLooseFiles([
|
|
481
|
-
path.join(
|
|
489
|
+
path.join(claudeDir, "CLAUDE.md"), path.join(codexDir, "AGENTS.md"),
|
|
490
|
+
path.join(copilotDir, "copilot-instructions.md"), path.join(workspace, ".github", "copilot-instructions.md"),
|
|
491
|
+
...walkFiles(path.join(homeDir, ".cursor", "rules"), (_file, name) => /\.(?:md|mdc)$/.test(name), 3),
|
|
482
492
|
path.join(workspace, "CLAUDE.md"), path.join(workspace, "AGENTS.md"),
|
|
483
493
|
...walkFiles(path.join(workspace, ".cursor", "rules"), (_file, name) => /\.(?:md|mdc)$/.test(name), 3),
|
|
484
494
|
], "instruction", homeDir, workspace, components);
|
package/dist/securityPilot.js
CHANGED
|
@@ -26,8 +26,6 @@ function constrainedPolicy(now) {
|
|
|
26
26
|
fetchedAt: now,
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
-
/** Safe, side-effect-free policy validation. No command is executed and none
|
|
30
|
-
* of the synthetic values are real credentials. */
|
|
31
29
|
function runSyntheticSecurityPilot(cwd = process.cwd(), now = Date.now) {
|
|
32
30
|
const cases = [];
|
|
33
31
|
const policy = constrainedPolicy(now());
|
package/dist/securityPolicy.js
CHANGED
|
@@ -55,13 +55,6 @@ function policyFile(companyId) {
|
|
|
55
55
|
const scope = companyId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128);
|
|
56
56
|
return `security-policy.${scope}.json`;
|
|
57
57
|
}
|
|
58
|
-
/**
|
|
59
|
-
* Vendor policy roots are compiled into the endpoint binary. This prevents a
|
|
60
|
-
* compromised control-plane response from introducing the key that verifies
|
|
61
|
-
* that same response. Additional customer-managed roots may still be supplied
|
|
62
|
-
* through CODIEDEV_SECURITY_POLICY_PUBLIC_KEYS, but they cannot replace the
|
|
63
|
-
* Codiedev production root with the same key id.
|
|
64
|
-
*/
|
|
65
58
|
exports.BUILT_IN_POLICY_KEYS = {
|
|
66
59
|
"codiedev-prod-2026-01": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA0H+UISjTn4zhd6Pk9YmrMBqnJEJmv9fXoavXorlV2cU=\n-----END PUBLIC KEY-----\n",
|
|
67
60
|
};
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.planSelfUpdate = planSelfUpdate;
|
|
37
|
+
exports.isSelfUpdateDue = isSelfUpdateDue;
|
|
38
|
+
exports.readSelfUpdateState = readSelfUpdateState;
|
|
39
|
+
exports.maybeSpawnSelfUpdate = maybeSpawnSelfUpdate;
|
|
40
|
+
exports.findInstalledHookScript = findInstalledHookScript;
|
|
41
|
+
exports.runSelfUpdate = runSelfUpdate;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const child_process_1 = require("child_process");
|
|
45
|
+
const version_1 = require("./version");
|
|
46
|
+
const versionCheck_1 = require("./versionCheck");
|
|
47
|
+
const configDir_1 = require("./configDir");
|
|
48
|
+
const captureLog_1 = require("./captureLog");
|
|
49
|
+
const launcher_1 = require("./launcher");
|
|
50
|
+
const PKG = "codiedev";
|
|
51
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
52
|
+
const LOCK_STALE_MS = 10 * 60 * 1000;
|
|
53
|
+
const INSTALL_TIMEOUT_MS = 5 * 60 * 1000;
|
|
54
|
+
const FETCH_TIMEOUT_MS = 5_000;
|
|
55
|
+
function planSelfUpdate(deps) {
|
|
56
|
+
const { env } = deps;
|
|
57
|
+
if (env.CODIEDEV_NO_UPDATE_CHECK || env.CODIEDEV_NO_AUTO_UPDATE) {
|
|
58
|
+
return { kind: "skip", reason: "disabled" };
|
|
59
|
+
}
|
|
60
|
+
if (env.CI || env.CONTINUOUS_INTEGRATION || env.GITHUB_ACTIONS || env.BUILD_NUMBER) {
|
|
61
|
+
return { kind: "skip", reason: "ci" };
|
|
62
|
+
}
|
|
63
|
+
if (deps.isContainer)
|
|
64
|
+
return { kind: "skip", reason: "container" };
|
|
65
|
+
const p = deps.hookScriptReal.replace(/\\/g, "/");
|
|
66
|
+
if (/\/(?:_npx|\.npm\/_npx)\//.test(p))
|
|
67
|
+
return { kind: "skip", reason: "npx" };
|
|
68
|
+
const pkgDir = path.dirname(path.dirname(deps.hookScriptReal));
|
|
69
|
+
if (!deps.isWritable(pkgDir))
|
|
70
|
+
return { kind: "skip", reason: "readonly" };
|
|
71
|
+
if (/\/\.pnpm\/|\/pnpm\/global\/|\/global\/v\d+\/[^/]+\/node_modules\/codiedev\/|\/store\/v\d+\/links\//.test(p)) {
|
|
72
|
+
return deps.viaLauncher ? { kind: "pnpm" } : { kind: "skip", reason: "pnpm-direct" };
|
|
73
|
+
}
|
|
74
|
+
if (/\/install\/global\/node_modules\/codiedev\/dist\/hook\.js$/.test(p))
|
|
75
|
+
return { kind: "bun" };
|
|
76
|
+
const unix = p.match(/^(.*)\/lib\/node_modules\/codiedev\/dist\/hook\.js$/);
|
|
77
|
+
if (unix && deps.platform !== "win32")
|
|
78
|
+
return { kind: "npm", prefix: unix[1] };
|
|
79
|
+
const win = p.match(/^(.*)\/node_modules\/codiedev\/dist\/hook\.js$/);
|
|
80
|
+
if (win && deps.platform === "win32")
|
|
81
|
+
return { kind: "npm", prefix: win[1] };
|
|
82
|
+
return { kind: "skip", reason: "unmanaged" };
|
|
83
|
+
}
|
|
84
|
+
function isSelfUpdateDue(state, nowMs) {
|
|
85
|
+
return !state || nowMs - state.lastAttemptAt > DAY_MS;
|
|
86
|
+
}
|
|
87
|
+
function statePath() {
|
|
88
|
+
return path.join((0, configDir_1.codiedevStateDir)(), ".self-update.json");
|
|
89
|
+
}
|
|
90
|
+
function lockPath() {
|
|
91
|
+
return path.join((0, configDir_1.codiedevStateDir)(), ".self-update.lock");
|
|
92
|
+
}
|
|
93
|
+
function readSelfUpdateState() {
|
|
94
|
+
try {
|
|
95
|
+
const parsed = JSON.parse(fs.readFileSync(statePath(), "utf8"));
|
|
96
|
+
return typeof parsed.lastAttemptAt === "number" ? parsed : null;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function writeState(state) {
|
|
103
|
+
try {
|
|
104
|
+
fs.mkdirSync((0, configDir_1.codiedevStateDir)(), { recursive: true });
|
|
105
|
+
fs.writeFileSync(statePath(), JSON.stringify(state), "utf8");
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function maybeSpawnSelfUpdate(hookEntry) {
|
|
113
|
+
try {
|
|
114
|
+
if (!hookEntry || process.env.CODIEDEV_NO_AUTO_UPDATE || process.env.CODIEDEV_NO_UPDATE_CHECK)
|
|
115
|
+
return;
|
|
116
|
+
const now = Date.now();
|
|
117
|
+
if (!isSelfUpdateDue(readSelfUpdateState(), now))
|
|
118
|
+
return;
|
|
119
|
+
if (!writeState({ lastAttemptAt: now, lastResult: "spawned" }))
|
|
120
|
+
return;
|
|
121
|
+
const child = (0, child_process_1.spawn)(process.execPath, [hookEntry, "self-update"], {
|
|
122
|
+
detached: true,
|
|
123
|
+
stdio: "ignore",
|
|
124
|
+
windowsHide: true,
|
|
125
|
+
});
|
|
126
|
+
child.unref();
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function acquireLock() {
|
|
132
|
+
const lock = lockPath();
|
|
133
|
+
try {
|
|
134
|
+
fs.mkdirSync(lock);
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
try {
|
|
139
|
+
if (Date.now() - fs.statSync(lock).mtimeMs > LOCK_STALE_MS) {
|
|
140
|
+
fs.rmSync(lock, { recursive: true, force: true });
|
|
141
|
+
fs.mkdirSync(lock);
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function detectContainer(env) {
|
|
151
|
+
if (env.KUBERNETES_SERVICE_HOST)
|
|
152
|
+
return true;
|
|
153
|
+
if (fs.existsSync("/.dockerenv") || fs.existsSync("/run/.containerenv"))
|
|
154
|
+
return true;
|
|
155
|
+
try {
|
|
156
|
+
return /docker|containerd|kubepods|lxc/.test(fs.readFileSync("/proc/1/cgroup", "utf8"));
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function registryBase(env) {
|
|
163
|
+
const configured = env.npm_config_registry || env.NPM_CONFIG_REGISTRY;
|
|
164
|
+
return (configured || "https://registry.npmjs.org").replace(/\/+$/, "");
|
|
165
|
+
}
|
|
166
|
+
async function fetchLatest(env) {
|
|
167
|
+
const controller = new AbortController();
|
|
168
|
+
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
169
|
+
try {
|
|
170
|
+
const res = await fetch(`${registryBase(env)}/${PKG}/latest`, {
|
|
171
|
+
headers: { Accept: "application/json" },
|
|
172
|
+
signal: controller.signal,
|
|
173
|
+
});
|
|
174
|
+
if (!res.ok)
|
|
175
|
+
return null;
|
|
176
|
+
const json = (await res.json());
|
|
177
|
+
return typeof json.version === "string" ? json.version : null;
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
finally {
|
|
183
|
+
clearTimeout(timer);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function installCommand(plan, version, env) {
|
|
187
|
+
const spec = `${PKG}@${version}`;
|
|
188
|
+
const configured = env.npm_config_registry || env.NPM_CONFIG_REGISTRY;
|
|
189
|
+
const registry = configured ? ["--registry", registryBase(env)] : [];
|
|
190
|
+
switch (plan.kind) {
|
|
191
|
+
case "npm": {
|
|
192
|
+
const args = ["i", "-g", "--prefix", plan.prefix, "--no-fund", "--no-audit", ...registry, spec];
|
|
193
|
+
const execDir = path.dirname(process.execPath);
|
|
194
|
+
const npmCli = [
|
|
195
|
+
path.join(execDir, "node_modules", "npm", "bin", "npm-cli.js"),
|
|
196
|
+
path.join(execDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
|
|
197
|
+
].find((p) => fs.existsSync(p));
|
|
198
|
+
if (npmCli)
|
|
199
|
+
return { cmd: process.execPath, args: [npmCli, ...args] };
|
|
200
|
+
return { cmd: process.platform === "win32" ? "npm.cmd" : "npm", args, shell: process.platform === "win32" };
|
|
201
|
+
}
|
|
202
|
+
case "pnpm":
|
|
203
|
+
return { cmd: "pnpm", args: ["add", "-g", ...registry, spec], shell: process.platform === "win32" };
|
|
204
|
+
case "bun":
|
|
205
|
+
return { cmd: "bun", args: ["add", "-g", ...registry, spec] };
|
|
206
|
+
default:
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
function readVersionAt(hookScript) {
|
|
211
|
+
try {
|
|
212
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(path.dirname(path.dirname(hookScript)), "package.json"), "utf8"));
|
|
213
|
+
return typeof pkg.version === "string" ? pkg.version : null;
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
function findInstalledHookScript(plan, hookEntry, version, pnpmRoot = pnpmGlobalRoot) {
|
|
220
|
+
if (plan.kind !== "pnpm")
|
|
221
|
+
return readVersionAt(hookEntry) === version ? hookEntry : null;
|
|
222
|
+
const root = pnpmRoot();
|
|
223
|
+
if (!root)
|
|
224
|
+
return null;
|
|
225
|
+
const candidates = [path.join(root, PKG, "dist", "hook.js")];
|
|
226
|
+
try {
|
|
227
|
+
for (const entry of fs.readdirSync(root)) {
|
|
228
|
+
candidates.push(path.join(root, entry, "node_modules", PKG, "dist", "hook.js"));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
}
|
|
233
|
+
for (const candidate of candidates) {
|
|
234
|
+
if (readVersionAt(candidate) !== version)
|
|
235
|
+
continue;
|
|
236
|
+
try {
|
|
237
|
+
return fs.realpathSync(candidate);
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
function pnpmGlobalRoot() {
|
|
245
|
+
const root = (0, child_process_1.spawnSync)("pnpm", ["root", "-g"], {
|
|
246
|
+
encoding: "utf8",
|
|
247
|
+
timeout: 30_000,
|
|
248
|
+
shell: process.platform === "win32",
|
|
249
|
+
windowsHide: true,
|
|
250
|
+
});
|
|
251
|
+
const dir = root.status === 0 ? root.stdout.trim() : "";
|
|
252
|
+
return dir || null;
|
|
253
|
+
}
|
|
254
|
+
async function runSelfUpdate(hookEntry) {
|
|
255
|
+
const env = process.env;
|
|
256
|
+
const now = Date.now();
|
|
257
|
+
const finish = (lastResult, extra = {}) => {
|
|
258
|
+
const state = { lastAttemptAt: now, lastResult, fromVersion: version_1.CLI_VERSION, ...extra };
|
|
259
|
+
writeState(state);
|
|
260
|
+
(0, captureLog_1.appendCaptureLog)({
|
|
261
|
+
stage: "self-update",
|
|
262
|
+
sessionId: undefined,
|
|
263
|
+
outcome: lastResult.startsWith("error") ? "ERROR" : "ok",
|
|
264
|
+
detail: `result=${lastResult} from=${version_1.CLI_VERSION} to=${extra.toVersion ?? "-"} elapsedMs=${Date.now() - now}`,
|
|
265
|
+
});
|
|
266
|
+
return state;
|
|
267
|
+
};
|
|
268
|
+
let hookScriptReal;
|
|
269
|
+
try {
|
|
270
|
+
hookScriptReal = fs.realpathSync(hookEntry);
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
return finish("skip:unresolved");
|
|
274
|
+
}
|
|
275
|
+
const plan = planSelfUpdate({
|
|
276
|
+
hookScriptReal,
|
|
277
|
+
env,
|
|
278
|
+
platform: process.platform,
|
|
279
|
+
isContainer: detectContainer(env),
|
|
280
|
+
viaLauncher: Boolean(env.CODIEDEV_VIA_LAUNCHER),
|
|
281
|
+
isWritable: (dir) => {
|
|
282
|
+
try {
|
|
283
|
+
fs.accessSync(dir, fs.constants.W_OK);
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
if (plan.kind === "skip")
|
|
292
|
+
return finish(`skip:${plan.reason}`);
|
|
293
|
+
if (!acquireLock()) {
|
|
294
|
+
(0, captureLog_1.appendCaptureLog)({ stage: "self-update", sessionId: undefined, outcome: "ok", detail: "result=skip:locked" });
|
|
295
|
+
return { lastAttemptAt: now, lastResult: "skip:locked" };
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
const latest = await fetchLatest(env);
|
|
299
|
+
if (!latest)
|
|
300
|
+
return finish("error:registry");
|
|
301
|
+
if ((0, versionCheck_1.compareSemver)(version_1.CLI_VERSION, latest) !== -1)
|
|
302
|
+
return finish("current", { toVersion: latest });
|
|
303
|
+
const install = installCommand(plan, latest, env);
|
|
304
|
+
if (!install)
|
|
305
|
+
return finish("skip:no-installer");
|
|
306
|
+
const result = (0, child_process_1.spawnSync)(install.cmd, install.args, {
|
|
307
|
+
stdio: "ignore",
|
|
308
|
+
timeout: INSTALL_TIMEOUT_MS,
|
|
309
|
+
env: { ...env, CODIEDEV_NO_AUTO_UPDATE: "1" },
|
|
310
|
+
shell: install.shell ?? false,
|
|
311
|
+
windowsHide: true,
|
|
312
|
+
});
|
|
313
|
+
if (result.error || result.status !== 0) {
|
|
314
|
+
return finish(`error:install-exit-${result.status ?? "spawn"}`, { toVersion: latest });
|
|
315
|
+
}
|
|
316
|
+
const installed = findInstalledHookScript(plan, hookScriptReal, latest);
|
|
317
|
+
if (!installed) {
|
|
318
|
+
return finish("error:not-found-after-install", { toVersion: latest });
|
|
319
|
+
}
|
|
320
|
+
if (!(0, launcher_1.recordCurrentInstall)(installed))
|
|
321
|
+
return finish("error:record", { toVersion: latest });
|
|
322
|
+
return finish("updated", { toVersion: latest });
|
|
323
|
+
}
|
|
324
|
+
finally {
|
|
325
|
+
try {
|
|
326
|
+
fs.rmSync(lockPath(), { recursive: true, force: true });
|
|
327
|
+
}
|
|
328
|
+
catch {
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.looksLikeSkill = looksLikeSkill;
|
|
4
|
+
exports.stripSkillMarker = stripSkillMarker;
|
|
5
|
+
exports.stampSkillMarker = stampSkillMarker;
|
|
6
|
+
const ID = /^[a-z0-9]{16,64}$/i;
|
|
7
|
+
const LINE = /^[ \t]*<!--\s*codiedev:artifact=[a-z0-9]+\s*-->[ \t]*(?:\r?\n|$)/gim;
|
|
8
|
+
function looksLikeSkill(markdown) {
|
|
9
|
+
const fm = markdown.match(/^?---\r?\n([\s\S]*?)\r?\n---/);
|
|
10
|
+
if (!fm)
|
|
11
|
+
return false;
|
|
12
|
+
return /^name\s*:/im.test(fm[1]) && /^description\s*:/im.test(fm[1]);
|
|
13
|
+
}
|
|
14
|
+
function stripSkillMarker(markdown) {
|
|
15
|
+
return markdown.replace(LINE, "");
|
|
16
|
+
}
|
|
17
|
+
function stampSkillMarker(markdown, artifactId) {
|
|
18
|
+
if (!artifactId || !ID.test(artifactId))
|
|
19
|
+
return markdown;
|
|
20
|
+
const body = stripSkillMarker(markdown);
|
|
21
|
+
const sep = body.endsWith("\n") ? "" : "\n";
|
|
22
|
+
return `${body}${sep}<!-- codiedev:artifact=${artifactId} -->\n`;
|
|
23
|
+
}
|