@actiondock/core 2.20.0 → 2.21.0
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/dist/errors.d.ts +11 -1
- package/dist/errors.js +23 -0
- package/dist/execution/service.js +36 -5
- package/dist/host/host.d.ts +11 -0
- package/dist/host/host.js +258 -39
- package/dist/host/types.d.ts +10 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +5 -1
- package/dist/invocation/types.d.ts +31 -0
- package/dist/invocation/types.js +10 -1
- package/dist/package/index.d.ts +1 -1
- package/dist/package/runtime.js +18 -4
- package/dist/platform/node.d.ts +6 -0
- package/dist/platform/node.js +59 -16
- package/dist/platform/types.d.ts +11 -0
- package/dist/process/command-executor.d.ts +35 -0
- package/dist/process/command-executor.js +326 -0
- package/dist/process/index.d.ts +1 -0
- package/dist/process/index.js +1 -0
- package/dist/process/process-driver.d.ts +19 -6
- package/dist/process/process-driver.js +223 -54
- package/dist/process/run-executor.js +101 -47
- package/dist/project/dependencies.d.ts +92 -0
- package/dist/project/dependencies.js +543 -0
- package/dist/project/index.d.ts +3 -0
- package/dist/project/index.js +3 -0
- package/dist/project/init.js +2 -2
- package/dist/project/loader.js +15 -30
- package/dist/project/package-manager.d.ts +40 -0
- package/dist/project/package-manager.js +224 -0
- package/dist/project/preparation.d.ts +8 -0
- package/dist/project/preparation.js +130 -0
- package/dist/project/transactions.d.ts +5 -1
- package/dist/project/transactions.js +35 -75
- package/dist/runtime/context.d.ts +21 -2
- package/dist/runtime/context.js +42 -17
- package/dist/runtime/run-persistence.d.ts +1 -1
- package/dist/runtime/run-persistence.js +4 -3
- package/dist/security/config-cipher.d.ts +54 -0
- package/dist/security/config-cipher.js +190 -0
- package/dist/security/config-key.d.ts +35 -0
- package/dist/security/config-key.js +469 -0
- package/dist/server/routes/config.js +20 -1
- package/dist/service/factory.js +3 -0
- package/dist/service/types.d.ts +8 -0
- package/dist/storage/config-value.d.ts +33 -0
- package/dist/storage/config-value.js +102 -0
- package/dist/storage/file-lock.js +35 -21
- package/dist/storage/index.d.ts +24 -2
- package/dist/storage/index.js +65 -2
- package/dist/storage/migrations/index.d.ts +40 -0
- package/dist/storage/migrations/index.js +96 -0
- package/dist/storage/migrations/v2-to-v3.d.ts +16 -0
- package/dist/storage/migrations/v2-to-v3.js +116 -0
- package/dist/storage/sqlite-config.d.ts +62 -3
- package/dist/storage/sqlite-config.js +163 -9
- package/dist/storage/sqlite-driver.d.ts +5 -2
- package/dist/storage/sqlite-driver.js +24 -3
- package/dist/storage/sqlite-schema.d.ts +20 -2
- package/dist/storage/sqlite-schema.js +129 -132
- package/dist/storage/sqlite.d.ts +7 -2
- package/dist/storage/sqlite.js +64 -13
- package/dist/storage/types.d.ts +72 -4
- package/dist/storage/types.js +7 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -17,12 +17,19 @@ export type { ResolvedEnv } from "./runtime/env.js";
|
|
|
17
17
|
export type { ActionInvokeOptions, ActionRef, ResolvedActionRef, ExecutionResult, RunRecord, RunOrigin, ExecutionEvent, } from "@actiondock/sdk";
|
|
18
18
|
export type { RunOptions, ExecutionTicket, CancelResult, } from "./execution/types.js";
|
|
19
19
|
export type { ActionBindings, ActionBindingTarget } from "./invocation/bindings.js";
|
|
20
|
+
export type { LocalPackagePreparationTarget, LocalPackagePreparationContext, LocalPackagePreparer, } from "./invocation/types.js";
|
|
20
21
|
export type { ActionSpec, ActionSummary, PlaybookSpec, PlaybookSummary, PackageInfo, ListActionsOptions, } from "./package/types.js";
|
|
21
22
|
export { createNodePlatform, } from "./platform/node.js";
|
|
22
23
|
export { startActionDockServer, } from "./server/server.js";
|
|
23
24
|
export type { ServerOptions, ServerOptions as ActionDockServerOptions, ActionDockServerInstance, } from "./server/types.js";
|
|
24
25
|
export { initProject } from "./project/init.js";
|
|
25
26
|
export { loadProjectConfig, findProjectRoot, } from "./project/loader.js";
|
|
27
|
+
export { ensureProjectDependencies, } from "./project/dependencies.js";
|
|
28
|
+
export type { EnsureProjectDependenciesOptions, EnsureProjectDependenciesResult, } from "./project/dependencies.js";
|
|
26
29
|
export type { ProjectConfig, } from "./project/types.js";
|
|
27
30
|
export type { PackageGraph, } from "./catalog/graph.js";
|
|
28
|
-
export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, CONFIG_VALUE_INVALID, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, PROCESS_FAILED, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, PROJECT_ROOT_NOT_FOUND, describeActionLoadFailure, createErrorEnvelope, resolveExecutionHint, } from "./errors.js";
|
|
31
|
+
export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, CONFIG_VALUE_INVALID, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, DEPENDENCIES_NOT_READY, DEPENDENCY_INSTALL_FAILED, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, CONFIG_ENCRYPTION_ERROR, CONFIG_DECRYPT_FAILED, NOT_FOUND, SERVER_ERROR, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, PROCESS_FAILED, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, PROJECT_ROOT_NOT_FOUND, describeActionLoadFailure, createErrorEnvelope, resolveExecutionHint, } from "./errors.js";
|
|
32
|
+
export { executeCommand } from "./process/command-executor.js";
|
|
33
|
+
export type { ExecuteCommandOptions, CommandExecutionResult, } from "./process/command-executor.js";
|
|
34
|
+
export type { ConfigEncryptionKey, ConfigKeyProvider, } from "./security/config-cipher.js";
|
|
35
|
+
export { createConfigKeyProvider } from "./security/config-key.js";
|
package/dist/index.js
CHANGED
|
@@ -19,5 +19,9 @@ export { startActionDockServer, } from "./server/server.js";
|
|
|
19
19
|
// 6. 核心工程辅助
|
|
20
20
|
export { initProject } from "./project/init.js";
|
|
21
21
|
export { loadProjectConfig, findProjectRoot, } from "./project/loader.js";
|
|
22
|
+
export { ensureProjectDependencies, } from "./project/dependencies.js";
|
|
22
23
|
// 8. 统一错误模型与核心标准错误码常量
|
|
23
|
-
export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, CONFIG_VALUE_INVALID, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, NOT_FOUND, SERVER_ERROR, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, PROCESS_FAILED, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, PROJECT_ROOT_NOT_FOUND, describeActionLoadFailure, createErrorEnvelope, resolveExecutionHint, } from "./errors.js";
|
|
24
|
+
export { ActionDockError, ProcessError, PACKAGE_NOT_FOUND, ACTION_PACKAGE_VERSION_CONFLICT, ACTION_NOT_FOUND, ACTION_LOAD_FAILED, ACTION_FAILED, ACTION_TIMEOUT, ACTION_CANCELLED, CONFIG_VALUE_INVALID, INPUT_VALIDATION_FAILED, OUTPUT_VALIDATION_FAILED, INPUT_NOT_JSON, OUTPUT_NOT_JSON, ACTION_SUBRUN_LIMIT, ACTION_CALL_CYCLE, UNDECLARED_ACTION_DEPENDENCY, INVALID_ACTION_REF, IDEMPOTENCY_CONFLICT, EXECUTION_FAILED, UNHANDLED_EXECUTION_ERROR, RUN_REPOSITORY_UNAVAILABLE, RUN_PERSISTENCE_FAILED, STANDALONE_ASYNC_UNSUPPORTED, HOST_PROCESS_EXITED, EXECUTION_ABORTED, TIMEOUT, NETWORK_ERROR, CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND, STORAGE_BUSY, DEPENDENCIES_NOT_READY, DEPENDENCY_INSTALL_FAILED, PROJECT_BUSY, PROJECT_RECOVERY_REQUIRED, EVENT_BACKPRESSURE_LIMIT, EVENT_CURSOR_EXPIRED, PROCESS_OUTPUT_LIMIT, PROCESS_SPAWN_ERROR, PROCESS_CANCELLED, PROCESS_TIMEOUT, UNAUTHORIZED, CONFIG_ENCRYPTION_ERROR, CONFIG_DECRYPT_FAILED, NOT_FOUND, SERVER_ERROR, PACKAGE_FORBIDDEN, ACTION_FORBIDDEN, PLAYBOOK_NOT_FOUND, REQUEST_TOO_LARGE, ACTION_START_FAILED, ACTION_EXECUTION_ERROR, DATA_DIR_IN_USE, DATA_DIR_RECOVERY_REQUIRED, PROCESS_FAILED, MCP_TOOL_NAME_COLLISION, ACCESS_DENIED, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, INVALID_ARGUMENT, PACKAGE_NOT_ALLOWED, INVALID_PACKAGE_ID, PATH_TRAVERSAL, AMBIGUOUS_STATE_KEY, RUN_NOT_FOUND, RUN_ALREADY_FINISHED, PROJECT_ROOT_NOT_FOUND, describeActionLoadFailure, createErrorEnvelope, resolveExecutionHint, } from "./errors.js";
|
|
25
|
+
// 一次性工程命令执行工具
|
|
26
|
+
export { executeCommand } from "./process/command-executor.js";
|
|
27
|
+
export { createConfigKeyProvider } from "./security/config-key.js";
|
|
@@ -4,6 +4,29 @@ import { createPackageIdentity, type PackageIdentity } from "../runtime/identity
|
|
|
4
4
|
export { createPackageIdentity };
|
|
5
5
|
export type { PackageIdentity };
|
|
6
6
|
export type { RunOptions } from "../service/types.js";
|
|
7
|
+
/**
|
|
8
|
+
* 本地包准备目标契约。
|
|
9
|
+
*/
|
|
10
|
+
export interface LocalPackagePreparationTarget {
|
|
11
|
+
/** 目标包物理与快照身份标识 */
|
|
12
|
+
readonly identity: PackageIdentity;
|
|
13
|
+
/** 目标包物理根路径 */
|
|
14
|
+
readonly packageRoot: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 本地包准备上下文契约。
|
|
18
|
+
*/
|
|
19
|
+
export interface LocalPackagePreparationContext {
|
|
20
|
+
/** 取消信号 */
|
|
21
|
+
readonly signal: AbortSignal;
|
|
22
|
+
/** 根运行标识(用于在途合并与调用链追踪) */
|
|
23
|
+
readonly rootRunId: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 本地包准备协调器回调契约。
|
|
27
|
+
* 在本地 Action 实际执行前触发调用,确保包运行环境与依赖就绪。
|
|
28
|
+
*/
|
|
29
|
+
export type LocalPackagePreparer = (target: LocalPackagePreparationTarget, context: LocalPackagePreparationContext) => Promise<void>;
|
|
7
30
|
/**
|
|
8
31
|
* 构造默认进程归属所有者(ProcessOwner)的单一事实源工厂。
|
|
9
32
|
*
|
|
@@ -57,6 +80,10 @@ export interface InvocationContext {
|
|
|
57
80
|
readonly signal: AbortSignal;
|
|
58
81
|
/** 超时毫秒数 */
|
|
59
82
|
readonly timeoutMs?: number;
|
|
83
|
+
/** 初始超时毫秒数(原始预算) */
|
|
84
|
+
readonly initialTimeoutMs?: number;
|
|
85
|
+
/** 绝对超时时间戳 */
|
|
86
|
+
readonly deadline?: number;
|
|
60
87
|
/** 配置覆盖项 */
|
|
61
88
|
readonly config?: Record<string, unknown>;
|
|
62
89
|
/** 幂等请求标识 */
|
|
@@ -105,6 +132,10 @@ export interface CreateRootInvocationContextOptions {
|
|
|
105
132
|
signal?: AbortSignal;
|
|
106
133
|
/** 最大超时时间(毫秒) */
|
|
107
134
|
timeoutMs?: number;
|
|
135
|
+
/** 初始超时毫秒数(原始预算) */
|
|
136
|
+
initialTimeoutMs?: number;
|
|
137
|
+
/** 绝对超时时间戳 */
|
|
138
|
+
deadline?: number;
|
|
108
139
|
/** 执行级临时配置覆盖字典 */
|
|
109
140
|
config?: Record<string, unknown>;
|
|
110
141
|
/** 幂等请求标识 */
|
package/dist/invocation/types.js
CHANGED
|
@@ -35,6 +35,8 @@ export function createInvocationContext(options) {
|
|
|
35
35
|
package: pkg,
|
|
36
36
|
signal: options.signal ?? new AbortController().signal,
|
|
37
37
|
timeoutMs: options.timeoutMs,
|
|
38
|
+
initialTimeoutMs: options.initialTimeoutMs,
|
|
39
|
+
deadline: options.deadline,
|
|
38
40
|
config: options.config,
|
|
39
41
|
requestId: options.requestId,
|
|
40
42
|
tenantId: options.tenantId,
|
|
@@ -64,11 +66,16 @@ export function createInvocationContext(options) {
|
|
|
64
66
|
* parentRunId 与 caller 为 undefined,并按根调用契约挑选字段,保持无血缘血缘字段的键序不变。
|
|
65
67
|
*/
|
|
66
68
|
export function createRootInvocationContext(options) {
|
|
69
|
+
const initialTimeoutMs = options.initialTimeoutMs ?? (typeof options.timeoutMs === "number" && options.timeoutMs > 0 ? options.timeoutMs : undefined);
|
|
70
|
+
const deadline = options.deadline ?? (initialTimeoutMs !== undefined ? Date.now() + initialTimeoutMs : undefined);
|
|
71
|
+
const remainingBudget = deadline !== undefined ? Math.max(0, deadline - Date.now()) : options.timeoutMs;
|
|
67
72
|
const base = createInvocationContext({
|
|
68
73
|
package: options.targetPackage,
|
|
69
74
|
callStack: options.callStack,
|
|
70
75
|
signal: options.signal,
|
|
71
|
-
timeoutMs:
|
|
76
|
+
timeoutMs: remainingBudget,
|
|
77
|
+
initialTimeoutMs,
|
|
78
|
+
deadline,
|
|
72
79
|
config: options.config,
|
|
73
80
|
requestId: options.requestId,
|
|
74
81
|
hostSessionId: options.hostSessionId,
|
|
@@ -90,6 +97,8 @@ export function createRootInvocationContext(options) {
|
|
|
90
97
|
package: base.package,
|
|
91
98
|
signal: base.signal,
|
|
92
99
|
timeoutMs: base.timeoutMs,
|
|
100
|
+
initialTimeoutMs: base.initialTimeoutMs,
|
|
101
|
+
deadline: base.deadline,
|
|
93
102
|
config: base.config,
|
|
94
103
|
requestId: base.requestId,
|
|
95
104
|
hostSessionId: base.hostSessionId,
|
package/dist/package/index.d.ts
CHANGED
|
@@ -19,4 +19,4 @@ export type { ProcessAPI as ProcessExecutor } from "@actiondock/sdk";
|
|
|
19
19
|
export type { ProcessDriver, ProcessDriverCallbacks, ProcessDriverHandle, ProcessHandle, ProcessObserver, } from "../process/driver.js";
|
|
20
20
|
export { createStorage, resolveDatabasePath, } from "../storage/index.js";
|
|
21
21
|
export { SqliteRuntimeStorage } from "../storage/sqlite.js";
|
|
22
|
-
export type { RuntimeStorage, SqliteDriver, StateEntry, } from "../storage/types.js";
|
|
22
|
+
export type { RuntimeStorage, SqliteDriver, StateEntry, ConfigWriteOptions, ConfigSnapshot, } from "../storage/types.js";
|
package/dist/package/runtime.js
CHANGED
|
@@ -6,6 +6,7 @@ import { findProjectRoot, loadProjectConfig } from "../project/loader.js";
|
|
|
6
6
|
import { RuntimeConfig } from "../runtime/context.js";
|
|
7
7
|
import { normalizeActionCollection } from "../runtime/action-collection.js";
|
|
8
8
|
import { redactConfigValue, sanitizeConfigDefinitions } from "../storage/mask.js";
|
|
9
|
+
import { redactConfigValueWithProtection } from "../storage/index.js";
|
|
9
10
|
import { assertConcreteConfigKey, assertValidConfigDeclarations, isConfigTemplate, resolveConfigDeclaration, validateConfigValue, } from "../project/config-declarations.js";
|
|
10
11
|
import { decodeStateKey, SqliteRuntimeStorage } from "../storage/sqlite.js";
|
|
11
12
|
import { createPackageIdentity } from "../runtime/identity.js";
|
|
@@ -239,6 +240,7 @@ export class DefaultPackageRuntime {
|
|
|
239
240
|
}
|
|
240
241
|
/** 构造包存储工厂选项(单一事实源,异步与同步打开路径共用) */
|
|
241
242
|
buildStorageOptions() {
|
|
243
|
+
const config = this.projectConfig?.config;
|
|
242
244
|
return {
|
|
243
245
|
projectRoot: this.packageRoot,
|
|
244
246
|
dataDir: this.options.dataDir,
|
|
@@ -247,6 +249,9 @@ export class DefaultPackageRuntime {
|
|
|
247
249
|
// 默认持有者语义:App 主路径打开时收割死亡会话遗留非终态运行记录;
|
|
248
250
|
// CLI 查询旁观视图显式置 recoverOrphans: false 跳过收割
|
|
249
251
|
recoverOrphans: this.options.recoverOrphans !== false,
|
|
252
|
+
// 供旧版本库自动迁移判定敏感性(各字典内具体键优先于模板);
|
|
253
|
+
// 仅在库需要迁移时被读取,不引入新的生命周期
|
|
254
|
+
...(config && Object.keys(config).length > 0 ? { configDeclarations: [config] } : {}),
|
|
250
255
|
};
|
|
251
256
|
}
|
|
252
257
|
/**
|
|
@@ -300,12 +305,15 @@ export class DefaultPackageRuntime {
|
|
|
300
305
|
this.globalStorageRes = { kind: "own", storage };
|
|
301
306
|
return storage;
|
|
302
307
|
}
|
|
308
|
+
const config = this.projectConfig?.config;
|
|
303
309
|
const globalOpts = {
|
|
304
310
|
customHome: this.options.customHome,
|
|
305
311
|
dataDir: this.options.dataDir,
|
|
306
312
|
inMemory: this.options.inMemory,
|
|
307
313
|
// 与主存储保持同侧收割语义(全局库 runs 表为空集,收割无实际副作用)
|
|
308
314
|
recoverOrphans: this.options.recoverOrphans !== false,
|
|
315
|
+
// 独立全局库迁移以当前包声明为并集口径;Host 共享路径由 Host 汇集全部已加载包声明
|
|
316
|
+
...(config && Object.keys(config).length > 0 ? { configDeclarations: [config] } : {}),
|
|
309
317
|
};
|
|
310
318
|
const storage = this.platform.storage.createGlobalStorage(globalOpts);
|
|
311
319
|
this.globalStorageRes = { kind: "own", storage };
|
|
@@ -708,12 +716,16 @@ export class DefaultPackageRuntime {
|
|
|
708
716
|
this.assertOpen();
|
|
709
717
|
assertConcreteConfigKey(key);
|
|
710
718
|
const decl = resolveConfigDeclaration(this.projectConfig.config, key);
|
|
711
|
-
// 委托 RuntimeConfig
|
|
712
|
-
const resolved = this.ensureRuntimeConfig().
|
|
719
|
+
// 委托 RuntimeConfig 五层优先级链单一事实源,取值与历史保护声明同链原子解析
|
|
720
|
+
const resolved = this.ensureRuntimeConfig().describeWithProtection(key);
|
|
713
721
|
// configured 显式判定:仅真实显式来源(override/package/global/env)为 true,
|
|
714
722
|
// default 与整链未命中(source null)均为 false,不得依赖与 "default" 的不等比较
|
|
715
723
|
const configured = resolved.source !== null && resolved.source !== "default";
|
|
716
|
-
|
|
724
|
+
// 当前声明与存储持久化的历史保护声明合并脱敏:删除或弱化声明后仍保持既有保护;
|
|
725
|
+
// 无历史保护时沿用单声明脱敏原语,保持既有视图行为不变
|
|
726
|
+
const redacted = resolved.protection !== undefined
|
|
727
|
+
? redactConfigValueWithProtection(resolved.value, decl?.item ? [decl.item] : [], resolved.protection)
|
|
728
|
+
: redactConfigValue(resolved.value, decl?.item);
|
|
717
729
|
return {
|
|
718
730
|
key,
|
|
719
731
|
configured,
|
|
@@ -728,7 +740,9 @@ export class DefaultPackageRuntime {
|
|
|
728
740
|
assertConcreteConfigKey(key);
|
|
729
741
|
const decl = resolveConfigDeclaration(this.projectConfig.config, key);
|
|
730
742
|
validateConfigValue(key, value, decl?.item);
|
|
731
|
-
|
|
743
|
+
// 传递当前有效声明(具体键优先于模板解析结果),
|
|
744
|
+
// 由存储统一判定整键加密并合并历史保护,禁止保护弱化
|
|
745
|
+
await (await this.prepareStorageAsync()).setConfig(key, value, decl?.item ? { declarations: [decl.item] } : undefined);
|
|
732
746
|
}
|
|
733
747
|
async deleteConfig(key) {
|
|
734
748
|
this.assertOpen();
|
package/dist/platform/node.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { type ModuleLoader } from "./module-loader.js";
|
|
|
4
4
|
import { ProcessManager } from "../process/process-manager.js";
|
|
5
5
|
import type { ProcessDriver } from "../process/driver.js";
|
|
6
6
|
import { type SqliteDriver } from "../storage/index.js";
|
|
7
|
+
import type { ConfigKeyProvider } from "../security/config-cipher.js";
|
|
7
8
|
import type { EventSink } from "../runtime/events.js";
|
|
8
9
|
import type { RuntimePlatform, StorageFactory } from "./types.js";
|
|
9
10
|
/**
|
|
@@ -35,6 +36,11 @@ export interface NodePlatformOptions {
|
|
|
35
36
|
clock?: Clock;
|
|
36
37
|
/** 自定义存储工厂(默认基于 NodeSqliteDriver 构造) */
|
|
37
38
|
storage?: StorageFactory;
|
|
39
|
+
/**
|
|
40
|
+
* 显式注入的配置加密密钥提供器:优先于由有效 customHome/dataDir 派生的默认提供器,
|
|
41
|
+
* 显式注入时对内存库同样生效(供测试注入固定密钥)。
|
|
42
|
+
*/
|
|
43
|
+
configKeyProvider?: ConfigKeyProvider;
|
|
38
44
|
/** 可选注入的执行事件接收器 */
|
|
39
45
|
eventSink?: EventSink;
|
|
40
46
|
/** 可选注入的统一日志记录器 */
|
package/dist/platform/node.js
CHANGED
|
@@ -7,6 +7,7 @@ import { NodeProcessDriver } from "../process/process-driver.js";
|
|
|
7
7
|
import { ProcessManager } from "../process/process-manager.js";
|
|
8
8
|
import { NodeSqliteDriver } from "../storage/sqlite-driver.js";
|
|
9
9
|
import { resolveDatabasePath, resolveGlobalDatabasePath, SqliteRuntimeStorage, } from "../storage/index.js";
|
|
10
|
+
import { createConfigKeyProvider } from "../security/config-key.js";
|
|
10
11
|
function ensureDirectoryForDb(dbPath) {
|
|
11
12
|
if (dbPath !== ":memory:") {
|
|
12
13
|
const dir = dirname(dbPath);
|
|
@@ -72,43 +73,85 @@ export function createNodePlatform(options = {}) {
|
|
|
72
73
|
return cachedModules;
|
|
73
74
|
};
|
|
74
75
|
const createDriver = options.driverFactory ?? ((dbPath) => new NodeSqliteDriver(dbPath));
|
|
76
|
+
// - 配置加密密钥提供器按每次建库时的有效路径派生:密钥必须与数据库共享同一
|
|
77
|
+
// dataDir/customHome 域,禁止密钥落真实 home 而数据库在别处(或反向)。
|
|
78
|
+
// 提供器懒加载:仅构造平台或读取普通配置不创建 keys 目录;
|
|
79
|
+
// 内存库不注入派生提供器,由存储使用随机内存密钥,即使环境提供密钥也不触真实密钥源;
|
|
80
|
+
// 显式注入的测试提供器对内存库保留生效。
|
|
81
|
+
const resolveConfigKeyProvider = (dbPath, effectiveCustomHome, effectiveDataDir) => {
|
|
82
|
+
if (options.configKeyProvider) {
|
|
83
|
+
return options.configKeyProvider;
|
|
84
|
+
}
|
|
85
|
+
if (dbPath === ":memory:") {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
return createConfigKeyProvider({
|
|
89
|
+
customHome: effectiveCustomHome,
|
|
90
|
+
dataDir: effectiveDataDir,
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
// - 自建驱动构造失败时释放句柄:SqliteRuntimeStorage 将注入 driver 视为外部资源,
|
|
94
|
+
// 构造抛出不会代为关闭,此处回收驱动,避免锁泄漏后原样透传错误
|
|
95
|
+
const createStorageWithDriverCleanup = (build, dbPath) => {
|
|
96
|
+
const driver = createDriver(dbPath);
|
|
97
|
+
try {
|
|
98
|
+
return build(driver);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
try {
|
|
102
|
+
driver.close();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// 忽略清理阶段副异常,确保原始错误优先透传
|
|
106
|
+
}
|
|
107
|
+
throw err;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
75
110
|
const storage = options.storage ?? {
|
|
76
111
|
createStorage(packageId, opts) {
|
|
112
|
+
// 显式 opts 中的 undefined 不得覆盖平台级路径:密钥与数据库必须解析同一有效路径
|
|
113
|
+
const effectiveCustomHome = opts?.customHome ?? options.customHome;
|
|
114
|
+
const effectiveDataDir = opts?.dataDir ?? options.dataDir;
|
|
77
115
|
const mergedOpts = {
|
|
78
|
-
customHome:
|
|
79
|
-
dataDir:
|
|
80
|
-
|
|
116
|
+
customHome: effectiveCustomHome,
|
|
117
|
+
dataDir: effectiveDataDir,
|
|
118
|
+
inMemory: opts?.inMemory,
|
|
119
|
+
projectRoot: opts?.projectRoot,
|
|
81
120
|
};
|
|
82
121
|
const dbPath = resolveDatabasePath(packageId, mergedOpts);
|
|
83
122
|
ensureDirectoryForDb(dbPath);
|
|
84
|
-
|
|
123
|
+
const configKeyProvider = resolveConfigKeyProvider(dbPath, effectiveCustomHome, effectiveDataDir);
|
|
124
|
+
return createStorageWithDriverCleanup((driver) => new SqliteRuntimeStorage({
|
|
85
125
|
dbPath,
|
|
86
126
|
packageId,
|
|
87
127
|
clock,
|
|
88
|
-
driver
|
|
128
|
+
driver,
|
|
89
129
|
recoverOrphans: opts?.recoverOrphans === true,
|
|
90
130
|
retentionPolicy: opts?.retentionPolicy,
|
|
91
131
|
logger: options.logger,
|
|
92
|
-
|
|
132
|
+
...(configKeyProvider ? { configKeyProvider } : {}),
|
|
133
|
+
...(opts?.configDeclarations?.length ? { configDeclarations: opts.configDeclarations } : {}),
|
|
134
|
+
}), dbPath);
|
|
93
135
|
},
|
|
94
136
|
createGlobalStorage(opts) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
};
|
|
100
|
-
const dbPath = mergedOpts.inMemory
|
|
137
|
+
const effectiveCustomHome = opts?.customHome ?? options.customHome;
|
|
138
|
+
const effectiveDataDir = opts?.dataDir ?? options.dataDir;
|
|
139
|
+
const inMemory = Boolean(opts?.inMemory);
|
|
140
|
+
const dbPath = inMemory
|
|
101
141
|
? ":memory:"
|
|
102
|
-
: resolveGlobalDatabasePath({ dataDir:
|
|
142
|
+
: resolveGlobalDatabasePath({ dataDir: effectiveDataDir, customHome: effectiveCustomHome });
|
|
103
143
|
ensureDirectoryForDb(dbPath);
|
|
104
|
-
|
|
144
|
+
const configKeyProvider = resolveConfigKeyProvider(dbPath, effectiveCustomHome, effectiveDataDir);
|
|
145
|
+
return createStorageWithDriverCleanup((driver) => new SqliteRuntimeStorage({
|
|
105
146
|
dbPath,
|
|
106
147
|
packageId: "__global__",
|
|
107
148
|
clock,
|
|
108
|
-
driver
|
|
149
|
+
driver,
|
|
109
150
|
recoverOrphans: opts?.recoverOrphans === true,
|
|
110
151
|
logger: options.logger,
|
|
111
|
-
|
|
152
|
+
...(configKeyProvider ? { configKeyProvider } : {}),
|
|
153
|
+
...(opts?.configDeclarations?.length ? { configDeclarations: opts.configDeclarations } : {}),
|
|
154
|
+
}), dbPath);
|
|
112
155
|
},
|
|
113
156
|
};
|
|
114
157
|
const platform = {
|
package/dist/platform/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { ModuleLoader } from "./module-loader.js";
|
|
|
4
4
|
import type { RunsRetentionPolicy, RuntimeStorage } from "../storage/types.js";
|
|
5
5
|
import type { EventSink } from "../runtime/events.js";
|
|
6
6
|
import type { PackageRuntime } from "../package/types.js";
|
|
7
|
+
import type { ConfigItemDefinition } from "../project/types.js";
|
|
7
8
|
/**
|
|
8
9
|
* 跨运行时持久化存储工厂配置选项。
|
|
9
10
|
*/
|
|
@@ -19,6 +20,11 @@ export interface StorageFactoryOptions {
|
|
|
19
20
|
recoverOrphans?: boolean;
|
|
20
21
|
/** 运行记录保留策略配置 */
|
|
21
22
|
retentionPolicy?: RunsRetentionPolicy;
|
|
23
|
+
/**
|
|
24
|
+
* 供旧版本数据库迁移判定的配置声明字典集合(包级存储传当前包声明)。
|
|
25
|
+
* 仅在库需要迁移时被读取;版本迁移只在首次打开执行。
|
|
26
|
+
*/
|
|
27
|
+
configDeclarations?: readonly Record<string, ConfigItemDefinition>[];
|
|
22
28
|
}
|
|
23
29
|
/**
|
|
24
30
|
* 跨运行时全局存储工厂配置选项。
|
|
@@ -29,6 +35,11 @@ export interface GlobalStorageFactoryOptions {
|
|
|
29
35
|
customHome?: string;
|
|
30
36
|
/** 是否以持有者身份打开并收割遗留非终态运行记录(默认 false,旁观语义) */
|
|
31
37
|
recoverOrphans?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* 供旧版本全局库迁移判定的配置声明字典集合(通常为所有已加载包的声明并集)。
|
|
40
|
+
* 仅在库需要迁移时被读取;版本迁移只在首次打开执行。
|
|
41
|
+
*/
|
|
42
|
+
configDeclarations?: readonly Record<string, ConfigItemDefinition>[];
|
|
32
43
|
}
|
|
33
44
|
/**
|
|
34
45
|
* 跨运行时持久化存储工厂契约。
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ProcessDriver } from "./driver.js";
|
|
2
|
+
/**
|
|
3
|
+
* 工程工具命令执行配置选项。
|
|
4
|
+
*/
|
|
5
|
+
export interface ExecuteCommandOptions {
|
|
6
|
+
cwd?: string;
|
|
7
|
+
env?: Record<string, string | undefined>;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
maxOutputBytes?: number;
|
|
11
|
+
onOutput?: (stream: "stdout" | "stderr", text: string) => void;
|
|
12
|
+
driver?: ProcessDriver;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 工程工具命令执行结果。
|
|
16
|
+
*/
|
|
17
|
+
export interface CommandExecutionResult {
|
|
18
|
+
status: number | null;
|
|
19
|
+
signal: string | null;
|
|
20
|
+
stdout: string;
|
|
21
|
+
stderr: string;
|
|
22
|
+
truncated: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 面向工程工具的一次性命令适配执行器。
|
|
26
|
+
*
|
|
27
|
+
* 核心设计契约:
|
|
28
|
+
* - 复用底层 ProcessDriver 平台驱动,严格保持进程组隔离与进程树收敛能力;
|
|
29
|
+
* - 绝不启用系统 Shell,参数列表原样透传,杜绝命令注入与参数转义漏洞;
|
|
30
|
+
* - 默认每流上限 512KiB 字节有界捕获,超出上限继续排空或转发并置 truncated 标志;
|
|
31
|
+
* - 捕获字节独立深拷贝,脱离原始底层缓冲区以防内存滞留与复用篡改;
|
|
32
|
+
* - 仅当显式指定 onOutput 时流式转发,严格保证跨分块 UTF-8 字符解码完整性;
|
|
33
|
+
* - 规范化取消、超时与异常收敛:等待 driver.terminate 与 outputClosed 终态后抛出结构化 ProcessError。
|
|
34
|
+
*/
|
|
35
|
+
export declare function executeCommand(executable: string, args: readonly string[], options?: ExecuteCommandOptions): Promise<CommandExecutionResult>;
|