@f2a/network 0.1.2

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 (234) hide show
  1. package/.github/workflows/ci.yml +113 -0
  2. package/.github/workflows/publish.yml +60 -0
  3. package/LICENSE +21 -0
  4. package/MONOREPO.md +58 -0
  5. package/README.md +280 -0
  6. package/SKILL.md +137 -0
  7. package/dist/adapters/openclaw.d.ts +103 -0
  8. package/dist/adapters/openclaw.d.ts.map +1 -0
  9. package/dist/adapters/openclaw.js +297 -0
  10. package/dist/adapters/openclaw.js.map +1 -0
  11. package/dist/cli/commands.d.ts +17 -0
  12. package/dist/cli/commands.d.ts.map +1 -0
  13. package/dist/cli/commands.js +107 -0
  14. package/dist/cli/commands.js.map +1 -0
  15. package/dist/cli/index.d.ts +6 -0
  16. package/dist/cli/index.d.ts.map +1 -0
  17. package/dist/cli/index.js +203 -0
  18. package/dist/cli/index.js.map +1 -0
  19. package/dist/core/autonomous-economy.d.ts +136 -0
  20. package/dist/core/autonomous-economy.d.ts.map +1 -0
  21. package/dist/core/autonomous-economy.js +255 -0
  22. package/dist/core/autonomous-economy.js.map +1 -0
  23. package/dist/core/connection-manager.d.ts +80 -0
  24. package/dist/core/connection-manager.d.ts.map +1 -0
  25. package/dist/core/connection-manager.js +235 -0
  26. package/dist/core/connection-manager.js.map +1 -0
  27. package/dist/core/connection-manager.test.d.ts +2 -0
  28. package/dist/core/connection-manager.test.d.ts.map +1 -0
  29. package/dist/core/connection-manager.test.js +52 -0
  30. package/dist/core/connection-manager.test.js.map +1 -0
  31. package/dist/core/e2ee-crypto.d.ts +90 -0
  32. package/dist/core/e2ee-crypto.d.ts.map +1 -0
  33. package/dist/core/e2ee-crypto.js +190 -0
  34. package/dist/core/e2ee-crypto.js.map +1 -0
  35. package/dist/core/f2a.d.ts +126 -0
  36. package/dist/core/f2a.d.ts.map +1 -0
  37. package/dist/core/f2a.js +425 -0
  38. package/dist/core/f2a.js.map +1 -0
  39. package/dist/core/identity.d.ts +47 -0
  40. package/dist/core/identity.d.ts.map +1 -0
  41. package/dist/core/identity.js +130 -0
  42. package/dist/core/identity.js.map +1 -0
  43. package/dist/core/identity.test.d.ts +2 -0
  44. package/dist/core/identity.test.d.ts.map +1 -0
  45. package/dist/core/identity.test.js +43 -0
  46. package/dist/core/identity.test.js.map +1 -0
  47. package/dist/core/p2p-network.d.ts +242 -0
  48. package/dist/core/p2p-network.d.ts.map +1 -0
  49. package/dist/core/p2p-network.js +1182 -0
  50. package/dist/core/p2p-network.js.map +1 -0
  51. package/dist/core/reputation-security.d.ts +168 -0
  52. package/dist/core/reputation-security.d.ts.map +1 -0
  53. package/dist/core/reputation-security.js +369 -0
  54. package/dist/core/reputation-security.js.map +1 -0
  55. package/dist/core/reputation.d.ts +179 -0
  56. package/dist/core/reputation.d.ts.map +1 -0
  57. package/dist/core/reputation.js +472 -0
  58. package/dist/core/reputation.js.map +1 -0
  59. package/dist/core/review-committee.d.ts +130 -0
  60. package/dist/core/review-committee.d.ts.map +1 -0
  61. package/dist/core/review-committee.js +251 -0
  62. package/dist/core/review-committee.js.map +1 -0
  63. package/dist/core/serverless.d.ts +155 -0
  64. package/dist/core/serverless.d.ts.map +1 -0
  65. package/dist/core/serverless.js +615 -0
  66. package/dist/core/serverless.js.map +1 -0
  67. package/dist/core/token-manager.d.ts +42 -0
  68. package/dist/core/token-manager.d.ts.map +1 -0
  69. package/dist/core/token-manager.js +122 -0
  70. package/dist/core/token-manager.js.map +1 -0
  71. package/dist/daemon/control-server.d.ts +55 -0
  72. package/dist/daemon/control-server.d.ts.map +1 -0
  73. package/dist/daemon/control-server.js +262 -0
  74. package/dist/daemon/control-server.js.map +1 -0
  75. package/dist/daemon/index.d.ts +35 -0
  76. package/dist/daemon/index.d.ts.map +1 -0
  77. package/dist/daemon/index.js +69 -0
  78. package/dist/daemon/index.js.map +1 -0
  79. package/dist/daemon/main.d.ts +6 -0
  80. package/dist/daemon/main.d.ts.map +1 -0
  81. package/dist/daemon/main.js +38 -0
  82. package/dist/daemon/main.js.map +1 -0
  83. package/dist/daemon/start.d.ts +6 -0
  84. package/dist/daemon/start.d.ts.map +1 -0
  85. package/dist/daemon/start.js +25 -0
  86. package/dist/daemon/start.js.map +1 -0
  87. package/dist/daemon/webhook.d.ts +30 -0
  88. package/dist/daemon/webhook.d.ts.map +1 -0
  89. package/dist/daemon/webhook.js +86 -0
  90. package/dist/daemon/webhook.js.map +1 -0
  91. package/dist/daemon/webhook.test.d.ts +2 -0
  92. package/dist/daemon/webhook.test.d.ts.map +1 -0
  93. package/dist/daemon/webhook.test.js +24 -0
  94. package/dist/daemon/webhook.test.js.map +1 -0
  95. package/dist/index.d.ts +24 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +25 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/protocol/messages.d.ts +739 -0
  100. package/dist/protocol/messages.d.ts.map +1 -0
  101. package/dist/protocol/messages.js +188 -0
  102. package/dist/protocol/messages.js.map +1 -0
  103. package/dist/protocol/messages.test.d.ts +2 -0
  104. package/dist/protocol/messages.test.d.ts.map +1 -0
  105. package/dist/protocol/messages.test.js +55 -0
  106. package/dist/protocol/messages.test.js.map +1 -0
  107. package/dist/types/index.d.ts +247 -0
  108. package/dist/types/index.d.ts.map +1 -0
  109. package/dist/types/index.js +10 -0
  110. package/dist/types/index.js.map +1 -0
  111. package/dist/types/result.d.ts +28 -0
  112. package/dist/types/result.d.ts.map +1 -0
  113. package/dist/types/result.js +16 -0
  114. package/dist/types/result.js.map +1 -0
  115. package/dist/utils/benchmark.d.ts +67 -0
  116. package/dist/utils/benchmark.d.ts.map +1 -0
  117. package/dist/utils/benchmark.js +179 -0
  118. package/dist/utils/benchmark.js.map +1 -0
  119. package/dist/utils/logger.d.ts +105 -0
  120. package/dist/utils/logger.d.ts.map +1 -0
  121. package/dist/utils/logger.js +275 -0
  122. package/dist/utils/logger.js.map +1 -0
  123. package/dist/utils/middleware.d.ts +85 -0
  124. package/dist/utils/middleware.d.ts.map +1 -0
  125. package/dist/utils/middleware.js +173 -0
  126. package/dist/utils/middleware.js.map +1 -0
  127. package/dist/utils/rate-limiter.d.ts +71 -0
  128. package/dist/utils/rate-limiter.d.ts.map +1 -0
  129. package/dist/utils/rate-limiter.js +160 -0
  130. package/dist/utils/rate-limiter.js.map +1 -0
  131. package/dist/utils/signature.d.ts +57 -0
  132. package/dist/utils/signature.d.ts.map +1 -0
  133. package/dist/utils/signature.js +102 -0
  134. package/dist/utils/signature.js.map +1 -0
  135. package/dist/utils/validation.d.ts +504 -0
  136. package/dist/utils/validation.d.ts.map +1 -0
  137. package/dist/utils/validation.js +159 -0
  138. package/dist/utils/validation.js.map +1 -0
  139. package/docs/F2A-PROTOCOL.md +61 -0
  140. package/docs/MOBILE_BOOTSTRAP_DESIGN.md +126 -0
  141. package/docs/a2a-lessons.md +316 -0
  142. package/docs/middleware-guide.md +448 -0
  143. package/docs/readme-update-checklist.md +90 -0
  144. package/docs/reputation-guide.md +396 -0
  145. package/docs/rfcs/001-reputation-system.md +712 -0
  146. package/docs/security-design.md +247 -0
  147. package/install.sh +231 -0
  148. package/package.json +64 -0
  149. package/packages/openclaw-adapter/README.md +510 -0
  150. package/packages/openclaw-adapter/openclaw.plugin.json +106 -0
  151. package/packages/openclaw-adapter/package.json +40 -0
  152. package/packages/openclaw-adapter/src/announcement-queue.test.ts +449 -0
  153. package/packages/openclaw-adapter/src/announcement-queue.ts +403 -0
  154. package/packages/openclaw-adapter/src/capability-detector.test.ts +99 -0
  155. package/packages/openclaw-adapter/src/capability-detector.ts +183 -0
  156. package/packages/openclaw-adapter/src/claim-handlers.test.ts +974 -0
  157. package/packages/openclaw-adapter/src/claim-handlers.ts +482 -0
  158. package/packages/openclaw-adapter/src/connector.business.test.ts +583 -0
  159. package/packages/openclaw-adapter/src/connector.ts +795 -0
  160. package/packages/openclaw-adapter/src/index.test.ts +82 -0
  161. package/packages/openclaw-adapter/src/index.ts +18 -0
  162. package/packages/openclaw-adapter/src/integration.e2e.test.ts +829 -0
  163. package/packages/openclaw-adapter/src/logger.ts +51 -0
  164. package/packages/openclaw-adapter/src/network-client.test.ts +266 -0
  165. package/packages/openclaw-adapter/src/network-client.ts +251 -0
  166. package/packages/openclaw-adapter/src/network-recovery.test.ts +465 -0
  167. package/packages/openclaw-adapter/src/node-manager.test.ts +136 -0
  168. package/packages/openclaw-adapter/src/node-manager.ts +429 -0
  169. package/packages/openclaw-adapter/src/plugin.test.ts +439 -0
  170. package/packages/openclaw-adapter/src/plugin.ts +104 -0
  171. package/packages/openclaw-adapter/src/reputation.test.ts +221 -0
  172. package/packages/openclaw-adapter/src/reputation.ts +368 -0
  173. package/packages/openclaw-adapter/src/task-guard.test.ts +502 -0
  174. package/packages/openclaw-adapter/src/task-guard.ts +860 -0
  175. package/packages/openclaw-adapter/src/task-queue.concurrency.test.ts +462 -0
  176. package/packages/openclaw-adapter/src/task-queue.edge-cases.test.ts +284 -0
  177. package/packages/openclaw-adapter/src/task-queue.persistence.test.ts +408 -0
  178. package/packages/openclaw-adapter/src/task-queue.ts +668 -0
  179. package/packages/openclaw-adapter/src/tool-handlers.test.ts +906 -0
  180. package/packages/openclaw-adapter/src/tool-handlers.ts +574 -0
  181. package/packages/openclaw-adapter/src/types.ts +361 -0
  182. package/packages/openclaw-adapter/src/webhook-pusher.test.ts +188 -0
  183. package/packages/openclaw-adapter/src/webhook-pusher.ts +220 -0
  184. package/packages/openclaw-adapter/src/webhook-server.test.ts +580 -0
  185. package/packages/openclaw-adapter/src/webhook-server.ts +202 -0
  186. package/packages/openclaw-adapter/tsconfig.json +20 -0
  187. package/src/cli/commands.test.ts +157 -0
  188. package/src/cli/commands.ts +129 -0
  189. package/src/cli/index.test.ts +77 -0
  190. package/src/cli/index.ts +234 -0
  191. package/src/core/autonomous-economy.test.ts +291 -0
  192. package/src/core/autonomous-economy.ts +428 -0
  193. package/src/core/e2ee-crypto.test.ts +125 -0
  194. package/src/core/e2ee-crypto.ts +246 -0
  195. package/src/core/f2a.test.ts +269 -0
  196. package/src/core/f2a.ts +618 -0
  197. package/src/core/p2p-network.test.ts +199 -0
  198. package/src/core/p2p-network.ts +1432 -0
  199. package/src/core/reputation-security.test.ts +403 -0
  200. package/src/core/reputation-security.ts +562 -0
  201. package/src/core/reputation.test.ts +260 -0
  202. package/src/core/reputation.ts +576 -0
  203. package/src/core/review-committee.test.ts +380 -0
  204. package/src/core/review-committee.ts +401 -0
  205. package/src/core/token-manager.test.ts +133 -0
  206. package/src/core/token-manager.ts +140 -0
  207. package/src/daemon/control-server.test.ts +216 -0
  208. package/src/daemon/control-server.ts +292 -0
  209. package/src/daemon/index.test.ts +85 -0
  210. package/src/daemon/index.ts +89 -0
  211. package/src/daemon/main.ts +44 -0
  212. package/src/daemon/start.ts +29 -0
  213. package/src/daemon/webhook.test.ts +68 -0
  214. package/src/daemon/webhook.ts +105 -0
  215. package/src/index.test.ts +436 -0
  216. package/src/index.ts +72 -0
  217. package/src/types/index.test.ts +87 -0
  218. package/src/types/index.ts +341 -0
  219. package/src/types/result.ts +68 -0
  220. package/src/utils/benchmark.ts +237 -0
  221. package/src/utils/logger.ts +331 -0
  222. package/src/utils/middleware.ts +229 -0
  223. package/src/utils/rate-limiter.ts +207 -0
  224. package/src/utils/signature.ts +136 -0
  225. package/src/utils/validation.ts +186 -0
  226. package/tests/docker/Dockerfile.node +23 -0
  227. package/tests/docker/Dockerfile.runner +18 -0
  228. package/tests/docker/docker-compose.test.yml +73 -0
  229. package/tests/integration/message-passing.test.ts +109 -0
  230. package/tests/integration/multi-node.test.ts +92 -0
  231. package/tests/integration/p2p-connection.test.ts +83 -0
  232. package/tests/integration/test-config.ts +32 -0
  233. package/tsconfig.json +21 -0
  234. package/vitest.config.ts +26 -0
