evolcore 0.0.16 → 0.0.18
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/CHANGELOG.md +46 -0
- package/bin/codex-managed-hook.mjs +16 -7
- package/bin/install-codex-managed-hooks.mjs +4 -2
- package/dist/agents/claude-runner.js +132 -14
- package/dist/agents/codex-app-server-client.js +6 -1
- package/dist/agents/codex-runner.js +21 -6
- package/dist/agents/ecagent-runner.js +39 -10
- package/dist/agents/gemini-runner.js +90 -19
- package/dist/aun/aid/store.js +36 -0
- package/dist/aun/msg/group.js +3 -1
- package/dist/aun/msg/p2p.js +23 -9
- package/dist/channels/aun.js +159 -21
- package/dist/cli/agent-command.js +67 -6
- package/dist/cli/agent.js +26 -0
- package/dist/cli/command-log.js +23 -4
- package/dist/cli/daemon-commands.js +53 -12
- package/dist/cli/init.js +21 -5
- package/dist/cli/restart-monitor.js +13 -6
- package/dist/cli/task-context.js +46 -1
- package/dist/cli/watch-logs.js +2 -2
- package/dist/config/builtin-roles.js +5 -1
- package/dist/config/role-ranks.js +4 -0
- package/dist/core/audit/event-key.js +29 -0
- package/dist/core/audit/log-integrity.js +13 -3
- package/dist/core/auth/auth-gateway.js +14 -18
- package/dist/core/auth/authorization-audit.js +110 -3
- package/dist/core/auth/authorization-denial.js +17 -0
- package/dist/core/auth/operation-authorizer.js +143 -18
- package/dist/core/auth/operation-catalog.js +21 -5
- package/dist/core/bootstrap-messages.js +11 -6
- package/dist/core/bootstrap-service.js +26 -4
- package/dist/core/causation/aun-association.js +7 -4
- package/dist/core/command/agent-control.js +25 -16
- package/dist/core/command/command-handler.js +50 -4
- package/dist/core/command/group-menu.js +1 -1
- package/dist/core/command/menu-catalog.js +32 -7
- package/dist/core/command/menu-handler.js +59 -23
- package/dist/core/command/menu-protocol.js +196 -0
- package/dist/core/command/slash-gate.js +14 -5
- package/dist/core/command/slash-handler.js +81 -99
- package/dist/core/event-catalog.js +18 -0
- package/dist/core/message/message-bridge.js +72 -9
- package/dist/core/message/pause-controller.js +53 -0
- package/dist/core/message/response-engine.js +98 -11
- package/dist/core/permission/sandbox-runtime.js +79 -13
- package/dist/core/permission/tool-policy.js +1 -1
- package/dist/index.js +357 -48
- package/dist/ipc.js +75 -4
- package/dist/utils/atomic-write.js +45 -11
- package/dist/utils/error-utils.js +38 -0
- package/dist/utils/logger.js +27 -0
- package/dist/utils/windows-autostart.js +740 -83
- package/ecagent/dist/harness/agent-harness.d.ts +1 -1
- package/ecagent/dist/harness/agent-harness.js +6 -4
- package/kits/docs/evolcore/config.md +1 -1
- package/kits/docs/evolcore/group-rules.md +2 -1
- package/kits/docs/identity/ROLE_DETAIL.md +3 -1
- package/kits/eck_manifest.json +25 -16
- package/kits/rules/01-overview.md +5 -5
- package/kits/rules/03-identity.md +1 -1
- package/kits/rules/04-relation.md +4 -4
- package/kits/rules/05-venue.md +5 -5
- package/kits/templates/bootstrap-welcome.md +3 -1
- package/kits/templates/system-fragments/bootstrap.md +17 -9
- package/package.json +1 -1
|
@@ -4,7 +4,42 @@ import { resolveCommandPath } from '../../utils/cross-platform.js';
|
|
|
4
4
|
import { getExistingHClassMaskTargets, getExistingLClassReadOnlyTargets, isSameOrDescendant, } from '../protected-paths.js';
|
|
5
5
|
import { resolveRoot } from '../../paths.js';
|
|
6
6
|
let cachedBubblewrapPath;
|
|
7
|
+
let sandboxInitializationCircuit;
|
|
8
|
+
let sandboxCircuitNoticeAt = 0;
|
|
7
9
|
export const SANDBOX_INITIALIZATION_FAILED = 'sandbox_initialization_failed';
|
|
10
|
+
export const SANDBOX_INITIALIZATION_COOLDOWN_MS = 5 * 60 * 1000;
|
|
11
|
+
export const SANDBOX_CIRCUIT_NOTICE_INTERVAL_MS = 60 * 1000;
|
|
12
|
+
/** Open a process-wide fail-closed circuit after a confirmed host bootstrap failure. */
|
|
13
|
+
export function recordSandboxInitializationFailure(error, stderr = [], now = Date.now()) {
|
|
14
|
+
const detail = createSandboxInitializationError(error, stderr).message.slice(0, 512);
|
|
15
|
+
sandboxInitializationCircuit = sandboxInitializationCircuit
|
|
16
|
+
? {
|
|
17
|
+
...sandboxInitializationCircuit,
|
|
18
|
+
lastObservedAt: now,
|
|
19
|
+
occurrences: sandboxInitializationCircuit.occurrences + 1,
|
|
20
|
+
detail,
|
|
21
|
+
}
|
|
22
|
+
: { openedAt: now, lastObservedAt: now, occurrences: 1, detail };
|
|
23
|
+
return { ...sandboxInitializationCircuit };
|
|
24
|
+
}
|
|
25
|
+
/** Return an active failure circuit, or allow one probe after the cooldown. */
|
|
26
|
+
export function getActiveSandboxInitializationFailure(now = Date.now(), cooldownMs = SANDBOX_INITIALIZATION_COOLDOWN_MS) {
|
|
27
|
+
if (!sandboxInitializationCircuit)
|
|
28
|
+
return undefined;
|
|
29
|
+
if (now - sandboxInitializationCircuit.lastObservedAt >= cooldownMs) {
|
|
30
|
+
sandboxInitializationCircuit = undefined;
|
|
31
|
+
sandboxCircuitNoticeAt = 0;
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return { ...sandboxInitializationCircuit };
|
|
35
|
+
}
|
|
36
|
+
/** Rate-limit human-readable warnings; structured audit still records every blocked task. */
|
|
37
|
+
export function shouldLogSandboxCircuitNotice(now = Date.now(), intervalMs = SANDBOX_CIRCUIT_NOTICE_INTERVAL_MS) {
|
|
38
|
+
if (sandboxCircuitNoticeAt && now - sandboxCircuitNoticeAt < intervalMs)
|
|
39
|
+
return false;
|
|
40
|
+
sandboxCircuitNoticeAt = now;
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
8
43
|
/** Recognize sandbox bootstrap failures independently of localized stderr. */
|
|
9
44
|
export function isSandboxInitializationFailure(error, stderr = []) {
|
|
10
45
|
const text = [error instanceof Error ? error.message : String(error ?? ''), ...stderr]
|
|
@@ -14,9 +49,18 @@ export function isSandboxInitializationFailure(error, stderr = []) {
|
|
|
14
49
|
|| /(?:apply-seccomp|seccomp)[\s\S]*(?:uid_map|gid_map|operation not permitted)/.test(text)
|
|
15
50
|
|| /(?:uid_map|gid_map)[\s\S]*(?:operation not permitted|permission denied)/.test(text)
|
|
16
51
|
|| /user namespace[\s\S]*(?:not permitted|unavailable|failed)/.test(text)
|
|
17
|
-
|| /bubblewrap[\s\S]*namespace[\s\S]*(?:failed|not permitted|permission denied)/.test(text)
|
|
52
|
+
|| /bubblewrap[\s\S]*namespace[\s\S]*(?:failed|not permitted|permission denied)/.test(text)
|
|
53
|
+
|| /(?:^|\n)\s*bwrap:\s*(?:can't|cannot|unable to)[\s\S]*(?:bind|mount|mount table)/.test(text);
|
|
18
54
|
}
|
|
19
55
|
export function createSandboxInitializationError(error, stderr = []) {
|
|
56
|
+
if (error instanceof Error
|
|
57
|
+
&& (error.code === SANDBOX_INITIALIZATION_FAILED
|
|
58
|
+
|| error.message.includes(`${SANDBOX_INITIALIZATION_FAILED}:`))) {
|
|
59
|
+
error.code = SANDBOX_INITIALIZATION_FAILED;
|
|
60
|
+
if (stderr.length > 0)
|
|
61
|
+
error.stderr = [...stderr].slice(-20);
|
|
62
|
+
return error;
|
|
63
|
+
}
|
|
20
64
|
const detail = error instanceof Error ? error.message : String(error ?? 'sandbox bootstrap failed');
|
|
21
65
|
const wrapped = new Error(`${SANDBOX_INITIALIZATION_FAILED}: ${detail}`);
|
|
22
66
|
wrapped.name = 'SandboxInitializationError';
|
|
@@ -211,6 +255,16 @@ function appendRuntimeBackedEtcFiles(args) {
|
|
|
211
255
|
args.push('--ro-bind', candidate, resolved);
|
|
212
256
|
}
|
|
213
257
|
}
|
|
258
|
+
function appendContainerEtcFileBinds(args) {
|
|
259
|
+
for (const candidate of ['/etc/resolv.conf', '/etc/hosts', '/etc/hostname']) {
|
|
260
|
+
if (!fs.existsSync(candidate))
|
|
261
|
+
continue;
|
|
262
|
+
// A directory bind does not recursively preserve OCI/container-runtime
|
|
263
|
+
// file mounts. Rebind only the three standard runtime-injected files after
|
|
264
|
+
// /etc becomes readonly; no other /etc mount is carried into the guard.
|
|
265
|
+
args.push('--ro-bind', candidate, candidate);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
214
268
|
function appendHClassMasks(args, root, maskContainerSockets) {
|
|
215
269
|
for (const target of getExistingHClassMaskTargets(root)) {
|
|
216
270
|
if (target.kind === 'directory')
|
|
@@ -251,20 +305,30 @@ export function buildHClassGuardCommand(executable, executableArgs, root = resol
|
|
|
251
305
|
throw new Error(`Codex managed requirements is not a file: ${requirements}`);
|
|
252
306
|
}
|
|
253
307
|
const managedDirectory = path.dirname(requirements);
|
|
308
|
+
const systemConfigDirectory = '/etc/codex';
|
|
309
|
+
let systemConfigStat;
|
|
310
|
+
try {
|
|
311
|
+
systemConfigStat = fs.lstatSync(systemConfigDirectory);
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
throw new Error(`Codex managed requirements mountpoint is unavailable: ${systemConfigDirectory} `
|
|
315
|
+
+ 'must be created as a real directory during installation');
|
|
316
|
+
}
|
|
317
|
+
if (!systemConfigStat.isDirectory() || systemConfigStat.isSymbolicLink()) {
|
|
318
|
+
throw new Error(`Codex managed requirements mountpoint is unsafe: ${systemConfigDirectory} `
|
|
319
|
+
+ 'must be a real directory');
|
|
320
|
+
}
|
|
254
321
|
// Keep the copied hook immutable even when a session uses bypass mode.
|
|
255
322
|
args.push('--ro-bind', managedDirectory, managedDirectory);
|
|
256
|
-
//
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
|
|
260
|
-
args.push('--
|
|
261
|
-
args
|
|
262
|
-
// Replace
|
|
263
|
-
//
|
|
264
|
-
args.push('--
|
|
265
|
-
args.push('--ro-bind', requirements, '/etc/codex/requirements.toml');
|
|
266
|
-
args.push('--remount-ro', '/etc/codex');
|
|
267
|
-
args.push('--remount-ro', '/etc');
|
|
323
|
+
// The guard starts from a writable root so owner-bypass workspaces keep
|
|
324
|
+
// their normal semantics. Make the system configuration tree readonly
|
|
325
|
+
// before replacing only Codex's directory, so a root daemon cannot write
|
|
326
|
+
// unrelated files under /etc from inside this namespace.
|
|
327
|
+
args.push('--ro-bind', '/etc', '/etc');
|
|
328
|
+
appendContainerEtcFileBinds(args);
|
|
329
|
+
// Replace only Codex's system-config directory. Requiring the mountpoint to
|
|
330
|
+
// exist prevents Bubblewrap from creating it on the writable host root.
|
|
331
|
+
args.push('--ro-bind', managedDirectory, systemConfigDirectory);
|
|
268
332
|
}
|
|
269
333
|
args.push('--', executable, ...executableArgs);
|
|
270
334
|
return { command: bubblewrapPath, args };
|
|
@@ -304,4 +368,6 @@ export function buildBubblewrapCommand(executable, executableArgs, options) {
|
|
|
304
368
|
}
|
|
305
369
|
export function _resetSandboxRuntimeCache() {
|
|
306
370
|
cachedBubblewrapPath = undefined;
|
|
371
|
+
sandboxInitializationCircuit = undefined;
|
|
372
|
+
sandboxCircuitNoticeAt = 0;
|
|
307
373
|
}
|
|
@@ -1148,7 +1148,7 @@ export function checkLClassWrite(toolName, input, context) {
|
|
|
1148
1148
|
behavior: 'deny',
|
|
1149
1149
|
message: context?.permissionMode === 'readonly'
|
|
1150
1150
|
? '🔒 只读模式:visitor 最低权限不允许读取 L-class 路径'
|
|
1151
|
-
: '🔒 L-class
|
|
1151
|
+
: '🔒 L-class 路径允许读取,但当前 Bash 复合命令无法证明为只读,已拒绝执行。请改用受控的 EvolCore 读取命令或白名单只读命令',
|
|
1152
1152
|
};
|
|
1153
1153
|
}
|
|
1154
1154
|
collectFilesystemWriteGrantPaths(input.additionalPermissions, writeGrantPaths, projectRootWriteSubpaths);
|