log-llm-config-staging 1.3.86 → 1.3.90

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.
@@ -6,8 +6,8 @@
6
6
  * When autofix returns restart_commands, this process does not spawn them — the shell hook pipes
7
7
  * the same JSON line to execute_trusted_restarts (TS allowlist + spawn).
8
8
  */
9
- import { applyAutofixViolations, normalizeAgentToken, pruneSatisfiedOneTimeRemediations, reportPostRestartVerificationOutcomes, runLocalRemediationComplianceCheck, uploadSatisfiedManifestConfigs, } from './log_config_files/runtime/compliance_check.js';
10
- import { isRemediationQuarantined, markRemediationApplyVerified, } from './log_config_files/runtime/remediation_apply_tracking.js';
9
+ import { applyAutofixViolations, confirmAppliedAutofixVerified, normalizeAgentToken, pruneSatisfiedOneTimeRemediations, reportPostRestartVerificationOutcomes, runLocalRemediationComplianceCheck, uploadSatisfiedManifestConfigs, } from './log_config_files/runtime/compliance_check.js';
10
+ import { isRemediationQuarantined } from './log_config_files/runtime/remediation_apply_tracking.js';
11
11
  import { existsSync, readFileSync, statSync } from 'node:fs';
12
12
  import { getRemediationInstructionsPath } from './log_config_files/runtime/management_storage.js';
13
13
  import { hookLogSessionBanner, hookRunLog, logRemediationApplyFailure } from './log_config_files/runtime/hook_logger.js';
@@ -249,12 +249,12 @@ export async function runCompliancePromptGate() {
249
249
  hookRunLog('compliance_prompt_gate: Claude — autofix wrote JSON; recheck still flags same UUID(s) — proceeding (immediate apply)');
250
250
  }