@@ -0,0 +1,85 @@
1
+ /**
2
+ * F2A 中间件系统
3
+ * 支持消息拦截、过滤和转换
4
+ */
5
+ import { F2AMessage, AgentInfo } from '../types/index.js';
6
+ import { Logger } from './logger.js';
7
+ export interface MiddlewareContext {
8
+ /** 消息 */
9
+ message: F2AMessage;
10
+ /** 发送方 Peer ID */
11
+ peerId: string;
12
+ /** 发送方 Agent 信息 */
13
+ agentInfo?: AgentInfo;
14
+ /** 中间件元数据 */
15
+ metadata: Map<string, unknown>;
16
+ }
17
+ export type MiddlewareResult = {
18
+ action: 'continue';
19
+ context: MiddlewareContext;
20
+ } | {
21
+ action: 'drop';
22
+ reason: string;
23
+ } | {
24
+ action: 'modify';
25
+ context: MiddlewareContext;
26
+ };
27
+ export interface Middleware {
28
+ /** 中间件名称 */
29
+ name: string;
30
+ /** 执行优先级(数字越小优先级越高) */
31
+ priority?: number;
32
+ /**
33
+ * 中间件类型
34
+ * - 'essential': 核心中间件,异常时中断链
35
+ * - 'optional': 可选中间件,异常时继续处理
36
+ */
37
+ type?: 'essential' | 'optional';
38
+ /** 处理函数 */
39
+ process(context: MiddlewareContext): Promise<MiddlewareResult> | MiddlewareResult;
40
+ }
41
+ /**
42
+ * 中间件管理器
43
+ */
44
+ export declare class MiddlewareManager {
45
+ private middlewares;
46
+ private logger;
47
+ constructor();
48
+ /**
49
+ * 注册中间件
50
+ */
51
+ use(middleware: Middleware): void;
52
+ /**
53
+ * 移除中间件
54
+ */
55
+ remove(name: string): boolean;
56
+ /**
57
+ * 执行中间件链
58
+ */
59
+ execute(context: MiddlewareContext): Promise<MiddlewareResult>;
60
+ /**
61
+ * 获取已注册的中间件列表
62
+ */
63
+ list(): string[];
64
+ /**
65
+ * 清空所有中间件
66
+ */
67
+ clear(): void;
68
+ }
69
+ /**
70
+ * 消息大小限制中间件
71
+ */
72
+ export declare function createMessageSizeLimitMiddleware(maxSize: number): Middleware;
73
+ /**
74
+ * 消息类型过滤中间件
75
+ */
76
+ export declare function createMessageTypeFilterMiddleware(allowedTypes: string[]): Middleware;
77
+ /**
78
+ * 消息日志中间件
79
+ */
80
+ export declare function createMessageLoggingMiddleware(logger?: Logger): Middleware;
81
+ /**
82
+ * 消息转换中间件示例
83
+ */
84
+ export declare function createMessageTransformMiddleware(transform: (msg: F2AMessage) => F2AMessage): Middleware;
85
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/utils/middleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,WAAW,iBAAiB;IAChC,SAAS;IACT,OAAO,EAAE,UAAU,CAAC;IACpB,kBAAkB;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,aAAa;IACb,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,MAAM,gBAAgB,GACxB;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAClD;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,YAAY;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,GAAG,UAAU,CAAC;IAChC,WAAW;IACX,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAAC;CACnF;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,MAAM,CAAS;;IAMvB;;OAEG;IACH,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI;IAOjC;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAU7B;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAkDpE;;OAEG;IACH,IAAI,IAAI,MAAM,EAAE;IAIhB;;OAEG;IACH,KAAK,IAAI,IAAI;CAId;AAMD;;GAEG;AACH,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAe5E;AAED;;GAEG;AACH,wBAAgB,iCAAiC,CAC/C,YAAY,EAAE,MAAM,EAAE,GACrB,UAAU,CAcZ;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,CAAC,EAAE,MAAM,GACd,UAAU,CAcZ;AAED;;GAEG;AACH,wBAAgB,gCAAgC,CAC9C,SAAS,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,UAAU,GACzC,UAAU,CAeZ"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * F2A 中间件系统
3
+ * 支持消息拦截、过滤和转换
4
+ */
5
+ import { Logger } from './logger.js';
6
+ /**
7
+ * 中间件管理器
8
+ */
9
+ export class MiddlewareManager {
10
+ middlewares = [];
11
+ logger;
12
+ constructor() {
13
+ this.logger = new Logger({ component: 'MiddlewareManager' });
14
+ }
15
+ /**
16
+ * 注册中间件
17
+ */
18
+ use(middleware) {
19
+ this.middlewares.push(middleware);
20
+ // 按优先级排序
21
+ this.middlewares.sort((a, b) => (a.priority || 0) - (b.priority || 0));
22
+ this.logger.info('Registered middleware', { name: middleware.name });
23
+ }
24
+ /**
25
+ * 移除中间件
26
+ */
27
+ remove(name) {
28
+ const index = this.middlewares.findIndex(m => m.name === name);
29
+ if (index !== -1) {
30
+ this.middlewares.splice(index, 1);
31
+ this.logger.info('Removed middleware', { name });
32
+ return true;
33
+ }
34
+ return false;
35
+ }
36
+ /**
37
+ * 执行中间件链
38
+ */
39
+ async execute(context) {
40
+ let currentContext = context;
41
+ for (const middleware of this.middlewares) {
42
+ try {
43
+ const result = await middleware.process(currentContext);
44
+ if (result.action === 'drop') {
45
+ this.logger.info('Message dropped by middleware', {
46
+ middleware: middleware.name,
47
+ reason: result.reason
48
+ });
49
+ return result;
50
+ }
51
+ if (result.action === 'modify') {
52
+ currentContext = result.context;
53
+ }
54
+ }
55
+ catch (error) {
56
+ this.logger.error('Middleware error', {
57
+ middleware: middleware.name,
58
+ error,
59
+ type: middleware.type || 'optional'
60
+ });
61
+ // 根据中间件类型决定是否中断链
62
+ // essential: 核心中间件,异常时中断链,返回 drop
63
+ // optional: 可选中间件,异常时继续处理(原有行为)
64
+ const middlewareType = middleware.type || 'optional';
65
+ if (middlewareType === 'essential') {
66
+ this.logger.warn('Essential middleware failed, aborting chain', {
67
+ middleware: middleware.name
68
+ });
69
+ return {
70
+ action: 'drop',
71
+ reason: `Essential middleware ${middleware.name} failed: ${error instanceof Error ? error.message : String(error)}`
72
+ };
73
+ }
74
+ // optional 中间件出错时继续处理,不阻塞消息
75
+ this.logger.info('Optional middleware failed, continuing chain', {
76
+ middleware: middleware.name
77
+ });
78
+ }
79
+ }
80
+ return { action: 'continue', context: currentContext };
81
+ }
82
+ /**
83
+ * 获取已注册的中间件列表
84
+ */
85
+ list() {
86
+ return this.middlewares.map(m => m.name);
87
+ }
88
+ /**
89
+ * 清空所有中间件
90
+ */
91
+ clear() {
92
+ this.middlewares = [];
93
+ this.logger.info('Cleared all middlewares');
94
+ }
95
+ }
96
+ // ============================================================================
97
+ // 内置中间件
98
+ // ============================================================================
99
+ /**
100
+ * 消息大小限制中间件
101
+ */
102
+ export function createMessageSizeLimitMiddleware(maxSize) {
103
+ return {
104
+ name: 'MessageSizeLimit',
105
+ priority: 100, // 高优先级,尽早检查
106
+ process(context) {
107
+ const messageSize = JSON.stringify(context.message).length;
108
+ if (messageSize > maxSize) {
109
+ return {
110
+ action: 'drop',
111
+ reason: `Message size ${messageSize} exceeds limit ${maxSize}`
112
+ };
113
+ }
114
+ return { action: 'continue', context };
115
+ }
116
+ };
117
+ }
118
+ /**
119
+ * 消息类型过滤中间件
120
+ */
121
+ export function createMessageTypeFilterMiddleware(allowedTypes) {
122
+ return {
123
+ name: 'MessageTypeFilter',
124
+ priority: 90,
125
+ process(context) {
126
+ if (!allowedTypes.includes(context.message.type)) {
127
+ return {
128
+ action: 'drop',
129
+ reason: `Message type ${context.message.type} not allowed`
130
+ };
131
+ }
132
+ return { action: 'continue', context };
133
+ }
134
+ };
135
+ }
136
+ /**
137
+ * 消息日志中间件
138
+ */
139
+ export function createMessageLoggingMiddleware(logger) {
140
+ const log = logger || new Logger({ component: 'MessageLogger' });
141
+ return {
142
+ name: 'MessageLogger',
143
+ priority: 50, // 中等优先级
144
+ process(context) {
145
+ log.debug('Processing message', {
146
+ type: context.message.type,
147
+ from: context.peerId.slice(0, 16),
148
+ id: context.message.id
149
+ });
150
+ return { action: 'continue', context };
151
+ }
152
+ };
153
+ }
154
+ /**
155
+ * 消息转换中间件示例
156
+ */
157
+ export function createMessageTransformMiddleware(transform) {
158
+ return {
159
+ name: 'MessageTransform',
160
+ priority: 10, // 低优先级,最后执行
161
+ process(context) {
162
+ const transformedMessage = transform(context.message);
163
+ return {
164
+ action: 'modify',
165
+ context: {
166
+ ...context,
167
+ message: transformedMessage
168
+ }
169
+ };
170
+ }
171
+ };
172
+ }
173
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/utils/middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * 速率限制中间件
3
+ * 基于 Token Bucket 算法实现,支持突发流量
4
+ */
5
+ export interface RateLimitConfig {
6
+ /** 最大请求数 */
7
+ maxRequests: number;
8
+ /** 时间窗口(毫秒) */
9
+ windowMs: number;
10
+ /** 是否跳过成功请求 */
11
+ skipSuccessfulRequests?: boolean;
12
+ /** 突发容量倍数(默认 1.5,允许短暂的请求爆发) */
13
+ burstMultiplier?: number;
14
+ }
15
+ export interface RateLimitEntry {
16
+ tokens: number;
17
+ lastRefill: number;
18
+ }
19
+ /**
20
+ * 速率限制器
21
+ * 实现 Disposable 接口,确保资源正确释放
22
+ */
23
+ export declare class RateLimiter implements Disposable {
24
+ private config;
25
+ private burstCapacity;
26
+ private store;
27
+ private logger;
28
+ private cleanupTimer?;
29
+ private disposed;
30
+ constructor(config: RateLimitConfig);
31
+ /**
32
+ * 实现 Disposable 接口
33
+ * 确保资源被正确释放
34
+ */
35
+ [Symbol.dispose](): void;
36
+ /**
37
+ * 检查是否已释放
38
+ */
39
+ isDisposed(): boolean;
40
+ /**
41
+ * 停止速率限制器,清理资源
42
+ * 幂等操作,可多次调用
43
+ */
44
+ stop(): void;
45
+ /**
46
+ * 检查是否允许请求
47
+ * @param key 标识符(如 IP 地址、Peer ID)
48
+ * @returns 是否允许请求
49
+ */
50
+ allowRequest(key: string): boolean;
51
+ /**
52
+ * 获取剩余令牌数
53
+ */
54
+ getRemainingTokens(key: string): number;
55
+ /**
56
+ * 重置限制
57
+ */
58
+ reset(key?: string): void;
59
+ /**
60
+ * 清理过期的条目
61
+ */
62
+ cleanup(): void;
63
+ }
64
+ /**
65
+ * 创建速率限制中间件(用于 HTTP 服务器)
66
+ */
67
+ export declare function createRateLimitMiddleware(config: RateLimitConfig): {
68
+ (req: any, res: any, next: () => void): void;
69
+ stop(): void;
70
+ };
71
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,eAAe;IAC9B,YAAY;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe;IACf,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,+BAA+B;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,WAAY,YAAW,UAAU;IAC5C,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,KAAK,CAA0C;IACvD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAC,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,MAAM,EAAE,eAAe;IAkBnC;;;OAGG;IACH,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;IAIxB;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;;OAGG;IACH,IAAI,IAAI,IAAI;IAeZ;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IA4ClC;;OAEG;IACH,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAavC;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAQzB;;OAEG;IACH,OAAO,IAAI,IAAI;CAUhB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe;UAGtC,GAAG,OAAO,GAAG,QAAQ,MAAM,IAAI;;EAsBzD"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * 速率限制中间件
3
+ * 基于 Token Bucket 算法实现,支持突发流量
4
+ */
5
+ import { Logger } from './logger.js';
6
+ /**
7
+ * 速率限制器
8
+ * 实现 Disposable 接口,确保资源正确释放
9
+ */
10
+ export class RateLimiter {
11
+ config;
12
+ burstCapacity;
13
+ store = new Map();
14
+ logger;
15
+ cleanupTimer;
16
+ disposed = false;
17
+ constructor(config) {
18
+ this.config = {
19
+ skipSuccessfulRequests: false,
20
+ burstMultiplier: 1.5,
21
+ ...config
22
+ };
23
+ // 计算突发容量
24
+ this.burstCapacity = Math.floor(this.config.maxRequests * this.config.burstMultiplier);
25
+ this.logger = new Logger({ component: 'RateLimiter' });
26
+ // 自动启动清理定时器
27
+ this.cleanupTimer = setInterval(() => this.cleanup(), config.windowMs);
28
+ // 注册析构回调,确保即使 stop() 未调用也能清理资源
29
+ if (typeof Symbol.dispose !== 'undefined') {
30
+ // 支持 using 语法的自动清理
31
+ }
32
+ }
33
+ /**
34
+ * 实现 Disposable 接口
35
+ * 确保资源被正确释放
36
+ */
37
+ [Symbol.dispose]() {
38
+ this.stop();
39
+ }
40
+ /**
41
+ * 检查是否已释放
42
+ */
43
+ isDisposed() {
44
+ return this.disposed;
45
+ }
46
+ /**
47
+ * 停止速率限制器,清理资源
48
+ * 幂等操作,可多次调用
49
+ */
50
+ stop() {
51
+ if (this.disposed) {
52
+ return; // 幂等:已释放则跳过
53
+ }
54
+ this.disposed = true;
55
+ if (this.cleanupTimer) {
56
+ clearInterval(this.cleanupTimer);
57
+ this.cleanupTimer = undefined;
58
+ }
59
+ this.store.clear();
60
+ this.logger.info('Rate limiter stopped');
61
+ }
62
+ /**
63
+ * 检查是否允许请求
64
+ * @param key 标识符(如 IP 地址、Peer ID)
65
+ * @returns 是否允许请求
66
+ */
67
+ allowRequest(key) {
68
+ const now = Date.now();
69
+ const entry = this.store.get(key);
70
+ if (!entry) {
71
+ // 首次请求,初始化令牌桶
72
+ // 初始令牌数为 maxRequests - 1(本次请求消耗 1 个)
73
+ this.store.set(key, {
74
+ tokens: this.config.maxRequests - 1,
75
+ lastRefill: now
76
+ });
77
+ return true;
78
+ }
79
+ // 计算需要补充的令牌数
80
+ const timePassed = now - entry.lastRefill;
81
+ const tokensToAdd = Math.floor((timePassed / this.config.windowMs) * this.config.maxRequests);
82
+ if (tokensToAdd > 0) {
83
+ // 令牌补充后不能超过突发容量
84
+ entry.tokens = Math.min(this.burstCapacity, entry.tokens + tokensToAdd);
85
+ entry.lastRefill = now;
86
+ }
87
+ // 检查是否有可用令牌
88
+ if (entry.tokens > 0) {
89
+ entry.tokens--;
90
+ return true;
91
+ }
92
+ this.logger.warn('Rate limit exceeded', {
93
+ key,
94
+ remaining: entry.tokens,
95
+ maxRequests: this.config.maxRequests,
96
+ burstCapacity: this.burstCapacity
97
+ });
98
+ return false;
99
+ }
100
+ /**
101
+ * 获取剩余令牌数
102
+ */
103
+ getRemainingTokens(key) {
104
+ const entry = this.store.get(key);
105
+ if (!entry)
106
+ return this.config.maxRequests;
107
+ const now = Date.now();
108
+ const timePassed = now - entry.lastRefill;
109
+ const tokensToAdd = Math.floor((timePassed / this.config.windowMs) * this.config.maxRequests);
110
+ return Math.min(this.burstCapacity, entry.tokens + tokensToAdd);
111
+ }
112
+ /**
113
+ * 重置限制
114
+ */
115
+ reset(key) {
116
+ if (key) {
117
+ this.store.delete(key);
118
+ }
119
+ else {
120
+ this.store.clear();
121
+ }
122
+ }
123
+ /**
124
+ * 清理过期的条目
125
+ */
126
+ cleanup() {
127
+ const now = Date.now();
128
+ const maxAge = this.config.windowMs * 2;
129
+ for (const [key, entry] of this.store) {
130
+ if (now - entry.lastRefill > maxAge) {
131
+ this.store.delete(key);
132
+ }
133
+ }
134
+ }
135
+ }
136
+ /**
137
+ * 创建速率限制中间件(用于 HTTP 服务器)
138
+ */
139
+ export function createRateLimitMiddleware(config) {
140
+ const limiter = new RateLimiter(config);
141
+ const middleware = (req, res, next) => {
142
+ const key = req.socket?.remoteAddress || 'unknown';
143
+ if (!limiter.allowRequest(key)) {
144
+ res.writeHead(429, { 'Content-Type': 'application/json' });
145
+ res.end(JSON.stringify({
146
+ success: false,
147
+ error: 'Too many requests',
148
+ code: 'RATE_LIMIT_EXCEEDED'
149
+ }));
150
+ return;
151
+ }
152
+ next();
153
+ };
154
+ // 提供 stop 方法清理资源
155
+ middleware.stop = () => {
156
+ limiter.stop();
157
+ };
158
+ return middleware;
159
+ }
160
+ //# sourceMappingURL=rate-limiter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/utils/rate-limiter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * 请求签名验证工具
3
+ * 使用 HMAC-SHA256 验证消息来源真实性
4
+ */
5
+ export interface SignatureConfig {
6
+ /** 签名密钥 */
7
+ secretKey: string;
8
+ /** 时间戳容忍度(毫秒,默认 5 分钟) */
9
+ timestampTolerance?: number;
10
+ }
11
+ export interface SignedMessage {
12
+ /** 消息体 */
13
+ payload: string;
14
+ /** 时间戳 */
15
+ timestamp: number;
16
+ /** 签名 */
17
+ signature: string;
18
+ /** 随机 nonce */
19
+ nonce: string;
20
+ }
21
+ /**
22
+ * 请求签名验证器
23
+ */
24
+ export declare class RequestSigner {
25
+ private secretKey;
26
+ private timestampTolerance;
27
+ private logger;
28
+ constructor(config: SignatureConfig);
29
+ /**
30
+ * 生成签名
31
+ * @param payload - 消息体(JSON 字符串)
32
+ * @returns 签名后的消息
33
+ */
34
+ sign(payload: string): SignedMessage;
35
+ /**
36
+ * 验证签名
37
+ * @param message - 签名后的消息
38
+ * @returns 验证结果
39
+ */
40
+ verify(message: SignedMessage): {
41
+ valid: boolean;
42
+ error?: string;
43
+ };
44
+ /**
45
+ * 生成 HMAC-SHA256 签名
46
+ */
47
+ private generateSignature;
48
+ /**
49
+ * 常量时间比较(防止时序攻击)
50
+ */
51
+ private constantTimeCompare;
52
+ }
53
+ /**
54
+ * 从环境变量加载签名密钥
55
+ */
56
+ export declare function loadSignatureConfig(): SignatureConfig | null;
57
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../src/utils/signature.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,eAAe;IAC9B,WAAW;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,yBAAyB;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU;IACV,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS;IACT,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,eAAe;IAMnC;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa;IAapC;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE;IA2BlE;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAM5B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,eAAe,GAAG,IAAI,CAuB5D"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * 请求签名验证工具
3
+ * 使用 HMAC-SHA256 验证消息来源真实性
4
+ */
5
+ import { createHmac, randomBytes, timingSafeEqual } from 'crypto';
6
+ import { Logger } from './logger.js';
7
+ /**
8
+ * 请求签名验证器
9
+ */
10
+ export class RequestSigner {
11
+ secretKey;
12
+ timestampTolerance;
13
+ logger;
14
+ constructor(config) {
15
+ this.secretKey = config.secretKey;
16
+ this.timestampTolerance = config.timestampTolerance || 5 * 60 * 1000; // 5 分钟
17
+ this.logger = new Logger({ component: 'RequestSigner' });
18
+ }
19
+ /**
20
+ * 生成签名
21
+ * @param payload - 消息体(JSON 字符串)
22
+ * @returns 签名后的消息
23
+ */
24
+ sign(payload) {
25
+ const timestamp = Date.now();
26
+ const nonce = randomBytes(16).toString('hex');
27
+ const signature = this.generateSignature(payload, timestamp, nonce);
28
+ return {
29
+ payload,
30
+ timestamp,
31
+ signature,
32
+ nonce
33
+ };
34
+ }
35
+ /**
36
+ * 验证签名
37
+ * @param message - 签名后的消息
38
+ * @returns 验证结果
39
+ */
40
+ verify(message) {
41
+ // 1. 检查时间戳
42
+ const now = Date.now();
43
+ const timeDiff = Math.abs(now - message.timestamp);
44
+ if (timeDiff > this.timestampTolerance) {
45
+ this.logger.warn('Signature timestamp expired', {
46
+ timestamp: message.timestamp,
47
+ diff: timeDiff
48
+ });
49
+ return { valid: false, error: 'Timestamp expired' };
50
+ }
51
+ // 2. 验证签名
52
+ const expectedSignature = this.generateSignature(message.payload, message.timestamp, message.nonce);
53
+ if (!this.constantTimeCompare(message.signature, expectedSignature)) {
54
+ this.logger.warn('Invalid signature');
55
+ return { valid: false, error: 'Invalid signature' };
56
+ }
57
+ return { valid: true };
58
+ }
59
+ /**
60
+ * 生成 HMAC-SHA256 签名
61
+ */
62
+ generateSignature(payload, timestamp, nonce) {
63
+ const data = `${payload}:${timestamp}:${nonce}`;
64
+ return createHmac('sha256', this.secretKey).update(data).digest('hex');
65
+ }
66
+ /**
67
+ * 常量时间比较(防止时序攻击)
68
+ */
69
+ constantTimeCompare(a, b) {
70
+ if (a.length !== b.length)
71
+ return false;
72
+ const bufA = Buffer.from(a);
73
+ const bufB = Buffer.from(b);
74
+ return timingSafeEqual(bufA, bufB);
75
+ }
76
+ }
77
+ /**
78
+ * 从环境变量加载签名密钥
79
+ */
80
+ export function loadSignatureConfig() {
81
+ const secretKey = process.env.F2A_SIGNATURE_KEY;
82
+ if (!secretKey) {
83
+ // 生产环境强制警告,开发环境仅提示
84
+ const isProduction = process.env.NODE_ENV === 'production';
85
+ const logger = new Logger({ component: 'SignatureConfig' });
86
+ if (isProduction) {
87
+ logger.error('F2A_SIGNATURE_KEY is not set! Signature verification is DISABLED. This is a security risk in production.');
88
+ }
89
+ else {
90
+ logger.warn('F2A_SIGNATURE_KEY is not set. Signature verification is disabled. Set this environment variable for secure message verification.');
91
+ }
92
+ return null;
93
+ }
94
+ const tolerance = process.env.F2A_SIGNATURE_TOLERANCE
95
+ ? parseInt(process.env.F2A_SIGNATURE_TOLERANCE, 10)
96
+ : undefined;
97
+ return {
98
+ secretKey,
99
+ timestampTolerance: tolerance
100
+ };
101
+ }
102
+ //# sourceMappingURL=signature.js.map