log-llm-config 1.3.70 → 1.3.74

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.
@@ -8,12 +8,14 @@
8
8
  */
9
9
  import { applyAutofixViolations, normalizeAgentToken, pruneSatisfiedOneTimeRemediations, runLocalRemediationComplianceCheck, } from './log_config_files/runtime/compliance_check.js';
10
10
  import { existsSync, readFileSync, statSync } from 'node:fs';
11
- import { getRemediationInstructionsPath } from './log_config_files/runtime/management_storage.js';
11
+ import { getRemediationInstructionsPath, readRemediationInstructionsFile } from './log_config_files/runtime/management_storage.js';
12
12
  import { hookLogSessionBanner, hookRunLog, logRemediationApplyFailure } from './log_config_files/runtime/hook_logger.js';
13
13
  import { isThisCliModule } from './cli_invocation_match.js';
14
14
  import { ensureAuthentication } from './log_config_files/auth/auth_flow.js';
15
15
  import { sendConfigFile } from './log_config_files/sender/batch_sender.js';
16
16
  import { tryResolveHardwareUuid } from './log_config_files/runtime/hardware_uuid.js';
17
+ import { syncRemediations } from './log_config_files/runtime/remediation_sync.js';
18
+ import { loadEndpointBase } from './log_config_files/sender/endpoint_config.js';
17
19
  const MANIFEST_STALE_MS = 7 * 24 * 60 * 60 * 1000;