251
251
  if (deferredSqlitePending || recheckOk || claudeRecheckStaleAfterImmediateApply) {
252
- // For immediate (non-restart, non-deferred) fixes that the inline recheck confirmed,
253
- // mark verified now so the next hook run does not false-quarantine due to pending flag.
254
- if (recheckOk && restartCommands.length === 0 && !deferredSqlitePending) {
255
- for (const v of appliedViolations) {
256
- markRemediationApplyVerified(v.uuid);
257
- }
252
+ const immediateVerified = restartCommands.length === 0 &&
253
+ !deferredSqlitePending &&
254
+ (recheckOk || claudeRecheckStaleAfterImmediateApply);
255
+ if (immediateVerified) {
256
+ confirmAppliedAutofixVerified(appliedViolations, reportPromises);
257
+ await Promise.allSettled(reportPromises);
258
258
  }
259
259
  const changePreview = formatRemediationChangePreviewForApplied(appliedViolations);
260
260
  const changePreviewSuffix = changePreview ? `\n\n${changePreview}` : '';
@@ -6,10 +6,10 @@ import { OPT_AI_SEC_MANAGEMENT_REL } from '../../bootstrap_constants.js';
6
6
  import { hookRunLog } from '../runtime/hook_logger.js';
7
7
  const AUTH_KEY_RELATIVE_PATH = path.join(OPT_AI_SEC_MANAGEMENT_REL, 'auth_key.txt');
8
8
  /** Ensure authentication — verify stored key or request new one via handshake. */
9
- async function ensureAuthentication(hardwareUuid) {
9
+ async function ensureAuthentication(hardwareUuid, endpointBase) {
10
10
  const key = await ensureTofuAuthentication({
11
11
  hardwareUuid,
12
- endpointBase: loadEndpointBase(),
12
+ endpointBase: endpointBase ?? loadEndpointBase(),
13
13
  authRelativePath: AUTH_KEY_RELATIVE_PATH,
14
14
  postJson: (endpointUrl, body) => postStartupPayload(endpointUrl, body),
15
15
  onLog: (message) => {
@@ -17,7 +17,7 @@ import { mergeComposerShadowKeysFromReactiveBlob, readVscdbItemTableJson, } from
17
17
  import { readRemediationInstructionsFile, writeRemediationInstructionsFile, } from './management_storage.js';
18
18
  import { resolveRemediationConfigPath } from './remediation_config_path.js';
19
19
  import { resolveOpsTargetPath } from './ops_target_path.js';
20
- import { isRemediationQuarantined, markRemediationApplyPendingVerification, processPendingPostRestartVerifications, readRemediationApplyTrackingFile, writeRemediationApplyTrackingFile, } from './remediation_apply_tracking.js';
20
+ import { isRemediationQuarantined, markRemediationApplyPendingVerification, markRemediationApplyVerified, processPendingPostRestartVerifications, readRemediationApplyTrackingFile, writeRemediationApplyTrackingFile, } from './remediation_apply_tracking.js';
21
21
  import { complianceRunnerDiag, hookRunLog, logRemediationApplyFailure } from './hook_logger.js';
22
22
  import { loadEndpointBase } from '../sender/endpoint_config.js';
23
23
  import { resolveHardwareUuid, tryResolveHardwareUuid } from './hardware_uuid.js';
@@ -487,6 +487,17 @@ export function reportPostRestartVerificationOutcomes(violations) {
487
487
  });
488
488
  return { outcomes, reportPromises };
489
489
  }
490
+ /**
491
+ * Immediate autofix succeeded (inline recheck OK or Claude stale-recheck tolerance).
492
+ * Clear pending verification locally and report verified so the next prompt does not POST
493
+ * verification_failed while the user already saw a successful fix.
494
+ */
495
+ export function confirmAppliedAutofixVerified(appliedViolations, reportPromises) {
496
+ for (const v of appliedViolations) {
497
+ markRemediationApplyVerified(v.uuid);
498
+ reportPromises.push(reportAutofixApplied(v.uuid, 'verified'));
499
+ }
500
+ }
490
501
  export function applyAutofixViolations(violations, agent = 'cursor') {
491
502
  for (const v of violations) {
492
503
  if (!v.autofix_allowed) {
@@ -158,12 +158,9 @@ function transferQuarantineForRetiredUuids(removed, added, retiredInstructions,
158
158
  if (changed)
159
159
  writeRemediationApplyTrackingFile(file);
160
160
  }
161
- async function ensureAuthKeyForMachine(machineUuid) {
162
- const stored = readStoredAuthKey();
163
- if (stored?.key)
164
- return stored;
161
+ async function ensureAuthKeyForMachine(endpointBase, machineUuid) {
165
162
  try {
166
- return await ensureAuthentication(machineUuid);
163
+ return await ensureAuthentication(machineUuid, endpointBase);
167
164
  }
168
165
  catch (err) {
169
166
  hookRunLog(`remediation_sync: ensureAuthentication failed: ${err instanceof Error ? err.message : String(err)}`);
@@ -178,7 +175,7 @@ function buildSignedMachinePostBody(machineUuid, fields, authKey) {
178
175
  }
179
176
  export async function fetchSync(endpointBase, machineUuid, activeUuids, timeoutMs = 8000) {
180
177
  const sortedUuids = [...new Set(activeUuids.map((u) => u.trim()).filter(Boolean))].sort();
181
- const authKey = await ensureAuthKeyForMachine(machineUuid);
178
+ const authKey = await ensureAuthKeyForMachine(endpointBase, machineUuid);
182
179
  if (!authKey) {
183
180
  hookRunLog('remediation_sync_post: no auth key, skipping');
184
181
  complianceRunnerDiag('remediation_sync_post: no auth key');
@@ -200,7 +197,10 @@ export async function fetchSync(endpointBase, machineUuid, activeUuids, timeoutM
200
197
  return null;
201
198
  }
202
199
  if (statusCode !== 200 || !responseBody) {
203
- const line = `remediation_sync_post: url=${url} status=${statusCode} bytes=${responseBody?.length ?? 0}`;
200
+ const bodyHint = responseBody && responseBody.length < 500
201
+ ? ` body=${responseBody.replace(/\s+/g, ' ').trim()}`
202
+ : '';
203
+ const line = `remediation_sync_post: url=${url} status=${statusCode} bytes=${responseBody?.length ?? 0}${bodyHint}`;
204
204
  hookRunLog(line);
205
205
  complianceRunnerDiag(line);
206
206
  return null;
@@ -216,7 +216,7 @@ export async function fetchSync(endpointBase, machineUuid, activeUuids, timeoutM
216
216
  }
217
217
  async function fetchManifest(endpointBase, machineUuid, uuids, timeoutMs = 8000) {
218
218
  const sortedUuids = [...new Set(uuids.map((u) => u.trim()).filter(Boolean))].sort();
219
- const authKey = await ensureAuthKeyForMachine(machineUuid);
219
+ const authKey = await ensureAuthKeyForMachine(endpointBase, machineUuid);
220
220
  if (!authKey) {
221
221
  hookRunLog('remediation_manifest_post: no auth key, skipping');
222
222
  complianceRunnerDiag('remediation_manifest_post: no auth key');
@@ -1,9 +1,9 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { OPT_AI_SEC_MANAGEMENT_REL } from '../bootstrap_constants.js';
4
+ import { loadEndpointBase } from '../log_config_files/sender/endpoint_config.js';
5
+ import { buildStartupEndpointUrl, normalizeBaseUrl } from '../tofu.js';
4
6
  const AUTH_KEY_RELATIVE_PATH = path.join(OPT_AI_SEC_MANAGEMENT_REL, 'auth_key.txt');
5
- const OPTIMUS_ENV_FILENAME = 'optimus_dev.env';
6
- const STARTUP_ENDPOINT_SUFFIX = '/endpoint_security/startup/';
7
7
  const getAuthKeyPath = () => {
8
8
  const homeDir = process.env.HOME || process.env.USERPROFILE;
9
9
  if (!homeDir)
@@ -34,38 +34,4 @@ const readStoredAuthKey = () => {
34
34
  }
35
35
  return null;
36
36
  };
37
- const loadEndpointBase = () => {
38
- const DEFAULT_ENDPOINT = 'https://demo.optimuslabs.io/';
39
- const fromEnv = process.env.OPTIMUS_ENDPOINT?.trim();
40
- if (fromEnv)
41
- return fromEnv;
42
- const envPath = path.join(process.cwd(), OPTIMUS_ENV_FILENAME);
43
- try {
44
- if (!existsSync(envPath))
45
- return DEFAULT_ENDPOINT;
46
- const envContent = readFileSync(envPath, 'utf8');
47
- for (const line of envContent.split(/\r?\n/)) {
48
- const trimmed = line.trim();
49
- if (!trimmed || trimmed.startsWith('#'))
50
- continue;
51
- const [key, ...rest] = trimmed.split('=');
52
- if (key === 'OPTIMUS_ENDPOINT') {
53
- const value = rest.join('=').trim();
54
- if (value)
55
- return value;
56
- }
57
- }
58
- }
59
- catch { /* fall back to default */ }
60
- return DEFAULT_ENDPOINT;
61
- };
62
- const normalizeBaseUrl = (rawUrl) => {
63
- let base = rawUrl.trim();
64
- if (!base)
65
- throw new Error('OPTIMUS_ENDPOINT is empty');
66
- base = base.replace(/\/+$/, '');
67
- base = base.replace(/\/(optimus_security|endpoint_security)$/i, '');
68
- return base;
69
- };
70
- const buildStartupEndpointUrl = (baseUrl) => `${normalizeBaseUrl(baseUrl)}${STARTUP_ENDPOINT_SUFFIX}`;
71
- export { getAuthKeyPath, writeAuthKey, readStoredAuthKey, loadEndpointBase, normalizeBaseUrl, buildStartupEndpointUrl };
37
+ export { getAuthKeyPath, writeAuthKey, readStoredAuthKey, loadEndpointBase, normalizeBaseUrl, buildStartupEndpointUrl, };
package/dist/tofu.js CHANGED
@@ -19,4 +19,4 @@ const useLocalTofu = shouldUseLocalTofuDist(localTofuPath);
19
19
  const tofu = (useLocalTofu
20
20
  ? await import(localTofuPath)
21
21
  : await import("optimus-tofu-staging"));
22
- export const { loadEndpointBase, buildStartupEndpointUrl, createSignature, persistAuthKey, readStoredAuthKey, ensureAuthentication, getEndpointSource, canonicalizePayload, getAuthKeyPath, } = tofu;
22
+ export const { loadEndpointBase, normalizeBaseUrl, 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-staging",
3
- "version": "1.3.86",
3
+ "version": "1.3.90",
4
4
  "description": "CLI helpers for logging hardware UUIDs and posting startup payloads to Optimus Security.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -58,6 +58,6 @@
58
58
  "dependencies": {
59
59
  "axios": "^1.15.2",
60
60
  "canonicalize": "^2.1.0",
61
- "optimus-tofu-staging": "^0.1.15"
61
+ "optimus-tofu-staging": "^0.1.16"
62
62
  }
63
63
  }