@actiondock/core 2.7.0 → 2.9.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/README.md +77 -64
- package/dist/catalog/action-catalog.d.ts +56 -0
- package/dist/catalog/action-catalog.js +202 -0
- package/dist/catalog/discovery.d.ts +60 -0
- package/dist/catalog/discovery.js +119 -0
- package/dist/catalog/graph.d.ts +190 -0
- package/dist/catalog/graph.js +589 -0
- package/dist/catalog/index.d.ts +5 -5
- package/dist/catalog/index.js +5 -5
- package/dist/catalog/resolve-action.d.ts +43 -0
- package/dist/catalog/resolve-action.js +119 -0
- package/dist/catalog/resolve-playbook.d.ts +26 -0
- package/dist/catalog/resolve-playbook.js +114 -0
- package/dist/doctor/checks/project.js +27 -8
- package/dist/doctor/checks/registry.js +2 -2
- package/dist/doctor/checks/runtime.js +34 -1
- package/dist/errors.d.ts +106 -10
- package/dist/errors.js +105 -10
- package/dist/execution/service.d.ts +18 -16
- package/dist/execution/service.js +183 -252
- package/dist/execution/types.d.ts +25 -69
- package/dist/execution/types.js +2 -1
- package/dist/filter/intent.d.ts +8 -9
- package/dist/filter/intent.js +49 -10
- package/dist/graph/index.d.ts +4 -0
- package/dist/graph/index.js +4 -0
- package/dist/host/host.d.ts +74 -32
- package/dist/host/host.js +585 -336
- package/dist/host/routing.d.ts +15 -48
- package/dist/host/routing.js +90 -153
- package/dist/host/types.d.ts +50 -17
- package/dist/index.d.ts +21 -24
- package/dist/index.js +19 -23
- package/dist/input/advice.d.ts +5 -1
- package/dist/input/advice.js +163 -214
- package/dist/input/describe.d.ts +1 -1
- package/dist/input/flat-errors.d.ts +5 -6
- package/dist/input/flat-errors.js +6 -6
- package/dist/input/flat-materializer.js +42 -44
- package/dist/invocation/index.d.ts +2 -0
- package/dist/invocation/index.js +2 -0
- package/dist/invocation/policy.d.ts +157 -0
- package/dist/invocation/policy.js +231 -0
- package/dist/invocation/types.d.ts +172 -0
- package/dist/invocation/types.js +97 -0
- package/dist/ipc/diagnostic.d.ts +0 -12
- package/dist/ipc/diagnostic.js +0 -21
- package/dist/ipc/host.d.ts +4 -4
- package/dist/ipc/host.js +44 -47
- package/dist/ipc/index.d.ts +1 -1
- package/dist/ipc/index.js +1 -1
- package/dist/ipc/service.d.ts +40 -0
- package/dist/ipc/service.js +349 -0
- package/dist/ipc/types.d.ts +21 -15
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +1 -0
- package/dist/node/module-loader.d.ts +63 -0
- package/dist/node/module-loader.js +112 -0
- package/dist/package/index.d.ts +23 -0
- package/dist/package/index.js +18 -0
- package/dist/{app/app.d.ts → package/runtime.d.ts} +41 -20
- package/dist/{app/app.js → package/runtime.js} +140 -95
- package/dist/{app → package}/static-index.js +58 -41
- package/dist/package/storage-view.d.ts +13 -0
- package/dist/package/storage-view.js +22 -0
- package/dist/{app → package}/types.d.ts +76 -57
- package/dist/package/types.js +22 -0
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.js +1 -1
- package/dist/platform/node.d.ts +48 -0
- package/dist/platform/node.js +96 -0
- package/dist/platform/types.d.ts +0 -9
- package/dist/process/control-arbiter.d.ts +2 -1
- package/dist/process/control-arbiter.js +1 -2
- package/dist/process/driver.d.ts +9 -8
- package/dist/process/driver.js +11 -22
- package/dist/process/index.d.ts +2 -0
- package/dist/process/index.js +2 -0
- package/dist/process/managed-record.d.ts +2 -2
- package/dist/process/process-driver.d.ts +109 -0
- package/dist/process/process-driver.js +650 -0
- package/dist/process/process-executor.d.ts +47 -0
- package/dist/process/process-executor.js +296 -0
- package/dist/process/process-manager.js +48 -26
- package/dist/process/run-executor.js +12 -12
- package/dist/profile/client-actions.js +2 -2
- package/dist/profile/client-health.js +2 -2
- package/dist/profile/client-query.js +5 -6
- package/dist/profile/client-transport.d.ts +19 -17
- package/dist/profile/client-transport.js +47 -80
- package/dist/profile/client.d.ts +2 -2
- package/dist/profile/client.js +1 -1
- package/dist/profile/index.d.ts +1 -0
- package/dist/profile/index.js +1 -0
- package/dist/profile/manager.d.ts +5 -0
- package/dist/profile/manager.js +41 -6
- package/dist/project/closure.js +2 -2
- package/dist/project/index.d.ts +8 -1
- package/dist/project/index.js +10 -1
- package/dist/project/init.js +2 -2
- package/dist/project/loader.d.ts +1 -1
- package/dist/project/loader.js +26 -29
- package/dist/project/transactions.js +5 -10
- package/dist/project/types.d.ts +5 -0
- package/dist/registry/index.d.ts +3 -1
- package/dist/registry/index.js +2 -1
- package/dist/registry/lock.d.ts +28 -7
- package/dist/registry/lock.js +136 -16
- package/dist/registry/registry.d.ts +1 -5
- package/dist/registry/registry.js +1 -53
- package/dist/registry/scan.d.ts +0 -15
- package/dist/registry/scan.js +0 -59
- package/dist/registry/store.d.ts +42 -0
- package/dist/registry/store.js +43 -0
- package/dist/registry/types.d.ts +0 -24
- package/dist/runtime/action-collection.d.ts +1 -1
- package/dist/runtime/action-registry.d.ts +0 -4
- package/dist/runtime/action-registry.js +0 -7
- package/dist/runtime/context.js +5 -11
- package/dist/runtime/events.js +3 -6
- package/dist/runtime/identity.d.ts +22 -0
- package/dist/runtime/identity.js +10 -0
- package/dist/runtime/index.d.ts +1 -2
- package/dist/runtime/index.js +1 -2
- package/dist/runtime/module-loader.d.ts +2 -34
- package/dist/runtime/module-loader.js +1 -16
- package/dist/runtime/process.d.ts +6 -24
- package/dist/runtime/process.js +1 -118
- package/dist/runtime/run-persistence.js +2 -5
- package/dist/runtime/runner.d.ts +33 -93
- package/dist/runtime/runner.js +132 -364
- package/dist/runtime/standalone.d.ts +23 -8
- package/dist/runtime/standalone.js +100 -147
- package/dist/server/body.d.ts +16 -8
- package/dist/server/body.js +33 -16
- package/dist/server/dispatcher.d.ts +6 -10
- package/dist/server/dispatcher.js +24 -32
- package/dist/server/http-server.d.ts +87 -0
- package/dist/server/http-server.js +304 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.js +11 -0
- package/dist/server/mcp-endpoint.d.ts +61 -0
- package/dist/server/mcp-endpoint.js +118 -0
- package/dist/server/policy.d.ts +138 -0
- package/dist/server/policy.js +368 -0
- package/dist/server/routes/actions.js +114 -64
- package/dist/server/routes/common.d.ts +18 -33
- package/dist/server/routes/common.js +45 -65
- package/dist/server/routes/config.d.ts +1 -1
- package/dist/server/routes/config.js +55 -65
- package/dist/server/routes/doctor.d.ts +1 -1
- package/dist/server/routes/doctor.js +13 -21
- package/dist/server/routes/health.d.ts +1 -1
- package/dist/server/routes/health.js +4 -5
- package/dist/server/routes/info.d.ts +2 -2
- package/dist/server/routes/info.js +17 -24
- package/dist/server/routes/playbooks.js +23 -36
- package/dist/server/routes/runs.js +151 -141
- package/dist/server/routes/state.d.ts +1 -1
- package/dist/server/routes/state.js +64 -63
- package/dist/server/security.d.ts +11 -0
- package/dist/server/security.js +36 -19
- package/dist/server/server.d.ts +2 -2
- package/dist/server/server.js +224 -238
- package/dist/server/types.d.ts +68 -21
- package/dist/service/factory.d.ts +12 -0
- package/dist/service/factory.js +85 -0
- package/dist/{target → service}/index.d.ts +1 -1
- package/dist/{target → service}/index.js +1 -1
- package/dist/service/local.d.ts +27 -0
- package/dist/service/local.js +138 -0
- package/dist/{target → service}/remote-errors.d.ts +3 -6
- package/dist/service/remote-errors.js +38 -0
- package/dist/{target → service}/remote-polling.d.ts +2 -2
- package/dist/{target → service}/remote-polling.js +8 -8
- package/dist/service/remote.d.ts +34 -0
- package/dist/service/remote.js +634 -0
- package/dist/service/sse-stream.d.ts +24 -0
- package/dist/service/sse-stream.js +139 -0
- package/dist/service/types.d.ts +272 -0
- package/dist/service/types.js +32 -0
- package/dist/storage/data-dir-lock.js +10 -5
- package/dist/storage/driver.d.ts +2 -1
- package/dist/storage/driver.js +3 -52
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +1 -0
- package/dist/storage/lock-core.d.ts +2 -6
- package/dist/storage/lock-core.js +4 -17
- package/dist/storage/params.d.ts +2 -8
- package/dist/storage/params.js +2 -8
- package/dist/storage/sqlite-driver.d.ts +40 -0
- package/dist/storage/sqlite-driver.js +116 -0
- package/dist/storage/sqlite.js +21 -6
- package/dist/storage/types.d.ts +4 -4
- package/dist/storage/types.js +2 -2
- package/dist/utils/index.d.ts +53 -0
- package/dist/utils/index.js +99 -4
- package/dist/utils/process.d.ts +10 -0
- package/dist/utils/process.js +21 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +41 -3
- package/dist/app/index.d.ts +0 -2
- package/dist/app/index.js +0 -2
- package/dist/app/types.js +0 -1
- package/dist/catalog/action-index.d.ts +0 -9
- package/dist/catalog/action-index.js +0 -95
- package/dist/catalog/action-resolver.d.ts +0 -20
- package/dist/catalog/action-resolver.js +0 -95
- package/dist/catalog/location-registry.d.ts +0 -15
- package/dist/catalog/location-registry.js +0 -138
- package/dist/catalog/package-catalog.d.ts +0 -7
- package/dist/catalog/package-catalog.js +0 -77
- package/dist/catalog/types.d.ts +0 -68
- package/dist/catalog/types.js +0 -1
- package/dist/export/index.d.ts +0 -1
- package/dist/export/index.js +0 -1
- package/dist/export/templates.d.ts +0 -71
- package/dist/export/templates.js +0 -635
- package/dist/ipc/target.d.ts +0 -74
- package/dist/ipc/target.js +0 -365
- package/dist/platform/default.d.ts +0 -38
- package/dist/platform/default.js +0 -78
- package/dist/project/resolver.d.ts +0 -116
- package/dist/project/resolver.js +0 -376
- package/dist/registry/resolve.d.ts +0 -62
- package/dist/registry/resolve.js +0 -195
- package/dist/runtime/execution-manager.d.ts +0 -48
- package/dist/runtime/execution-manager.js +0 -66
- package/dist/runtime/package-runner-factory.d.ts +0 -82
- package/dist/runtime/package-runner-factory.js +0 -186
- package/dist/target/local.d.ts +0 -53
- package/dist/target/local.js +0 -349
- package/dist/target/remote-errors.js +0 -51
- package/dist/target/remote.d.ts +0 -86
- package/dist/target/remote.js +0 -818
- package/dist/target/target.d.ts +0 -6
- package/dist/target/target.js +0 -37
- package/dist/target/types.d.ts +0 -261
- package/dist/target/types.js +0 -35
- /package/dist/{app → package}/static-index.d.ts +0 -0
- /package/dist/{target → service}/sse-parser.d.ts +0 -0
- /package/dist/{target → service}/sse-parser.js +0 -0
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import { decodeStateKey } from "../../storage/index.js";
|
|
2
|
-
import { CAPABILITY_UNAVAILABLE, STATE_KEY_NOT_FOUND } from "../../errors.js";
|
|
2
|
+
import { AMBIGUOUS_STATE_KEY, CAPABILITY_UNAVAILABLE, INVALID_ARGUMENT, INVALID_PACKAGE_ID, PACKAGE_NOT_ALLOWED, PACKAGE_NOT_FOUND, PATH_TRAVERSAL, STATE_CLEAR_ERROR, STATE_KEY_ERROR, STATE_KEY_NOT_FOUND, STATE_LIST_ERROR, } from "../../errors.js";
|
|
3
3
|
import { readJsonBody } from "../body.js";
|
|
4
|
-
import {
|
|
4
|
+
import { getSubPath, isManagementAllowedByPolicy, jsonResponse, resolveTargetPackageId, } from "./common.js";
|
|
5
|
+
function isClientStateError(err) {
|
|
6
|
+
return (err?.code === PACKAGE_NOT_FOUND ||
|
|
7
|
+
err?.code === INVALID_PACKAGE_ID ||
|
|
8
|
+
err?.code === PATH_TRAVERSAL ||
|
|
9
|
+
err?.code === AMBIGUOUS_STATE_KEY ||
|
|
10
|
+
err?.code === INVALID_ARGUMENT ||
|
|
11
|
+
err?.status === 400 ||
|
|
12
|
+
err?.status === 404);
|
|
13
|
+
}
|
|
5
14
|
/**
|
|
6
15
|
* 处理状态键名列表、读取、写入、删除及清空接口。
|
|
7
|
-
*
|
|
16
|
+
* 在未显式开启管理功能时返回 403 拒绝。
|
|
8
17
|
*/
|
|
9
18
|
export async function handleStateRoutes(ctx) {
|
|
10
|
-
const { req, url, pathname, corsHeaders, options,
|
|
19
|
+
const { req, url, pathname, corsHeaders, options, service, activePolicy: policy } = ctx;
|
|
11
20
|
const subpath = getSubPath(pathname);
|
|
12
21
|
const isStateRoute = subpath === "/state" ||
|
|
13
22
|
subpath.startsWith("/state/") ||
|
|
@@ -16,7 +25,7 @@ export async function handleStateRoutes(ctx) {
|
|
|
16
25
|
return null;
|
|
17
26
|
}
|
|
18
27
|
// 校验管理能力开关
|
|
19
|
-
if (
|
|
28
|
+
if (!isManagementAllowedByPolicy(policy) || !service.management?.state) {
|
|
20
29
|
return jsonResponse({
|
|
21
30
|
ok: false,
|
|
22
31
|
error: {
|
|
@@ -32,31 +41,26 @@ export async function handleStateRoutes(ctx) {
|
|
|
32
41
|
const actionParam = url.searchParams.get("action") || url.searchParams.get("actionId") || "";
|
|
33
42
|
const nsParam = url.searchParams.get("namespace") ?? undefined;
|
|
34
43
|
const prefix = url.searchParams.get("prefix") || "";
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
: (nsParam !== undefined ? nsParam : null);
|
|
43
|
-
const keys = await app.storage.listStateKeys(effectiveNs, prefix);
|
|
44
|
-
return jsonResponse({ ok: true, packageId: app.packageId, keys }, 200, corsHeaders);
|
|
44
|
+
const pkgs = await service.discovery.listPackages();
|
|
45
|
+
const targetPackageId = resolveTargetPackageId(pkgs, pkgParam, policy);
|
|
46
|
+
const keys = await service.management.state.list(targetPackageId, actionParam, {
|
|
47
|
+
namespace: nsParam,
|
|
48
|
+
prefix,
|
|
49
|
+
});
|
|
50
|
+
return jsonResponse({ ok: true, packageId: targetPackageId, keys }, 200, corsHeaders);
|
|
45
51
|
}
|
|
46
52
|
catch (err) {
|
|
47
|
-
if (err.code ===
|
|
53
|
+
if (err.code === PACKAGE_NOT_ALLOWED || err.status === 403) {
|
|
48
54
|
return jsonResponse({
|
|
49
55
|
ok: false,
|
|
50
56
|
error: {
|
|
51
|
-
code:
|
|
57
|
+
code: PACKAGE_NOT_ALLOWED,
|
|
52
58
|
message: err.message || "Package is not in the allowed package list",
|
|
53
59
|
},
|
|
54
60
|
}, 403, corsHeaders);
|
|
55
61
|
}
|
|
56
|
-
const isClient = err
|
|
57
|
-
|
|
58
|
-
err.message?.includes("escapes boundary");
|
|
59
|
-
return jsonResponse({ ok: false, error: { code: isClient ? "INVALID_ARGUMENT" : "STATE_LIST_ERROR", message: err.message } }, isClient ? 400 : 500, corsHeaders);
|
|
62
|
+
const isClient = isClientStateError(err);
|
|
63
|
+
return jsonResponse({ ok: false, error: { code: isClient ? INVALID_ARGUMENT : STATE_LIST_ERROR, message: err.message } }, isClient ? 400 : 500, corsHeaders);
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
// 2. State Clear: POST /state/clear
|
|
@@ -66,33 +70,27 @@ export async function handleStateRoutes(ctx) {
|
|
|
66
70
|
const pkgParam = url.searchParams.get("package") || url.searchParams.get("packageId") || body.package || undefined;
|
|
67
71
|
const actionParam = url.searchParams.get("action") || url.searchParams.get("actionId") || body.action || body.actionId || "";
|
|
68
72
|
const baseNs = body.namespace ?? (url.searchParams.get("namespace") || undefined);
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const app = resolveAppForPackage(pkgParam, host, target, options);
|
|
74
|
-
assertPackageAllowed(app.packageId, options);
|
|
75
|
-
const clearedCount = await app.storage.clearState({
|
|
76
|
-
namespace: effectiveNs,
|
|
73
|
+
const pkgs = await service.discovery.listPackages();
|
|
74
|
+
const targetPackageId = resolveTargetPackageId(pkgs, pkgParam, policy);
|
|
75
|
+
const clearedCount = await service.management.state.clear(targetPackageId, actionParam, {
|
|
76
|
+
namespace: baseNs,
|
|
77
77
|
all: Boolean(body.all ?? url.searchParams.get("all") === "true"),
|
|
78
78
|
prefix: body.prefix ?? (url.searchParams.get("prefix") || undefined),
|
|
79
79
|
});
|
|
80
|
-
return jsonResponse({ ok: true, packageId:
|
|
80
|
+
return jsonResponse({ ok: true, packageId: targetPackageId, clearedCount }, 200, corsHeaders);
|
|
81
81
|
}
|
|
82
82
|
catch (err) {
|
|
83
|
-
if (err.code ===
|
|
83
|
+
if (err.code === PACKAGE_NOT_ALLOWED || err.status === 403) {
|
|
84
84
|
return jsonResponse({
|
|
85
85
|
ok: false,
|
|
86
86
|
error: {
|
|
87
|
-
code:
|
|
87
|
+
code: PACKAGE_NOT_ALLOWED,
|
|
88
88
|
message: err.message || "Package is not in the allowed package list",
|
|
89
89
|
},
|
|
90
90
|
}, 403, corsHeaders);
|
|
91
91
|
}
|
|
92
|
-
const isClient = err
|
|
93
|
-
|
|
94
|
-
err.message?.includes("escapes boundary");
|
|
95
|
-
return jsonResponse({ ok: false, error: { code: isClient ? "INVALID_ARGUMENT" : "STATE_CLEAR_ERROR", message: err.message } }, isClient ? 400 : 500, corsHeaders);
|
|
92
|
+
const isClient = isClientStateError(err);
|
|
93
|
+
return jsonResponse({ ok: false, error: { code: isClient ? INVALID_ARGUMENT : STATE_CLEAR_ERROR, message: err.message } }, isClient ? 400 : 500, corsHeaders);
|
|
96
94
|
}
|
|
97
95
|
}
|
|
98
96
|
// 3. State Key CRUD: GET / PUT / POST / DELETE /state/:key
|
|
@@ -103,24 +101,26 @@ export async function handleStateRoutes(ctx) {
|
|
|
103
101
|
const pkgParam = url.searchParams.get("package") || url.searchParams.get("packageId") || undefined;
|
|
104
102
|
const actionParam = url.searchParams.get("action") || url.searchParams.get("actionId") || "";
|
|
105
103
|
const nsParam = url.searchParams.get("namespace") || undefined;
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
assertPackageAllowed(pkgParam, options);
|
|
109
|
-
}
|
|
110
|
-
const app = resolveAppForPackage(pkgParam, host, target, options);
|
|
111
|
-
assertPackageAllowed(app.packageId, options);
|
|
104
|
+
const pkgs = await service.discovery.listPackages();
|
|
105
|
+
const targetPackageId = resolveTargetPackageId(pkgs, pkgParam, policy);
|
|
112
106
|
if (req.method === "GET") {
|
|
113
|
-
const entry = await
|
|
114
|
-
|
|
107
|
+
const entry = await service.management.state.get(targetPackageId, actionParam, key, {
|
|
108
|
+
namespace: nsParam,
|
|
109
|
+
detail: true,
|
|
110
|
+
});
|
|
111
|
+
if (!entry || (typeof entry === "object" && entry.value === undefined)) {
|
|
115
112
|
return jsonResponse({ ok: false, error: { code: STATE_KEY_NOT_FOUND, message: `State key '${key}' not found` } }, 404, corsHeaders);
|
|
116
113
|
}
|
|
114
|
+
const data = typeof entry === "object" && "value" in entry
|
|
115
|
+
? entry
|
|
116
|
+
: { key, namespace: nsParam || "", value: entry, expiresAt: undefined };
|
|
117
117
|
return jsonResponse({
|
|
118
118
|
ok: true,
|
|
119
|
-
packageId:
|
|
120
|
-
key:
|
|
121
|
-
namespace:
|
|
122
|
-
value:
|
|
123
|
-
expiresAt:
|
|
119
|
+
packageId: targetPackageId,
|
|
120
|
+
key: data.key || key,
|
|
121
|
+
namespace: data.namespace ?? nsParam ?? "",
|
|
122
|
+
value: data.value,
|
|
123
|
+
expiresAt: data.expiresAt,
|
|
124
124
|
}, 200, corsHeaders);
|
|
125
125
|
}
|
|
126
126
|
if (req.method === "PUT" || req.method === "POST") {
|
|
@@ -129,40 +129,41 @@ export async function handleStateRoutes(ctx) {
|
|
|
129
129
|
const ttl = typeof body.ttl === "number" ? body.ttl : undefined;
|
|
130
130
|
const bodyAction = body.action || body.actionId || actionParam;
|
|
131
131
|
const explicitNs = body.namespace || nsParam;
|
|
132
|
-
const combinedNs = bodyAction ? (explicitNs ? `${bodyAction}:${explicitNs}` : bodyAction) : explicitNs;
|
|
133
132
|
let actualKey = key;
|
|
134
|
-
let ns =
|
|
135
|
-
if (!
|
|
133
|
+
let ns = explicitNs;
|
|
134
|
+
if (!bodyAction && !explicitNs) {
|
|
136
135
|
const decoded = decodeStateKey(key);
|
|
137
136
|
ns = decoded.namespace;
|
|
138
137
|
actualKey = decoded.key;
|
|
139
138
|
}
|
|
140
|
-
await
|
|
141
|
-
|
|
139
|
+
await service.management.state.set(targetPackageId, bodyAction, actualKey, val, {
|
|
140
|
+
namespace: ns,
|
|
141
|
+
ttl,
|
|
142
|
+
});
|
|
143
|
+
return jsonResponse({ ok: true, packageId: targetPackageId, key: actualKey, namespace: ns || bodyAction || "", message: "updated" }, 200, corsHeaders);
|
|
142
144
|
}
|
|
143
145
|
if (req.method === "DELETE") {
|
|
144
|
-
const deleted = await
|
|
146
|
+
const deleted = await service.management.state.delete(targetPackageId, actionParam, key, {
|
|
147
|
+
namespace: nsParam,
|
|
148
|
+
});
|
|
145
149
|
if (!deleted) {
|
|
146
150
|
return jsonResponse({ ok: false, error: { code: STATE_KEY_NOT_FOUND, message: `State key '${key}' not found` } }, 404, corsHeaders);
|
|
147
151
|
}
|
|
148
|
-
return jsonResponse({ ok: true, packageId:
|
|
152
|
+
return jsonResponse({ ok: true, packageId: targetPackageId, key, deleted: true }, 200, corsHeaders);
|
|
149
153
|
}
|
|
150
154
|
}
|
|
151
155
|
catch (err) {
|
|
152
|
-
if (err.code ===
|
|
156
|
+
if (err.code === PACKAGE_NOT_ALLOWED || err.status === 403) {
|
|
153
157
|
return jsonResponse({
|
|
154
158
|
ok: false,
|
|
155
159
|
error: {
|
|
156
|
-
code:
|
|
160
|
+
code: PACKAGE_NOT_ALLOWED,
|
|
157
161
|
message: err.message || "Package is not in the allowed package list",
|
|
158
162
|
},
|
|
159
163
|
}, 403, corsHeaders);
|
|
160
164
|
}
|
|
161
|
-
const isClient = err
|
|
162
|
-
|
|
163
|
-
err.message?.includes("escapes boundary") ||
|
|
164
|
-
err.message?.includes("Ambiguous state key");
|
|
165
|
-
return jsonResponse({ ok: false, error: { code: isClient ? "INVALID_ARGUMENT" : "STATE_KEY_ERROR", message: err.message } }, isClient ? 400 : 500, corsHeaders);
|
|
165
|
+
const isClient = isClientStateError(err);
|
|
166
|
+
return jsonResponse({ ok: false, error: { code: isClient ? INVALID_ARGUMENT : STATE_KEY_ERROR, message: err.message } }, isClient ? 400 : 500, corsHeaders);
|
|
166
167
|
}
|
|
167
168
|
}
|
|
168
169
|
return null;
|
|
@@ -15,6 +15,17 @@ export interface VerifyBearerTokenOptions {
|
|
|
15
15
|
/** 是否允许通过 URL 查询参数携带 Token(默认 false) */
|
|
16
16
|
allowQueryToken?: boolean;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* 从 HTTP 请求中提取 Bearer Token。
|
|
20
|
+
*
|
|
21
|
+
* 默认仅接受 HTTP 请求头: `Authorization: Bearer <token>`。
|
|
22
|
+
* 仅当 allowQueryToken 为 true 时才允许解析 URL 查询参数 `?token=<token>`。
|
|
23
|
+
*
|
|
24
|
+
* @param req 传入的 HTTP Request 对象
|
|
25
|
+
* @param allowQueryToken 是否允许从 URL 查询参数解析 Token
|
|
26
|
+
* @returns 提取出的 Token 字符串,若未携带则返回 null
|
|
27
|
+
*/
|
|
28
|
+
export declare function extractBearerToken(req: Request, allowQueryToken?: boolean): string | null;
|
|
18
29
|
/**
|
|
19
30
|
* 校验 HTTP 请求中的鉴权令牌是否有效。
|
|
20
31
|
*
|
package/dist/server/security.js
CHANGED
|
@@ -13,49 +13,66 @@ export function safeEqual(a, b) {
|
|
|
13
13
|
const aa = Buffer.from(a);
|
|
14
14
|
const bb = Buffer.from(b);
|
|
15
15
|
if (aa.length !== bb.length) {
|
|
16
|
+
// 长度不等时对自身做一次恒定时间比较,消除因长度不等提前退出带来的时序差
|
|
17
|
+
timingSafeEqual(aa, aa);
|
|
16
18
|
return false;
|
|
17
19
|
}
|
|
18
20
|
return timingSafeEqual(aa, bb);
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
21
|
-
*
|
|
23
|
+
* 从 HTTP 请求中提取 Bearer Token。
|
|
22
24
|
*
|
|
23
25
|
* 默认仅接受 HTTP 请求头: `Authorization: Bearer <token>`。
|
|
24
|
-
* 仅当
|
|
26
|
+
* 仅当 allowQueryToken 为 true 时才允许解析 URL 查询参数 `?token=<token>`。
|
|
25
27
|
*
|
|
26
28
|
* @param req 传入的 HTTP Request 对象
|
|
27
|
-
* @param
|
|
28
|
-
* @
|
|
29
|
-
* @returns 是否鉴权成功
|
|
29
|
+
* @param allowQueryToken 是否允许从 URL 查询参数解析 Token
|
|
30
|
+
* @returns 提取出的 Token 字符串,若未携带则返回 null
|
|
30
31
|
*/
|
|
31
|
-
export function
|
|
32
|
-
if (!expectedToken || !expectedToken.trim()) {
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
35
|
-
const trimmedExpected = expectedToken.trim();
|
|
32
|
+
export function extractBearerToken(req, allowQueryToken) {
|
|
36
33
|
// 1. 请求头 Authorization: Bearer <token>
|
|
37
34
|
const authHeader = req.headers.get("authorization");
|
|
38
35
|
if (authHeader && authHeader.startsWith("Bearer ")) {
|
|
39
36
|
const token = authHeader.slice(7).trim();
|
|
40
|
-
if (
|
|
41
|
-
return
|
|
42
|
-
}
|
|
37
|
+
if (token)
|
|
38
|
+
return token;
|
|
43
39
|
}
|
|
44
40
|
// 2. URL 查询参数: ?token=<token>(仅当显式开启 allowQueryToken 时允许)
|
|
45
|
-
|
|
46
|
-
if (allowQuery) {
|
|
41
|
+
if (allowQueryToken) {
|
|
47
42
|
try {
|
|
48
43
|
const url = new URL(req.url);
|
|
49
44
|
const tokenParam = url.searchParams.get("token");
|
|
50
|
-
if (tokenParam &&
|
|
51
|
-
return
|
|
45
|
+
if (tokenParam && tokenParam.trim()) {
|
|
46
|
+
return tokenParam.trim();
|
|
52
47
|
}
|
|
53
48
|
}
|
|
54
49
|
catch {
|
|
55
|
-
// 畸形 URL
|
|
50
|
+
// 畸形 URL 忽略
|
|
56
51
|
}
|
|
57
52
|
}
|
|
58
|
-
return
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 校验 HTTP 请求中的鉴权令牌是否有效。
|
|
57
|
+
*
|
|
58
|
+
* 默认仅接受 HTTP 请求头: `Authorization: Bearer <token>`。
|
|
59
|
+
* 仅当 options.allowQueryToken 为 true 时才允许解析 URL 查询参数 `?token=<token>`。
|
|
60
|
+
*
|
|
61
|
+
* @param req 传入的 HTTP Request 对象
|
|
62
|
+
* @param expectedToken 服务端预期的正确 Token(若未配置 Token 则默认放行)
|
|
63
|
+
* @param options 校验选项或布尔值 allowQueryToken 开关
|
|
64
|
+
* @returns 是否鉴权成功
|
|
65
|
+
*/
|
|
66
|
+
export function verifyBearerToken(req, expectedToken, options) {
|
|
67
|
+
if (!expectedToken || !expectedToken.trim()) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
const allowQuery = typeof options === "boolean" ? options : options?.allowQueryToken === true;
|
|
71
|
+
const token = extractBearerToken(req, allowQuery);
|
|
72
|
+
if (!token) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
return safeEqual(token, expectedToken.trim());
|
|
59
76
|
}
|
|
60
77
|
/**
|
|
61
78
|
* 根据配置的 CORS 白名单解析并返回跨域响应头。
|
package/dist/server/server.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare function formatHostForUrl(host: string): string;
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function launchHttpServer(port: number, host: string, fetchHandler: (req: Request) => Promise<Response>, tls?: ServerTlsOptions): Promise<CoreHttpServerInstance>;
|
|
11
11
|
/**
|
|
12
|
-
* 启动 ActionDock
|
|
13
|
-
*
|
|
12
|
+
* 启动 ActionDock 原生轻量级 HTTP 服务端。
|
|
13
|
+
* 面向 ActionDockService 服务端口,负责中间件流转、认证拦截与路由分发。
|
|
14
14
|
*/
|
|
15
15
|
export declare function startActionDockServer(options?: ServerOptions): Promise<ActionDockServerInstance>;
|