log-llm-config-staging 1.3.44
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 +46 -0
- package/dist/apply_deferred_vscdb.js +8 -0
- package/dist/bootstrap_constants.js +5 -0
- package/dist/cli/bash_script_generator.js +95 -0
- package/dist/cli.js +103 -0
- package/dist/cli_invocation_match.js +28 -0
- package/dist/compliance_check_runner.js +17 -0
- package/dist/compliance_prompt_gate.js +197 -0
- package/dist/endpoint_client/http_transport.js +88 -0
- package/dist/endpoint_client/index.js +3 -0
- package/dist/endpoint_client/registry_api.js +41 -0
- package/dist/endpoint_client/startup_api.js +43 -0
- package/dist/endpoint_client/types.js +4 -0
- package/dist/execute_trusted_restarts.js +54 -0
- package/dist/log_config_files/auth/auth_flow.js +22 -0
- package/dist/log_config_files/auth/auth_key_store.js +14 -0
- package/dist/log_config_files/collection/config_collector.js +160 -0
- package/dist/log_config_files/collection/directory_collector.js +96 -0
- package/dist/log_config_files/collection/enrichment_helpers.js +53 -0
- package/dist/log_config_files/collection/file_type_rules.js +47 -0
- package/dist/log_config_files/collection/mcp_tool_collector.js +37 -0
- package/dist/log_config_files/collection/openclaw_helpers.js +55 -0
- package/dist/log_config_files/collection/plugin_collector.js +89 -0
- package/dist/log_config_files/collection/plugin_version_helpers.js +37 -0
- package/dist/log_config_files/index.js +19 -0
- package/dist/log_config_files/paths/path_constants_helpers.js +71 -0
- package/dist/log_config_files/paths/pattern_resolver.js +227 -0
- package/dist/log_config_files/readers/file_readers.js +69 -0
- package/dist/log_config_files/readers/vscdb_config_builder.js +146 -0
- package/dist/log_config_files/readers/vscdb_reader.js +247 -0
- package/dist/log_config_files/runtime/compliance_check.js +518 -0
- package/dist/log_config_files/runtime/hardware_uuid.js +36 -0
- package/dist/log_config_files/runtime/hook_logger.js +197 -0
- package/dist/log_config_files/runtime/main_runner.js +192 -0
- package/dist/log_config_files/runtime/management_storage.js +82 -0
- package/dist/log_config_files/runtime/remediation_config_path.js +90 -0
- package/dist/log_config_files/runtime/remediation_sync.js +1290 -0
- package/dist/log_config_files/runtime/sqlite_binary.js +92 -0
- package/dist/log_config_files/runtime/trusted_restarts.js +52 -0
- package/dist/log_config_files/sender/batch_sender.js +220 -0
- package/dist/log_config_files/sender/endpoint_config.js +24 -0
- package/dist/log_config_files/sender/signing.js +1 -0
- package/dist/log_sensitive_paths_audit.js +97 -0
- package/dist/log_uuid/auth_key_store.js +71 -0
- package/dist/log_uuid/hardware_uuid.js +35 -0
- package/dist/log_uuid/index.js +11 -0
- package/dist/log_uuid/log_uuid_helper.js +30 -0
- package/dist/log_uuid/startup_sender.js +74 -0
- package/dist/log_uuid/user_profile.js +178 -0
- package/dist/types/config_file_types.js +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { createSignature as createSharedSignature } from 'optimus-tofu-staging';
|
|
2
|
+
import { classifyEndpointResponse, postStartupPayload } from '../endpoint_client/index.js';
|
|
3
|
+
import { resolveHardwareUuid } from './hardware_uuid.js';
|
|
4
|
+
import { writeAuthKey, readStoredAuthKey, loadEndpointBase, buildStartupEndpointUrl } from './auth_key_store.js';
|
|
5
|
+
import { resolveUserProfile } from './user_profile.js';
|
|
6
|
+
const canonicalizeValue = (value) => {
|
|
7
|
+
if (Array.isArray(value))
|
|
8
|
+
return value.map(canonicalizeValue);
|
|
9
|
+
if (value && typeof value === 'object') {
|
|
10
|
+
const result = {};
|
|
11
|
+
for (const key of Object.keys(value).sort())
|
|
12
|
+
result[key] = canonicalizeValue(value[key]);
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
};
|
|
17
|
+
const canonicalStringify = (value) => JSON.stringify(canonicalizeValue(value));
|
|
18
|
+
const createSignature = (payloadSummary, keyHex) => {
|
|
19
|
+
// Keep this adapter for backward compatibility of public exports in log_uuid.
|
|
20
|
+
return createSharedSignature(payloadSummary, keyHex);
|
|
21
|
+
};
|
|
22
|
+
const getMetadata = () => ({
|
|
23
|
+
github_username: process.env.GITHUB_USER || process.env.GH_USER || '',
|
|
24
|
+
org_identifier: process.env.GITHUB_ORG || '',
|
|
25
|
+
repo_identifier: process.env.GITHUB_REPOSITORY || '',
|
|
26
|
+
branch: process.env.GITHUB_REF_NAME || process.env.BRANCH_NAME || '',
|
|
27
|
+
commit_sha: process.env.GITHUB_SHA || '',
|
|
28
|
+
agent_name: process.env.OPTIMUS_AGENT || '',
|
|
29
|
+
user_profile: { ...resolveUserProfile() },
|
|
30
|
+
});
|
|
31
|
+
function buildRequestBody(hardwareUuid, timestamp) {
|
|
32
|
+
const payloadSummary = { timestamp, directory: process.cwd(), hardware_uuid: hardwareUuid };
|
|
33
|
+
const requestBody = { hardware_uuid: hardwareUuid, payload: payloadSummary, metadata: getMetadata(), scan_timestamp: timestamp };
|
|
34
|
+
const storedKey = readStoredAuthKey();
|
|
35
|
+
if (storedKey?.key && storedKey.hardware_uuid === hardwareUuid) {
|
|
36
|
+
requestBody.signature = createSignature(payloadSummary, storedKey.key);
|
|
37
|
+
if (storedKey.key_id)
|
|
38
|
+
requestBody.key_id = storedKey.key_id;
|
|
39
|
+
console.log('Using stored auth key to sign startup payload.');
|
|
40
|
+
}
|
|
41
|
+
else if (storedKey && storedKey.hardware_uuid !== hardwareUuid) {
|
|
42
|
+
console.warn('Stored auth key hardware UUID mismatch; requesting new key from server.');
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
console.log('No stored auth key found; requesting new key from server.');
|
|
46
|
+
}
|
|
47
|
+
return requestBody;
|
|
48
|
+
}
|
|
49
|
+
const maybeSendToEndpoint = async (hardwareUuid, timestamp) => {
|
|
50
|
+
const startupEndpointUrl = buildStartupEndpointUrl(loadEndpointBase());
|
|
51
|
+
const requestBody = buildRequestBody(hardwareUuid, timestamp);
|
|
52
|
+
try {
|
|
53
|
+
const response = await postStartupPayload(startupEndpointUrl, requestBody);
|
|
54
|
+
const result = classifyEndpointResponse(response);
|
|
55
|
+
console.log(result.message);
|
|
56
|
+
if (result.branch === 'key_issued' && result.key)
|
|
57
|
+
writeAuthKey(result.key, result.keyId, hardwareUuid);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error(`Failed to contact endpoint: ${error.message}`);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const main = async () => {
|
|
64
|
+
const timestamp = new Date().toISOString();
|
|
65
|
+
try {
|
|
66
|
+
const hardwareUuid = resolveHardwareUuid();
|
|
67
|
+
await maybeSendToEndpoint(hardwareUuid, timestamp);
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error(`Unable to log hardware UUID: ${error.message}`);
|
|
71
|
+
process.exitCode = 1;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
export { canonicalizeValue, canonicalStringify, createSignature, getMetadata, maybeSendToEndpoint, main };
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import crypto from 'node:crypto';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { readCommandOutput, resolveHardwareUuid } from './hardware_uuid.js';
|
|
7
|
+
const safeJsonParse = (raw) => {
|
|
8
|
+
try {
|
|
9
|
+
return JSON.parse(raw);
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const readCursorCachedEmailFromVscdb = () => {
|
|
16
|
+
const dbPath = path.join(os.homedir(), 'Library/Application Support/Cursor/User/globalStorage/state.vscdb');
|
|
17
|
+
if (!fs.existsSync(dbPath))
|
|
18
|
+
return '';
|
|
19
|
+
try {
|
|
20
|
+
const out = execFileSync('sqlite3', [dbPath, "select value from ItemTable where key='cursorAuth/cachedEmail';"], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] }).trim();
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return '';
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
/** Fallback: `storage.json` key path `cursor.auth.email` (design_notes). */
|
|
28
|
+
const readCursorCachedEmailFromStorageJson = () => {
|
|
29
|
+
const fp = path.join(os.homedir(), 'Library/Application Support/Cursor/User/globalStorage/storage.json');
|
|
30
|
+
if (!fs.existsSync(fp))
|
|
31
|
+
return '';
|
|
32
|
+
try {
|
|
33
|
+
const parsed = safeJsonParse(fs.readFileSync(fp, { encoding: 'utf8' }));
|
|
34
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
35
|
+
return '';
|
|
36
|
+
const root = parsed;
|
|
37
|
+
const cursor = root.cursor;
|
|
38
|
+
if (!cursor || typeof cursor !== 'object' || Array.isArray(cursor))
|
|
39
|
+
return '';
|
|
40
|
+
const auth = cursor.auth;
|
|
41
|
+
if (!auth || typeof auth !== 'object' || Array.isArray(auth))
|
|
42
|
+
return '';
|
|
43
|
+
const email = auth.email;
|
|
44
|
+
return typeof email === 'string' ? email.trim() : '';
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return '';
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const readCursorCachedEmail = () => readCursorCachedEmailFromVscdb() || readCursorCachedEmailFromStorageJson();
|
|
51
|
+
const readClaudeAuthEmailFromCli = () => {
|
|
52
|
+
try {
|
|
53
|
+
const out = execFileSync('claude', ['auth', 'status'], {
|
|
54
|
+
encoding: 'utf8',
|
|
55
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
56
|
+
}).trim();
|
|
57
|
+
if (!out)
|
|
58
|
+
return '';
|
|
59
|
+
const parsed = safeJsonParse(out);
|
|
60
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
61
|
+
const email = parsed.email;
|
|
62
|
+
return typeof email === 'string' ? email.trim() : '';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return '';
|
|
67
|
+
}
|
|
68
|
+
return '';
|
|
69
|
+
};
|
|
70
|
+
/** Fallback: optional Claude config files under ~/.claude/ (design_notes). */
|
|
71
|
+
const readClaudeEmailFromHomeFiles = () => {
|
|
72
|
+
const candidates = [
|
|
73
|
+
path.join(os.homedir(), '.claude/.credentials.json'),
|
|
74
|
+
path.join(os.homedir(), '.claude/.claude.json'),
|
|
75
|
+
];
|
|
76
|
+
for (const fp of candidates) {
|
|
77
|
+
if (!fs.existsSync(fp))
|
|
78
|
+
continue;
|
|
79
|
+
try {
|
|
80
|
+
const parsed = safeJsonParse(fs.readFileSync(fp, { encoding: 'utf8' }));
|
|
81
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
82
|
+
continue;
|
|
83
|
+
const email = parsed.email;
|
|
84
|
+
if (typeof email === 'string' && email.includes('@'))
|
|
85
|
+
return email.trim();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
/* try next */
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return '';
|
|
92
|
+
};
|
|
93
|
+
const readClaudeAuthEmail = () => readClaudeAuthEmailFromCli().trim() || readClaudeEmailFromHomeFiles();
|
|
94
|
+
const readMacUsername = () => {
|
|
95
|
+
const fromEnv = process.env.OPTIMUS_MAC_USERNAME?.trim() ||
|
|
96
|
+
process.env.USER?.trim() ||
|
|
97
|
+
process.env.LOGNAME?.trim() ||
|
|
98
|
+
'';
|
|
99
|
+
if (fromEnv)
|
|
100
|
+
return fromEnv;
|
|
101
|
+
return readCommandOutput('id -un');
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Matches design_notes order: `gh api user` (login), then CI-style env, then `git config user.name`.
|
|
105
|
+
* `metadata.github_username` in startup_sender still uses env only; this field is the richer probe.
|
|
106
|
+
*/
|
|
107
|
+
const readGithubUsername = () => {
|
|
108
|
+
try {
|
|
109
|
+
const out = execFileSync('gh', ['api', 'user', '--jq', '.login'], {
|
|
110
|
+
encoding: 'utf8',
|
|
111
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
112
|
+
maxBuffer: 1024 * 1024,
|
|
113
|
+
// CI often has `gh` installed; without a cap it can block on auth/network and hang callers.
|
|
114
|
+
timeout: 3500,
|
|
115
|
+
}).trim();
|
|
116
|
+
if (out)
|
|
117
|
+
return out;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
/* gh missing or not authenticated */
|
|
121
|
+
}
|
|
122
|
+
return (process.env.GITHUB_USER?.trim() ||
|
|
123
|
+
process.env.GH_USER?.trim() ||
|
|
124
|
+
readCommandOutput('git config user.name'));
|
|
125
|
+
};
|
|
126
|
+
const readUserProfileFromEnvOrFile = () => {
|
|
127
|
+
const inline = process.env.OPTIMUS_USER_PROFILE_JSON?.trim();
|
|
128
|
+
if (inline) {
|
|
129
|
+
const parsed = safeJsonParse(inline);
|
|
130
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
|
|
131
|
+
return parsed;
|
|
132
|
+
}
|
|
133
|
+
const filePath = process.env.OPTIMUS_USER_PROFILE_FILE?.trim();
|
|
134
|
+
if (filePath && fs.existsSync(filePath)) {
|
|
135
|
+
const parsed = safeJsonParse(fs.readFileSync(filePath, { encoding: 'utf8' }));
|
|
136
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
|
|
137
|
+
return parsed;
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
};
|
|
141
|
+
const isPlausibleUuid = (s) => /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i.test(s.trim());
|
|
142
|
+
/**
|
|
143
|
+
* macOS Open Directory **GeneratedUID** for the console user (same concept as Directory Utility).
|
|
144
|
+
* See `dscl . -read /Users/<shortname> GeneratedUID`. Not the hardware UUID (that is `machineuuid`).
|
|
145
|
+
*
|
|
146
|
+
* `OPTIMUS_MAC_GENERATED_UID` overrides for tests or locked-down environments where `dscl` is unavailable.
|
|
147
|
+
*/
|
|
148
|
+
const readMacAccountGeneratedUid = () => {
|
|
149
|
+
const env = process.env.OPTIMUS_MAC_GENERATED_UID?.trim();
|
|
150
|
+
if (env && isPlausibleUuid(env))
|
|
151
|
+
return env.trim().toLowerCase();
|
|
152
|
+
if (process.platform !== 'darwin')
|
|
153
|
+
return '';
|
|
154
|
+
const user = readMacUsername();
|
|
155
|
+
if (!user || !/^[a-zA-Z0-9._-]+$/.test(user))
|
|
156
|
+
return '';
|
|
157
|
+
try {
|
|
158
|
+
const out = execFileSync('dscl', ['.', '-read', `/Users/${user}`, 'GeneratedUID'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
159
|
+
const m = out.match(/GeneratedUID:\s*([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12})/);
|
|
160
|
+
if (m?.[1] && isPlausibleUuid(m[1]))
|
|
161
|
+
return m[1].toLowerCase();
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return '';
|
|
165
|
+
}
|
|
166
|
+
return '';
|
|
167
|
+
};
|
|
168
|
+
const buildDefaultUserProfile = () => ({
|
|
169
|
+
generateduuid: readMacAccountGeneratedUid() || crypto.randomUUID(),
|
|
170
|
+
machineuuid: resolveHardwareUuid(),
|
|
171
|
+
mac_username: readMacUsername(),
|
|
172
|
+
github_username: readGithubUsername(),
|
|
173
|
+
claude_email: readClaudeAuthEmail(),
|
|
174
|
+
cursor_email: readCursorCachedEmail(),
|
|
175
|
+
});
|
|
176
|
+
/** Best-effort local user profile object for startup metadata. */
|
|
177
|
+
const resolveUserProfile = () => readUserProfileFromEnvOrFile() ?? buildDefaultUserProfile();
|
|
178
|
+
export { resolveUserProfile };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "log-llm-config-staging",
|
|
3
|
+
"version": "1.3.44",
|
|
4
|
+
"description": "CLI helpers for logging hardware UUIDs and posting startup payloads to Optimus Security.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"log-llm-config-staging": "dist/cli.js",
|
|
8
|
+
"log_uuid-staging": "dist/log_uuid/index.js",
|
|
9
|
+
"log_config_files-staging": "dist/log_config_files/index.js",
|
|
10
|
+
"log_sensitive_paths_audit-staging": "dist/log_sensitive_paths_audit.js",
|
|
11
|
+
"apply-deferred-vscdb-staging": "dist/apply_deferred_vscdb.js",
|
|
12
|
+
"execute-trusted-restarts-staging": "dist/execute_trusted_restarts.js",
|
|
13
|
+
"compliance_prompt_gate-staging": "dist/compliance_prompt_gate.js",
|
|
14
|
+
"compliance_check_runner-staging": "dist/compliance_check_runner.js"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc -p tsconfig.json",
|
|
18
|
+
"dev": "ts-node src/cli.ts",
|
|
19
|
+
"lint": "eslint \"src/**/*.ts\"",
|
|
20
|
+
"prepare": "npm run build",
|
|
21
|
+
"pretest": "npm run build",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"mcp",
|
|
27
|
+
"config",
|
|
28
|
+
"logging",
|
|
29
|
+
"npx"
|
|
30
|
+
],
|
|
31
|
+
"author": "",
|
|
32
|
+
"license": "UNLICENSED",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/optimuslabs-io/optimus-secure-fdn.git",
|
|
36
|
+
"directory": "npx_packages/staging/log-llm-config"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/optimuslabs-io/optimus-secure-fdn/issues"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/optimuslabs-io/optimus-secure-fdn/tree/main/npx_packages/staging/log-llm-config#readme",
|
|
42
|
+
"files": [
|
|
43
|
+
"dist/**/*",
|
|
44
|
+
"README.md"
|
|
45
|
+
],
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^24.10.1",
|
|
51
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
52
|
+
"@vitest/ui": "^3.2.4",
|
|
53
|
+
"ts-node": "^10.9.2",
|
|
54
|
+
"typescript": "^5.4.5",
|
|
55
|
+
"vitest": "^3.2.4"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"axios": "^1.15.0",
|
|
59
|
+
"canonicalize": "^2.1.0",
|
|
60
|
+
"optimus-tofu-staging": "file:../optimus-tofu"
|
|
61
|
+
}
|
|
62
|
+
}
|