@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.
Files changed (243) hide show
  1. package/README.md +77 -64
  2. package/dist/catalog/action-catalog.d.ts +56 -0
  3. package/dist/catalog/action-catalog.js +202 -0
  4. package/dist/catalog/discovery.d.ts +60 -0
  5. package/dist/catalog/discovery.js +119 -0
  6. package/dist/catalog/graph.d.ts +190 -0
  7. package/dist/catalog/graph.js +589 -0
  8. package/dist/catalog/index.d.ts +5 -5
  9. package/dist/catalog/index.js +5 -5
  10. package/dist/catalog/resolve-action.d.ts +43 -0
  11. package/dist/catalog/resolve-action.js +119 -0
  12. package/dist/catalog/resolve-playbook.d.ts +26 -0
  13. package/dist/catalog/resolve-playbook.js +114 -0
  14. package/dist/doctor/checks/project.js +27 -8
  15. package/dist/doctor/checks/registry.js +2 -2
  16. package/dist/doctor/checks/runtime.js +34 -1
  17. package/dist/errors.d.ts +106 -10
  18. package/dist/errors.js +105 -10
  19. package/dist/execution/service.d.ts +18 -16
  20. package/dist/execution/service.js +183 -252
  21. package/dist/execution/types.d.ts +25 -69
  22. package/dist/execution/types.js +2 -1
  23. package/dist/filter/intent.d.ts +8 -9
  24. package/dist/filter/intent.js +49 -10
  25. package/dist/graph/index.d.ts +4 -0
  26. package/dist/graph/index.js +4 -0
  27. package/dist/host/host.d.ts +74 -32
  28. package/dist/host/host.js +585 -336
  29. package/dist/host/routing.d.ts +15 -48
  30. package/dist/host/routing.js +90 -153
  31. package/dist/host/types.d.ts +50 -17
  32. package/dist/index.d.ts +21 -24
  33. package/dist/index.js +19 -23
  34. package/dist/input/advice.d.ts +5 -1
  35. package/dist/input/advice.js +163 -214
  36. package/dist/input/describe.d.ts +1 -1
  37. package/dist/input/flat-errors.d.ts +5 -6
  38. package/dist/input/flat-errors.js +6 -6
  39. package/dist/input/flat-materializer.js +42 -44
  40. package/dist/invocation/index.d.ts +2 -0
  41. package/dist/invocation/index.js +2 -0
  42. package/dist/invocation/policy.d.ts +157 -0
  43. package/dist/invocation/policy.js +231 -0
  44. package/dist/invocation/types.d.ts +172 -0
  45. package/dist/invocation/types.js +97 -0
  46. package/dist/ipc/diagnostic.d.ts +0 -12
  47. package/dist/ipc/diagnostic.js +0 -21
  48. package/dist/ipc/host.d.ts +4 -4
  49. package/dist/ipc/host.js +44 -47
  50. package/dist/ipc/index.d.ts +1 -1
  51. package/dist/ipc/index.js +1 -1
  52. package/dist/ipc/service.d.ts +40 -0
  53. package/dist/ipc/service.js +349 -0
  54. package/dist/ipc/types.d.ts +21 -15
  55. package/dist/node/index.d.ts +1 -0
  56. package/dist/node/index.js +1 -0
  57. package/dist/node/module-loader.d.ts +63 -0
  58. package/dist/node/module-loader.js +112 -0
  59. package/dist/package/index.d.ts +23 -0
  60. package/dist/package/index.js +18 -0
  61. package/dist/{app/app.d.ts → package/runtime.d.ts} +41 -20
  62. package/dist/{app/app.js → package/runtime.js} +140 -95
  63. package/dist/{app → package}/static-index.js +58 -41
  64. package/dist/package/storage-view.d.ts +13 -0
  65. package/dist/package/storage-view.js +22 -0
  66. package/dist/{app → package}/types.d.ts +76 -57
  67. package/dist/package/types.js +22 -0
  68. package/dist/platform/index.d.ts +1 -1
  69. package/dist/platform/index.js +1 -1
  70. package/dist/platform/node.d.ts +48 -0
  71. package/dist/platform/node.js +96 -0
  72. package/dist/platform/types.d.ts +0 -9
  73. package/dist/process/control-arbiter.d.ts +2 -1
  74. package/dist/process/control-arbiter.js +1 -2
  75. package/dist/process/driver.d.ts +9 -8
  76. package/dist/process/driver.js +11 -22
  77. package/dist/process/index.d.ts +2 -0
  78. package/dist/process/index.js +2 -0
  79. package/dist/process/managed-record.d.ts +2 -2
  80. package/dist/process/process-driver.d.ts +109 -0
  81. package/dist/process/process-driver.js +650 -0
  82. package/dist/process/process-executor.d.ts +47 -0
  83. package/dist/process/process-executor.js +296 -0
  84. package/dist/process/process-manager.js +48 -26
  85. package/dist/process/run-executor.js +12 -12
  86. package/dist/profile/client-actions.js +2 -2
  87. package/dist/profile/client-health.js +2 -2
  88. package/dist/profile/client-query.js +5 -6
  89. package/dist/profile/client-transport.d.ts +19 -17
  90. package/dist/profile/client-transport.js +47 -80
  91. package/dist/profile/client.d.ts +2 -2
  92. package/dist/profile/client.js +1 -1
  93. package/dist/profile/index.d.ts +1 -0
  94. package/dist/profile/index.js +1 -0
  95. package/dist/profile/manager.d.ts +5 -0
  96. package/dist/profile/manager.js +41 -6
  97. package/dist/project/closure.js +2 -2
  98. package/dist/project/index.d.ts +8 -1
  99. package/dist/project/index.js +10 -1
  100. package/dist/project/init.js +2 -2
  101. package/dist/project/loader.d.ts +1 -1
  102. package/dist/project/loader.js +26 -29
  103. package/dist/project/transactions.js +5 -10
  104. package/dist/project/types.d.ts +5 -0
  105. package/dist/registry/index.d.ts +3 -1
  106. package/dist/registry/index.js +2 -1
  107. package/dist/registry/lock.d.ts +28 -7
  108. package/dist/registry/lock.js +136 -16
  109. package/dist/registry/registry.d.ts +1 -5
  110. package/dist/registry/registry.js +1 -53
  111. package/dist/registry/scan.d.ts +0 -15
  112. package/dist/registry/scan.js +0 -59
  113. package/dist/registry/store.d.ts +42 -0
  114. package/dist/registry/store.js +43 -0
  115. package/dist/registry/types.d.ts +0 -24
  116. package/dist/runtime/action-collection.d.ts +1 -1
  117. package/dist/runtime/action-registry.d.ts +0 -4
  118. package/dist/runtime/action-registry.js +0 -7
  119. package/dist/runtime/context.js +5 -11
  120. package/dist/runtime/events.js +3 -6
  121. package/dist/runtime/identity.d.ts +22 -0
  122. package/dist/runtime/identity.js +10 -0
  123. package/dist/runtime/index.d.ts +1 -2
  124. package/dist/runtime/index.js +1 -2
  125. package/dist/runtime/module-loader.d.ts +2 -34
  126. package/dist/runtime/module-loader.js +1 -16
  127. package/dist/runtime/process.d.ts +6 -24
  128. package/dist/runtime/process.js +1 -118
  129. package/dist/runtime/run-persistence.js +2 -5
  130. package/dist/runtime/runner.d.ts +33 -93
  131. package/dist/runtime/runner.js +132 -364
  132. package/dist/runtime/standalone.d.ts +23 -8
  133. package/dist/runtime/standalone.js +100 -147
  134. package/dist/server/body.d.ts +16 -8
  135. package/dist/server/body.js +33 -16
  136. package/dist/server/dispatcher.d.ts +6 -10
  137. package/dist/server/dispatcher.js +24 -32
  138. package/dist/server/http-server.d.ts +87 -0
  139. package/dist/server/http-server.js +304 -0
  140. package/dist/server/index.d.ts +12 -0
  141. package/dist/server/index.js +11 -0
  142. package/dist/server/mcp-endpoint.d.ts +61 -0
  143. package/dist/server/mcp-endpoint.js +118 -0
  144. package/dist/server/policy.d.ts +138 -0
  145. package/dist/server/policy.js +368 -0
  146. package/dist/server/routes/actions.js +114 -64
  147. package/dist/server/routes/common.d.ts +18 -33
  148. package/dist/server/routes/common.js +45 -65
  149. package/dist/server/routes/config.d.ts +1 -1
  150. package/dist/server/routes/config.js +55 -65
  151. package/dist/server/routes/doctor.d.ts +1 -1
  152. package/dist/server/routes/doctor.js +13 -21
  153. package/dist/server/routes/health.d.ts +1 -1
  154. package/dist/server/routes/health.js +4 -5
  155. package/dist/server/routes/info.d.ts +2 -2
  156. package/dist/server/routes/info.js +17 -24
  157. package/dist/server/routes/playbooks.js +23 -36
  158. package/dist/server/routes/runs.js +151 -141
  159. package/dist/server/routes/state.d.ts +1 -1
  160. package/dist/server/routes/state.js +64 -63
  161. package/dist/server/security.d.ts +11 -0
  162. package/dist/server/security.js +36 -19
  163. package/dist/server/server.d.ts +2 -2
  164. package/dist/server/server.js +224 -238
  165. package/dist/server/types.d.ts +68 -21
  166. package/dist/service/factory.d.ts +12 -0
  167. package/dist/service/factory.js +85 -0
  168. package/dist/{target → service}/index.d.ts +1 -1
  169. package/dist/{target → service}/index.js +1 -1
  170. package/dist/service/local.d.ts +27 -0
  171. package/dist/service/local.js +138 -0
  172. package/dist/{target → service}/remote-errors.d.ts +3 -6
  173. package/dist/service/remote-errors.js +38 -0
  174. package/dist/{target → service}/remote-polling.d.ts +2 -2
  175. package/dist/{target → service}/remote-polling.js +8 -8
  176. package/dist/service/remote.d.ts +34 -0
  177. package/dist/service/remote.js +634 -0
  178. package/dist/service/sse-stream.d.ts +24 -0
  179. package/dist/service/sse-stream.js +139 -0
  180. package/dist/service/types.d.ts +272 -0
  181. package/dist/service/types.js +32 -0
  182. package/dist/storage/data-dir-lock.js +10 -5
  183. package/dist/storage/driver.d.ts +2 -1
  184. package/dist/storage/driver.js +3 -52
  185. package/dist/storage/index.d.ts +1 -0
  186. package/dist/storage/index.js +1 -0
  187. package/dist/storage/lock-core.d.ts +2 -6
  188. package/dist/storage/lock-core.js +4 -17
  189. package/dist/storage/params.d.ts +2 -8
  190. package/dist/storage/params.js +2 -8
  191. package/dist/storage/sqlite-driver.d.ts +40 -0
  192. package/dist/storage/sqlite-driver.js +116 -0
  193. package/dist/storage/sqlite.js +21 -6
  194. package/dist/storage/types.d.ts +4 -4
  195. package/dist/storage/types.js +2 -2
  196. package/dist/utils/index.d.ts +53 -0
  197. package/dist/utils/index.js +99 -4
  198. package/dist/utils/process.d.ts +10 -0
  199. package/dist/utils/process.js +21 -0
  200. package/dist/version.d.ts +1 -1
  201. package/dist/version.js +1 -1
  202. package/package.json +41 -3
  203. package/dist/app/index.d.ts +0 -2
  204. package/dist/app/index.js +0 -2
  205. package/dist/app/types.js +0 -1
  206. package/dist/catalog/action-index.d.ts +0 -9
  207. package/dist/catalog/action-index.js +0 -95
  208. package/dist/catalog/action-resolver.d.ts +0 -20
  209. package/dist/catalog/action-resolver.js +0 -95
  210. package/dist/catalog/location-registry.d.ts +0 -15
  211. package/dist/catalog/location-registry.js +0 -138
  212. package/dist/catalog/package-catalog.d.ts +0 -7
  213. package/dist/catalog/package-catalog.js +0 -77
  214. package/dist/catalog/types.d.ts +0 -68
  215. package/dist/catalog/types.js +0 -1
  216. package/dist/export/index.d.ts +0 -1
  217. package/dist/export/index.js +0 -1
  218. package/dist/export/templates.d.ts +0 -71
  219. package/dist/export/templates.js +0 -635
  220. package/dist/ipc/target.d.ts +0 -74
  221. package/dist/ipc/target.js +0 -365
  222. package/dist/platform/default.d.ts +0 -38
  223. package/dist/platform/default.js +0 -78
  224. package/dist/project/resolver.d.ts +0 -116
  225. package/dist/project/resolver.js +0 -376
  226. package/dist/registry/resolve.d.ts +0 -62
  227. package/dist/registry/resolve.js +0 -195
  228. package/dist/runtime/execution-manager.d.ts +0 -48
  229. package/dist/runtime/execution-manager.js +0 -66
  230. package/dist/runtime/package-runner-factory.d.ts +0 -82
  231. package/dist/runtime/package-runner-factory.js +0 -186
  232. package/dist/target/local.d.ts +0 -53
  233. package/dist/target/local.js +0 -349
  234. package/dist/target/remote-errors.js +0 -51
  235. package/dist/target/remote.d.ts +0 -86
  236. package/dist/target/remote.js +0 -818
  237. package/dist/target/target.d.ts +0 -6
  238. package/dist/target/target.js +0 -37
  239. package/dist/target/types.d.ts +0 -261
  240. package/dist/target/types.js +0 -35
  241. /package/dist/{app → package}/static-index.d.ts +0 -0
  242. /package/dist/{target → service}/sse-parser.d.ts +0 -0
  243. /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 { assertPackageAllowed, getSubPath, jsonResponse, resolveAppForPackage } from "./common.js";
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
- * 在未显式开启管理功能 (options.enableManagement !== true) 时返回 403 拒绝。
16
+ * 在未显式开启管理功能时返回 403 拒绝。
8
17
  */