18
20
  function parseIde() {
19
21
  const eq = process.argv.find((a) => a.startsWith('--ide='));
@@ -90,6 +92,19 @@ function autofixDialogLine(v) {
90
92
  const short = d.length > 160 ? `${d.slice(0, 157)}…` : d;
91
93
  return `• [${v.finding_formatted_id}] ${short}`;
92
94
  }
95
+ /** Cursor restart dialog after enforced/preventive remediation is applied locally. */
96
+ export function formatCursorRestartAutofixDialog(appliedViolations) {
97
+ const policyNames = [
98
+ ...new Set(appliedViolations
99
+ .map((v) => v.policy_name?.trim() || v.finding_title?.trim() || '')
100
+ .filter(Boolean)),
101
+ ];
102
+ const policyLabel = policyNames.length > 0 ? policyNames.join('\n\n') : 'Agent security policy';
103
+ return ('Optimus Labs enforced a preventive agent security policy as determined by your security team:\n\n' +
104
+ `${policyLabel}\n\n` +
105
+ 'Cursor will now restart to apply this policy, and your context will be retained.\n\n' +
106
+ 'Click OK to continue');
107
+ }
93
108
  /**
94
109
  * Upload a secondary compliance file to the backend so the server can resolve the finding.
95
110
  * Fire-and-forget: upload runs in background; any failure is logged but does not block the gate.
@@ -135,6 +150,24 @@ export async function runCompliancePromptGate() {
135
150
  const ide = parseIde();
136
151
  const agent = parseAgent(ide);
137
152
  hookLogSessionBanner('compliance_prompt_gate (before submit)');
153
+ // Sync before checking so server-side changes (enforce/unenforce) propagate on every prompt
154
+ // without waiting for the background runner. Race against a 3 s timeout so a slow or
155
+ // unavailable server never delays the gate significantly.
156
+ const hw = tryResolveHardwareUuid();
157
+ if (hw) {
158
+ const { remediations } = readRemediationInstructionsFile();
159
+ if (Array.isArray(remediations) && remediations.length > 0) {
160
+ try {
161
+ await Promise.race([
162
+ syncRemediations(loadEndpointBase(), hw),
163
+ new Promise((resolve) => setTimeout(resolve, 3000)),
164
+ ]);
165
+ }
166
+ catch {
167
+ // Network or auth failure — fall back to local file state.
168
+ }
169
+ }
170
+ }
138
171
  const status = runLocalRemediationComplianceCheck(agent);
139
172
  // Secondary-satisfied: primary checks failed but settings.json (or equiv) has the fix.
140
173
  // Upload those files fire-and-forget so the backend can resolve the finding immediately.
@@ -189,9 +222,11 @@ export async function runCompliancePromptGate() {
189
222
  }
190
223
  if (deferredSqlitePending || recheckOk || claudeRecheckStaleAfterImmediateApply) {
191
224
  const violationLabel = fixed === 1 ? 'policy violation' : 'policy violations';
192
- const autofixMessage = `Optimus Labs auto-fixed ${fixed} ${violationLabel}:\n\n${appliedViolations
193
- .map((v) => autofixDialogLine(v))
194
- .join('\n')}`;
225
+ const autofixMessage = ide === 'cursor' && restartCommands.length > 0
226
+ ? formatCursorRestartAutofixDialog(appliedViolations)
227
+ : `Optimus Labs auto-fixed ${fixed} ${violationLabel}:\n\n${appliedViolations
228
+ .map((v) => autofixDialogLine(v))
229
+ .join('\n')}`;
195
230
  const payload = { __optimus_autofix: true, autofix_message: autofixMessage };
196
231
  if (restartCommands.length > 0)
197
232
  payload.restart_commands = restartCommands;
@@ -325,6 +325,7 @@ export function runLocalRemediationComplianceCheck(agent = 'cursor') {
325
325
  description: check.description,
326
326
  finding_title: entry.finding_title,
327
327
  finding_description: entry.finding_description,
328
+ policy_name: entry.policy_name,
328
329
  severity: compliance.severity,
329
330
  autofix_allowed: compliance.autofix_allowed,
330
331
  config_file_path: entry.config_file_path,
@@ -347,6 +348,7 @@ export function runLocalRemediationComplianceCheck(agent = 'cursor') {
347
348
  description: check.description,
348
349
  finding_title: entry.finding_title,
349
350
  finding_description: entry.finding_description,
351
+ policy_name: entry.policy_name,
350
352
  severity: compliance.severity,
351
353
  autofix_allowed: compliance.autofix_allowed,
352
354
  config_file_path: entry.config_file_path,
@@ -371,6 +373,7 @@ export function runLocalRemediationComplianceCheck(agent = 'cursor') {
371
373
  description: check.description,
372
374
  finding_title: entry.finding_title,
373
375
  finding_description: entry.finding_description,
376
+ policy_name: entry.policy_name,
374
377
  severity: compliance.severity,
375
378
  autofix_allowed: compliance.autofix_allowed,
376
379
  config_file_path: entry.config_file_path,
@@ -394,7 +394,7 @@ function assertSafeSqliteIdentifiersForItemTable(table, keyColumn, valueColumn)
394
394
  const TRUSTED_CURSOR_SQLITE_DEFERRED_RESTART_COMMAND = 'REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) && export REPO_ROOT && ' +
395
395
  'CURSOR_PROJECT="${CURSOR_PROJECT_DIR:-$REPO_ROOT}" && export CURSOR_PROJECT && ' +
396
396
  'OPTIMUS_DEFERRED_LOG="${HOME}/opt-ai-sec/management/deferred_vscdb_restart.log" && mkdir -p "$(dirname "$OPTIMUS_DEFERRED_LOG")" && export OPTIMUS_DEFERRED_LOG && ' +
397
- "nohup bash -c 'exec >>\"\$OPTIMUS_DEFERRED_LOG\" 2>&1; echo deferred_restart:begin ts=\$(date -u +%Y-%m-%dT%H:%M:%SZ) REPO_ROOT=\"\$REPO_ROOT\" CURSOR_PROJECT=\"\$CURSOR_PROJECT\"; sleep 2; STATIC_DEV_ENV=\"\$HOME/opt-ai-sec/management/optimus_dev.env\"; ENV_LABEL=\"\"; if [ -f \"\$STATIC_DEV_ENV\" ]; then ENV_LABEL=\$(grep -E \"^(environment|ENVIRONMENT|OPTIMUS_ENVIRONMENT)=\" \"\$STATIC_DEV_ENV\" 2>/dev/null | head -1 | cut -d\"=\" -f2- | tr \"[:upper:]\" \"[:lower:]\" | xargs); fi; if [ -z \"\$ENV_LABEL\" ] && [ -n \"\${OPTIMUS_ENVIRONMENT:-}\" ]; then ENV_LABEL=\$(printf \"%s\" \"\$OPTIMUS_ENVIRONMENT\" | tr \"[:upper:]\" \"[:lower:]\" | xargs); fi; [ -z \"\$ENV_LABEL\" ] && ENV_LABEL=\"production\"; NPX_BASE=\"\"; if [ -f \"\$STATIC_DEV_ENV\" ]; then _nb=\$(grep -E \"^npx=\" \"\$STATIC_DEV_ENV\" 2>/dev/null | head -1 | cut -d\"=\" -f2- | xargs); [ -n \"\$_nb\" ] && [ -d \"\$_nb\" ] && NPX_BASE=\"\$_nb\"; fi; p=\"\${npm_config_prefix:-\${NPM_CONFIG_PREFIX:-}}\"; gp=\"\${npm_config_global_prefix:-}\"; gc=\"\${npm_config_globalconfig:-}\"; if [[ \"\$p\" == *\"/Applications/Cursor.app/\"* ]] || [[ \"\$gp\" == *\"/Applications/Cursor.app/\"* ]] || [[ \"\$gc\" == *\"/Applications/Cursor.app/\"* ]]; then unset npm_config_prefix NPM_CONFIG_PREFIX npm_config_global_prefix npm_config_globalconfig npm_node_execpath 2>/dev/null; fi; APPLY_EC=0; if [ -f \"\$REPO_ROOT/dev_npx_packages/log-llm-config/dist/apply_deferred_vscdb.js\" ]; then echo deferred_restart:apply_via_dev_npx_packages; node \"\$REPO_ROOT/dev_npx_packages/log-llm-config/dist/apply_deferred_vscdb.js\"; APPLY_EC=\$?; elif [ \"\$ENV_LABEL\" = \"development\" ] && [ -n \"\$NPX_BASE\" ] && [ -f \"\$NPX_BASE/log-llm-config/dist/apply_deferred_vscdb.js\" ]; then echo deferred_restart:apply_via_optimus_npx_base; node \"\$NPX_BASE/log-llm-config/dist/apply_deferred_vscdb.js\"; APPLY_EC=\$?; elif command -v npx >/dev/null 2>&1; then echo deferred_restart:apply_via_npx env=\"\$ENV_LABEL\"; cd \"\$REPO_ROOT\" || true; if [ \"\$ENV_LABEL\" = \"staging\" ]; then npx --yes --package=log-llm-config-staging@latest apply-deferred-vscdb-staging; APPLY_EC=\$?; else npx --yes --package=log-llm-config@latest apply-deferred-vscdb; APPLY_EC=\$?; fi; else echo deferred_restart:no_npx; APPLY_EC=127; fi; echo deferred_restart:apply_exit=\$APPLY_EC; if [ \$APPLY_EC -ne 0 ]; then echo deferred_restart:APPLY_FAILED_see_messages_above; fi; echo deferred_restart:open_cursor; open -a Cursor \"\$CURSOR_PROJECT\"; echo deferred_restart:open_exit=\$?; echo deferred_restart:end ts=\$(date -u +%Y-%m-%dT%H:%M:%SZ)' >/dev/null 2>&1 & killall -9 Cursor";
397
+ "nohup bash -c 'exec >>\"\$OPTIMUS_DEFERRED_LOG\" 2>&1; echo deferred_restart:begin ts=\$(date -u +%Y-%m-%dT%H:%M:%SZ) REPO_ROOT=\"\$REPO_ROOT\" CURSOR_PROJECT=\"\$CURSOR_PROJECT\"; sleep 2; STATIC_DEV_ENV=\"\$HOME/opt-ai-sec/management/optimus_dev.env\"; ENV_LABEL=\"\"; if [ -f \"\$STATIC_DEV_ENV\" ]; then ENV_LABEL=\$(grep -E \"^(environment|ENVIRONMENT|OPTIMUS_ENVIRONMENT)=\" \"\$STATIC_DEV_ENV\" 2>/dev/null | head -1 | cut -d\"=\" -f2- | tr \"[:upper:]\" \"[:lower:]\" | xargs); fi; if [ -z \"\$ENV_LABEL\" ] && [ -n \"\${OPTIMUS_ENVIRONMENT:-}\" ]; then ENV_LABEL=\$(printf \"%s\" \"\$OPTIMUS_ENVIRONMENT\" | tr \"[:upper:]\" \"[:lower:]\" | xargs); fi; [ -z \"\$ENV_LABEL\" ] && ENV_LABEL=\"production\"; NPX_BASE=\"\"; if [ -f \"\$STATIC_DEV_ENV\" ]; then _nb=\$(grep -E \"^npx=\" \"\$STATIC_DEV_ENV\" 2>/dev/null | head -1 | cut -d\"=\" -f2- | xargs); [ -n \"\$_nb\" ] && [ -d \"\$_nb\" ] && NPX_BASE=\"\$_nb\"; fi; p=\"\${npm_config_prefix:-\${NPM_CONFIG_PREFIX:-}}\"; gp=\"\${npm_config_global_prefix:-}\"; gc=\"\${npm_config_globalconfig:-}\"; if [[ \"\$p\" == *\"/Applications/Cursor.app/\"* ]] || [[ \"\$gp\" == *\"/Applications/Cursor.app/\"* ]] || [[ \"\$gc\" == *\"/Applications/Cursor.app/\"* ]]; then unset npm_config_prefix NPM_CONFIG_PREFIX npm_config_global_prefix npm_config_globalconfig npm_node_execpath 2>/dev/null; fi; APPLY_EC=0; if [ -f \"\$REPO_ROOT/dev_npx_packages/log-llm-config/dist/apply_deferred_vscdb.js\" ]; then echo deferred_restart:apply_via_dev_npx_packages; node \"\$REPO_ROOT/dev_npx_packages/log-llm-config/dist/apply_deferred_vscdb.js\"; APPLY_EC=\$?; elif [ \"\$ENV_LABEL\" = \"development\" ] && [ -n \"\$NPX_BASE\" ] && [ -f \"\$NPX_BASE/log-llm-config/dist/apply_deferred_vscdb.js\" ]; then echo deferred_restart:apply_via_optimus_npx_base; node \"\$NPX_BASE/log-llm-config/dist/apply_deferred_vscdb.js\"; APPLY_EC=\$?; elif command -v npx >/dev/null 2>&1; then echo deferred_restart:apply_via_npx env=\"\$ENV_LABEL\"; cd \"\$REPO_ROOT\" || true; if [ \"\$ENV_LABEL\" = \"staging\" ]; then npx --yes --package=log-llm-config-staging@latest apply-deferred-vscdb-staging; APPLY_EC=\$?; else npx --yes --package=log-llm-config@latest apply-deferred-vscdb; APPLY_EC=\$?; fi; else echo deferred_restart:no_npx; APPLY_EC=127; fi; echo deferred_restart:apply_exit=\$APPLY_EC; if [ \$APPLY_EC -ne 0 ]; then echo deferred_restart:APPLY_FAILED_see_messages_above; fi; echo deferred_restart:open_cursor; env -u npm_config_package -u npm_lifecycle_event -u npm_lifecycle_script -u npm_config_local_prefix open -a Cursor \"\$CURSOR_PROJECT\"; echo deferred_restart:open_exit=\$?; echo deferred_restart:end ts=\$(date -u +%Y-%m-%dT%H:%M:%SZ)' >/dev/null 2>&1 & killall -9 Cursor";
398
398
  const TRUSTED_CURSOR_JSON_SETTINGS_RESTART_COMMAND = 'CURSOR_PROJECT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) && export CURSOR_PROJECT && nohup bash -c \'sleep 2 && open -a Cursor "$CURSOR_PROJECT"\' >/dev/null 2>&1 & killall -9 Cursor';
399
399
  const TRUSTED_CLAUDE_RESTART_COMMAND = "nohup bash -c 'sleep 2 && open -a Claude' >/dev/null 2>&1 & pkill -x 'Claude'";
400
400
  export function isClaudeRestartCommand(cmd) {
@@ -8,6 +8,20 @@ import { getDeferredVscdbRestartLogPath } from './management_storage.js';
8
8
  import { normalizeAgentToken } from './compliance_check.js';
9
9
  import { isClaudeRestartCommand, isCursorRestartCommand, isTrustedRestartCommandForAutofix } from './remediation_sync.js';
10
10
  const FALLBACK_PATH = '/usr/bin:/bin:/usr/local/bin:/opt/homebrew/bin';
11
+ /** Vars set by `npx --package=...` that break unrelated scoped `npx @scope/pkg` after Cursor reopen. */
12
+ const NPM_RESTART_POLLUTION = [
13
+ 'npm_config_package',
14
+ 'npm_lifecycle_event',
15
+ 'npm_lifecycle_script',
16
+ 'npm_config_local_prefix',
17
+ ];
18
+ function envForRestartSpawn(base) {
19
+ const env = { ...base };
20
+ for (const key of NPM_RESTART_POLLUTION) {
21
+ delete env[key];
22
+ }
23
+ return env;
24
+ }
11
25
  function isDeferredVscdbRestart(cmd) {
12
26
  return cmd.includes('OPTIMUS_DEFERRED_LOG') || cmd.includes('apply_deferred_vscdb');
13
27
  }
@@ -61,12 +75,12 @@ export function executeTrustedRestartCommands(commands) {
61
75
  const child = spawn('sh', ['-c', t], {
62
76
  detached: true,
63
77
  stdio: 'ignore',
64
- env: {
78
+ env: envForRestartSpawn({
65
79
  ...process.env,
66
80
  PATH: process.env.PATH && String(process.env.PATH).trim().length > 0
67
81
  ? process.env.PATH
68
82
  : FALLBACK_PATH,
69
- },
83
+ }),
70
84
  });
71
85
  child.on('error', (err) => {
72
86
  const emsg = err instanceof Error ? err.message : String(err);
@@ -51,7 +51,7 @@ const getMetadata = () => ({
51
51
  github_username: process.env.GITHUB_USER || process.env.GH_USER || '',
52
52
  org_identifier: process.env.GITHUB_ORG || '',
53
53
  organization_uuid: readOrganizationUuid(),
54
- repo_identifier: process.env.GITHUB_REPOSITORY || '',
54
+ repo_identifier: process.env.OPTIMUS_WORKSPACE_REPO || process.env.GITHUB_REPOSITORY || '',
55
55
  branch: process.env.GITHUB_REF_NAME || process.env.BRANCH_NAME || '',
56
56
  commit_sha: process.env.GITHUB_SHA || '',
57
57
  agent_name: process.env.OPTIMUS_AGENT || '',
package/dist/tofu.js CHANGED
@@ -2,37 +2,48 @@
2
2
  * Tofu shim — centralises all imports from optimus-tofu.
3
3
  *
4
4
  * Reads ~/opt-ai-sec/management/optimus_dev.env at startup:
5
- * - environment=development loads local dist (file-relative path)
6
- * - anything else loads the published npm package
5
+ * - No file / unreadable production (ignores OPTIMUS_ENVIRONMENT).
6
+ * - File present environment= line in file, then OPTIMUS_ENVIRONMENT, then production.
7
+ * - environment=development + local dist present → loads sibling optimus-tofu dist
8
+ * - anything else → published optimus-tofu npm package
7
9
  *
8
10
  * All other source files import from this module, never directly from
9
11
  * "optimus-tofu", so the conditional lives in exactly one place.
10
12
  */
11
- import { readFileSync } from "fs";
13
+ import { existsSync, readFileSync } from "fs";
12
14
  import { homedir } from "os";
13
15
  import path from "path";
14
16
  import { fileURLToPath } from "url";
17
+ function managementEnvPath() {
18
+ const home = homedir();
19
+ if (!home)
20
+ return null;
21
+ return path.join(home, "opt-ai-sec", "management", "optimus_dev.env");
22
+ }
15
23
  function readEnvironment() {
16
- const fromEnv = process.env.OPTIMUS_ENVIRONMENT?.trim().toLowerCase();
17
- if (fromEnv)
18
- return fromEnv;
24
+ const envPath = managementEnvPath();
25
+ if (!envPath) {
26
+ return "production";
27
+ }
19
28
  try {
20
- const content = readFileSync(path.join(homedir(), "opt-ai-sec", "management", "optimus_dev.env"), "utf8");
29
+ const content = readFileSync(envPath, "utf8");
21
30
  const match = content.match(/^(?:environment|ENVIRONMENT|OPTIMUS_ENVIRONMENT)\s*=\s*(.+)/m);
22
31
  if (match)
23
32
  return match[1].trim().toLowerCase();
24
33
  }
25
34
  catch {
26
- // file missing or unreadable default to production
35
+ // No management file: always production (ignore stale OPTIMUS_ENVIRONMENT).
36
+ return "production";
27
37
  }
38
+ const fromEnv = process.env.OPTIMUS_ENVIRONMENT?.trim().toLowerCase();
39
+ if (fromEnv)
40
+ return fromEnv;
28
41
  return "production";
29
42
  }
30
43
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
31
- const isDevelopment = readEnvironment() === "development";
32
- // In development: resolve local optimus-tofu dist relative to this file.
33
- // dist/tofu.js → ../.. → npx_packages/staging/ → optimus-tofu/dist/index.js
34
44
  const localTofuPath = path.join(__dirname, "../../optimus-tofu/dist/index.js");
35
- const tofu = (isDevelopment
45
+ const useLocalTofu = readEnvironment() === "development" && existsSync(localTofuPath);
46
+ const tofu = (useLocalTofu
36
47
  ? await import(localTofuPath)
37
48
  : await import("optimus-tofu"));
38
49
  export const { loadEndpointBase, buildStartupEndpointUrl, createSignature, persistAuthKey, readStoredAuthKey, ensureAuthentication, getEndpointSource, canonicalizePayload, getAuthKeyPath, } = tofu;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "log-llm-config",
3
- "version": "1.3.70",
3
+ "version": "1.3.74",
4
4
  "description": "CLI helpers for logging hardware UUIDs and posting startup payloads to Optimus Security.",
5
5
  "type": "module",
6
6
  "bin": {