9
18
  export async function handleStateRoutes(ctx) {
10
- const { req, url, pathname, corsHeaders, options, host, target } = ctx;
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 (options.enableManagement !== true) {
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
- if (pkgParam) {
36
- assertPackageAllowed(pkgParam, options);
37
- }
38
- const app = resolveAppForPackage(pkgParam, host, target, options);
39
- assertPackageAllowed(app.packageId, options);
40
- const effectiveNs = actionParam
41
- ? (nsParam !== undefined ? `${actionParam}:${nsParam}` : actionParam)
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 === "PACKAGE_NOT_ALLOWED" || err.status === 403) {
53
+ if (err.code === PACKAGE_NOT_ALLOWED || err.status === 403) {
48
54
  return jsonResponse({
49
55
  ok: false,
50
56
  error: {
51
- code: "PACKAGE_NOT_ALLOWED",
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.message?.includes("Unknown or unregistered package") ||
57
- err.message?.includes("Invalid packageId") ||
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 effectiveNs = actionParam ? (baseNs ? `${actionParam}:${baseNs}` : actionParam) : baseNs;
70
- if (pkgParam) {
71
- assertPackageAllowed(pkgParam, options);
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: app.packageId, clearedCount }, 200, corsHeaders);
80
+ return jsonResponse({ ok: true, packageId: targetPackageId, clearedCount }, 200, corsHeaders);
81
81
  }
82
82
  catch (err) {
83
- if (err.code === "PACKAGE_NOT_ALLOWED" || err.status === 403) {
83
+ if (err.code === PACKAGE_NOT_ALLOWED || err.status === 403) {
84
84
  return jsonResponse({
85
85
  ok: false,
86
86
  error: {
87
- code: "PACKAGE_NOT_ALLOWED",
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.message?.includes("Unknown or unregistered package") ||
93
- err.message?.includes("Invalid packageId") ||
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 effectiveNs = actionParam ? (nsParam ? `${actionParam}:${nsParam}` : actionParam) : nsParam;
107
- if (pkgParam) {
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 app.storage.findState(key, effectiveNs);
114
- if (!entry || entry.value === undefined) {
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: app.packageId,
120
- key: entry.key,
121
- namespace: entry.namespace,
122
- value: entry.value,
123
- expiresAt: entry.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 = combinedNs || "";
135
- if (!combinedNs) {
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 app.storage.setState(ns, actualKey, val, ttl);
141
- return jsonResponse({ ok: true, packageId: app.packageId, key: actualKey, namespace: ns, message: "updated" }, 200, corsHeaders);
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 app.storage.deleteStateSmart(key, effectiveNs);
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: app.packageId, key, deleted: true }, 200, corsHeaders);
152
+ return jsonResponse({ ok: true, packageId: targetPackageId, key, deleted: true }, 200, corsHeaders);
149
153
  }
150
154
  }
151
155
  catch (err) {
152
- if (err.code === "PACKAGE_NOT_ALLOWED" || err.status === 403) {
156
+ if (err.code === PACKAGE_NOT_ALLOWED || err.status === 403) {
153
157
  return jsonResponse({
154
158
  ok: false,
155
159
  error: {
156
- code: "PACKAGE_NOT_ALLOWED",
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.message?.includes("Unknown or unregistered package") ||
162
- err.message?.includes("Invalid packageId") ||
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
  *
@@ -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
- * 校验 HTTP 请求中的鉴权令牌是否有效。
23
+ * 从 HTTP 请求中提取 Bearer Token。
22
24
  *
23
25
  * 默认仅接受 HTTP 请求头: `Authorization: Bearer <token>`。
24
- * 仅当 options.allowQueryToken 为 true 时才允许解析 URL 查询参数 `?token=<token>`。
26
+ * 仅当 allowQueryToken 为 true 时才允许解析 URL 查询参数 `?token=<token>`。
25
27
  *
26
28
  * @param req 传入的 HTTP Request 对象
27
- * @param expectedToken 服务端预期的正确 Token(若未配置 Token 则默认放行)
28
- * @param options 校验选项或布尔值 allowQueryToken 开关
29
- * @returns 是否鉴权成功
29
+ * @param allowQueryToken 是否允许从 URL 查询参数解析 Token
30
+ * @returns 提取出的 Token 字符串,若未携带则返回 null
30
31
  */
31
- export function verifyBearerToken(req, expectedToken, options) {
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 (safeEqual(token, trimmedExpected)) {
41
- return true;
42
- }
37
+ if (token)
38
+ return token;
43
39
  }
44
40
  // 2. URL 查询参数: ?token=<token>(仅当显式开启 allowQueryToken 时允许)
45
- const allowQuery = typeof options === "boolean" ? options : options?.allowQueryToken === true;
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 && safeEqual(tokenParam.trim(), trimmedExpected)) {
51
- return true;
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 false;
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 白名单解析并返回跨域响应头。
@@ -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 2.0 原生轻量级 HTTP 服务端。
13
- * 作为 ActionDockHost 与 ActionDockTarget 的薄适配层,负责中间件流转、认证拦截与路由分发。
12
+ * 启动 ActionDock 原生轻量级 HTTP 服务端。
13
+ * 面向 ActionDockService 服务端口,负责中间件流转、认证拦截与路由分发。
14
14
  */
15
15
  export declare function startActionDockServer(options?: ServerOptions): Promise<ActionDockServerInstance>;