@playcraft/common 0.0.3 → 0.0.6

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 (44) hide show
  1. package/dist/auth/index.d.ts +1 -0
  2. package/dist/auth/index.d.ts.map +1 -1
  3. package/dist/auth/index.js +1 -0
  4. package/dist/auth/index.js.map +1 -1
  5. package/dist/auth/signature.d.ts +82 -0
  6. package/dist/auth/signature.d.ts.map +1 -0
  7. package/dist/auth/signature.js +154 -0
  8. package/dist/auth/signature.js.map +1 -0
  9. package/dist/auth/signature.spec.d.ts +2 -0
  10. package/dist/auth/signature.spec.d.ts.map +1 -0
  11. package/dist/auth/signature.spec.js +195 -0
  12. package/dist/auth/signature.spec.js.map +1 -0
  13. package/dist/index.d.ts +1 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +1 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/mcp/index.d.ts +3 -0
  18. package/dist/mcp/index.d.ts.map +1 -0
  19. package/dist/mcp/index.js +2 -0
  20. package/dist/mcp/index.js.map +1 -0
  21. package/dist/mcp/tools.d.ts +29 -0
  22. package/dist/mcp/tools.d.ts.map +1 -0
  23. package/dist/mcp/tools.js +179 -0
  24. package/dist/mcp/tools.js.map +1 -0
  25. package/dist/messenger/server.d.ts.map +1 -1
  26. package/dist/messenger/server.js +7 -1
  27. package/dist/messenger/server.js.map +1 -1
  28. package/dist/messenger/server.test.js.map +1 -1
  29. package/dist/messenger/types.d.ts +1 -2
  30. package/dist/messenger/types.d.ts.map +1 -1
  31. package/dist/sharedb/server.d.ts +7 -1
  32. package/dist/sharedb/server.d.ts.map +1 -1
  33. package/dist/sharedb/server.js +83 -21
  34. package/dist/sharedb/server.js.map +1 -1
  35. package/dist/sharedb/server.test.js.map +1 -1
  36. package/package.json +9 -5
  37. package/dist/models/converters.d.ts +0 -11
  38. package/dist/models/converters.d.ts.map +0 -1
  39. package/dist/models/converters.js +0 -25
  40. package/dist/models/converters.js.map +0 -1
  41. package/dist/models/converters.test.d.ts +0 -2
  42. package/dist/models/converters.test.d.ts.map +0 -1
  43. package/dist/models/converters.test.js +0 -18
  44. package/dist/models/converters.test.js.map +0 -1
@@ -1,4 +1,5 @@
1
1
  export * from './types.js';
2
2
  export * from './jwt.js';
3
3
  export * from './local-dev.js';
4
+ export * from './signature.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from './types.js';
2
2
  export * from './jwt.js';
3
3
  export * from './local-dev.js';
4
+ export * from './signature.js';
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * 签名验证结果
3
+ */
4
+ export interface SignatureVerificationResult {
5
+ valid: boolean;
6
+ error?: string;
7
+ }
8
+ /**
9
+ * 签名生成选项
10
+ */
11
+ export interface SignatureOptions {
12
+ method: string;
13
+ path: string;
14
+ timestamp: number;
15
+ secret: string;
16
+ }
17
+ /**
18
+ * 时间戳有效期(毫秒)
19
+ * 默认 5 分钟,容忍一定的时钟偏差
20
+ */
21
+ export declare const SIGNATURE_VALIDITY_MS: number;
22
+ /**
23
+ * 生成内部 API 签名
24
+ *
25
+ * 使用 HMAC-SHA256 算法生成签名,格式:
26
+ * HMAC-SHA256(method:path:timestamp, secret)
27
+ *
28
+ * @param method HTTP 方法(GET/POST/DELETE 等)
29
+ * @param path 请求路径(不含 query string)
30
+ * @param timestamp Unix 时间戳(毫秒)
31
+ * @param secret 共享密钥
32
+ * @returns 十六进制签名字符串
33
+ *
34
+ * @example
35
+ * const signature = generateInternalSignature('GET', '/api/assets/internal/123', Date.now(), 'secret');
36
+ */
37
+ export declare function generateInternalSignature(method: string, path: string, timestamp: number, secret: string): string;
38
+ /**
39
+ * 验证内部 API 签名
40
+ *
41
+ * @param method HTTP 方法
42
+ * @param path 请求路径
43
+ * @param timestamp 请求时间戳
44
+ * @param signature 提供的签名
45
+ * @param secret 共享密钥
46
+ * @returns 验证结果
47
+ *
48
+ * @example
49
+ * const result = verifyInternalSignature('GET', '/api/assets/internal/123', 1738645200000, 'abc123...', 'secret');
50
+ * if (result.valid) {
51
+ * // 签名有效
52
+ * } else {
53
+ * console.error(result.error);
54
+ * }
55
+ */
56
+ export declare function verifyInternalSignature(method: string, path: string, timestamp: number, signature: string, secret: string): SignatureVerificationResult;
57
+ /**
58
+ * 常量时间字符串比较
59
+ *
60
+ * 防止时序攻击(timing attack)
61
+ * 无论字符串是否匹配,都会比较所有字符
62
+ *
63
+ * @param a 字符串 A
64
+ * @param b 字符串 B
65
+ * @returns 是否相等
66
+ */
67
+ export declare function timingSafeEqual(a: string, b: string): boolean;
68
+ /**
69
+ * 生成带签名的请求头
70
+ *
71
+ * @param method HTTP 方法
72
+ * @param path 请求路径
73
+ * @param secret 共享密钥
74
+ * @param serviceName 服务名称(realtime/messenger/cli)
75
+ * @returns 包含签名的 headers 对象
76
+ *
77
+ * @example
78
+ * const headers = generateSignedHeaders('GET', '/api/assets/internal/123', 'secret', 'realtime');
79
+ * fetch(url, { headers });
80
+ */
81
+ export declare function generateSignedHeaders(method: string, path: string, secret: string, serviceName: string): Record<string, string>;
82
+ //# sourceMappingURL=signature.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.d.ts","sourceRoot":"","sources":["../../src/auth/signature.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAAgB,CAAC;AAEnD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,MAAM,CAeR;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,2BAA2B,CA2D7B;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAmB7D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAClB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB"}
@@ -0,0 +1,154 @@
1
+ import * as crypto from 'crypto';
2
+ /**
3
+ * 时间戳有效期(毫秒)
4
+ * 默认 5 分钟,容忍一定的时钟偏差
5
+ */
6
+ export const SIGNATURE_VALIDITY_MS = 5 * 60 * 1000;
7
+ /**
8
+ * 生成内部 API 签名
9
+ *
10
+ * 使用 HMAC-SHA256 算法生成签名,格式:
11
+ * HMAC-SHA256(method:path:timestamp, secret)
12
+ *
13
+ * @param method HTTP 方法(GET/POST/DELETE 等)
14
+ * @param path 请求路径(不含 query string)
15
+ * @param timestamp Unix 时间戳(毫秒)
16
+ * @param secret 共享密钥
17
+ * @returns 十六进制签名字符串
18
+ *
19
+ * @example
20
+ * const signature = generateInternalSignature('GET', '/api/assets/internal/123', Date.now(), 'secret');
21
+ */
22
+ export function generateInternalSignature(method, path, timestamp, secret) {
23
+ if (!method || !path || !timestamp || !secret) {
24
+ throw new Error('Missing required parameters for signature generation');
25
+ }
26
+ // 构造签名消息:method:path:timestamp
27
+ const message = `${method.toUpperCase()}:${path}:${timestamp}`;
28
+ // 使用 HMAC-SHA256 生成签名
29
+ const signature = crypto
30
+ .createHmac('sha256', secret)
31
+ .update(message)
32
+ .digest('hex');
33
+ return signature;
34
+ }
35
+ /**
36
+ * 验证内部 API 签名
37
+ *
38
+ * @param method HTTP 方法
39
+ * @param path 请求路径
40
+ * @param timestamp 请求时间戳
41
+ * @param signature 提供的签名
42
+ * @param secret 共享密钥
43
+ * @returns 验证结果
44
+ *
45
+ * @example
46
+ * const result = verifyInternalSignature('GET', '/api/assets/internal/123', 1738645200000, 'abc123...', 'secret');
47
+ * if (result.valid) {
48
+ * // 签名有效
49
+ * } else {
50
+ * console.error(result.error);
51
+ * }
52
+ */
53
+ export function verifyInternalSignature(method, path, timestamp, signature, secret) {
54
+ // 参数验证
55
+ if (!method || !path || !timestamp || !signature || !secret) {
56
+ return {
57
+ valid: false,
58
+ error: 'Missing required parameters for signature verification'
59
+ };
60
+ }
61
+ // 验证时间戳类型
62
+ if (typeof timestamp !== 'number' || isNaN(timestamp)) {
63
+ return {
64
+ valid: false,
65
+ error: 'Invalid timestamp format'
66
+ };
67
+ }
68
+ // 验证时间戳有效期(防重放攻击)
69
+ const now = Date.now();
70
+ const age = now - timestamp;
71
+ if (age < 0) {
72
+ return {
73
+ valid: false,
74
+ error: 'Timestamp is in the future'
75
+ };
76
+ }
77
+ if (age > SIGNATURE_VALIDITY_MS) {
78
+ return {
79
+ valid: false,
80
+ error: `Request expired (age: ${Math.floor(age / 1000)}s, max: ${SIGNATURE_VALIDITY_MS / 1000}s)`
81
+ };
82
+ }
83
+ // 重新计算签名
84
+ let expectedSignature;
85
+ try {
86
+ expectedSignature = generateInternalSignature(method, path, timestamp, secret);
87
+ }
88
+ catch (error) {
89
+ return {
90
+ valid: false,
91
+ error: `Signature calculation failed: ${error instanceof Error ? error.message : 'Unknown error'}`
92
+ };
93
+ }
94
+ // 使用常量时间比较防止时序攻击
95
+ const isValid = timingSafeEqual(signature, expectedSignature);
96
+ if (!isValid) {
97
+ return {
98
+ valid: false,
99
+ error: 'Signature mismatch'
100
+ };
101
+ }
102
+ return {
103
+ valid: true
104
+ };
105
+ }
106
+ /**
107
+ * 常量时间字符串比较
108
+ *
109
+ * 防止时序攻击(timing attack)
110
+ * 无论字符串是否匹配,都会比较所有字符
111
+ *
112
+ * @param a 字符串 A
113
+ * @param b 字符串 B
114
+ * @returns 是否相等
115
+ */
116
+ export function timingSafeEqual(a, b) {
117
+ if (typeof a !== 'string' || typeof b !== 'string') {
118
+ return false;
119
+ }
120
+ // 长度不同直接返回 false,但仍需要进行完整比较以保持常量时间
121
+ const lengthMatch = a.length === b.length;
122
+ const compareLength = Math.max(a.length, b.length);
123
+ let result = lengthMatch ? 0 : 1;
124
+ // 始终比较相同次数,避免提前退出
125
+ for (let i = 0; i < compareLength; i++) {
126
+ const aChar = i < a.length ? a.charCodeAt(i) : 0;
127
+ const bChar = i < b.length ? b.charCodeAt(i) : 0;
128
+ result |= aChar ^ bChar;
129
+ }
130
+ return result === 0;
131
+ }
132
+ /**
133
+ * 生成带签名的请求头
134
+ *
135
+ * @param method HTTP 方法
136
+ * @param path 请求路径
137
+ * @param secret 共享密钥
138
+ * @param serviceName 服务名称(realtime/messenger/cli)
139
+ * @returns 包含签名的 headers 对象
140
+ *
141
+ * @example
142
+ * const headers = generateSignedHeaders('GET', '/api/assets/internal/123', 'secret', 'realtime');
143
+ * fetch(url, { headers });
144
+ */
145
+ export function generateSignedHeaders(method, path, secret, serviceName) {
146
+ const timestamp = Date.now();
147
+ const signature = generateInternalSignature(method, path, timestamp, secret);
148
+ return {
149
+ 'X-Internal-Timestamp': timestamp.toString(),
150
+ 'X-Internal-Signature': signature,
151
+ 'X-Internal-Service': serviceName
152
+ };
153
+ }
154
+ //# sourceMappingURL=signature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.js","sourceRoot":"","sources":["../../src/auth/signature.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=signature.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.spec.d.ts","sourceRoot":"","sources":["../../src/auth/signature.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,195 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { generateInternalSignature, verifyInternalSignature, timingSafeEqual, generateSignedHeaders, SIGNATURE_VALIDITY_MS } from './signature.js';
3
+ describe('Signature Utils', () => {
4
+ const testSecret = 'test-secret-key-12345';
5
+ const testMethod = 'GET';
6
+ const testPath = '/api/assets/internal/123';
7
+ let testTimestamp;
8
+ beforeEach(() => {
9
+ testTimestamp = Date.now();
10
+ });
11
+ describe('generateInternalSignature', () => {
12
+ it('should generate a valid signature', () => {
13
+ const signature = generateInternalSignature(testMethod, testPath, testTimestamp, testSecret);
14
+ expect(signature).toBeDefined();
15
+ expect(typeof signature).toBe('string');
16
+ expect(signature.length).toBe(64); // SHA256 hex = 64 characters
17
+ });
18
+ it('should generate consistent signatures for same inputs', () => {
19
+ const sig1 = generateInternalSignature(testMethod, testPath, testTimestamp, testSecret);
20
+ const sig2 = generateInternalSignature(testMethod, testPath, testTimestamp, testSecret);
21
+ expect(sig1).toBe(sig2);
22
+ });
23
+ it('should generate different signatures for different methods', () => {
24
+ const getSig = generateInternalSignature('GET', testPath, testTimestamp, testSecret);
25
+ const postSig = generateInternalSignature('POST', testPath, testTimestamp, testSecret);
26
+ expect(getSig).not.toBe(postSig);
27
+ });
28
+ it('should generate different signatures for different paths', () => {
29
+ const path1Sig = generateInternalSignature(testMethod, '/api/assets/internal/123', testTimestamp, testSecret);
30
+ const path2Sig = generateInternalSignature(testMethod, '/api/scenes/internal/456', testTimestamp, testSecret);
31
+ expect(path1Sig).not.toBe(path2Sig);
32
+ });
33
+ it('should generate different signatures for different timestamps', () => {
34
+ const sig1 = generateInternalSignature(testMethod, testPath, testTimestamp, testSecret);
35
+ const sig2 = generateInternalSignature(testMethod, testPath, testTimestamp + 1000, testSecret);
36
+ expect(sig1).not.toBe(sig2);
37
+ });
38
+ it('should normalize method to uppercase', () => {
39
+ const upperSig = generateInternalSignature('GET', testPath, testTimestamp, testSecret);
40
+ const lowerSig = generateInternalSignature('get', testPath, testTimestamp, testSecret);
41
+ expect(upperSig).toBe(lowerSig);
42
+ });
43
+ it('should throw error when missing required parameters', () => {
44
+ expect(() => generateInternalSignature('', testPath, testTimestamp, testSecret)).toThrow();
45
+ expect(() => generateInternalSignature(testMethod, '', testTimestamp, testSecret)).toThrow();
46
+ expect(() => generateInternalSignature(testMethod, testPath, 0, testSecret)).toThrow();
47
+ expect(() => generateInternalSignature(testMethod, testPath, testTimestamp, '')).toThrow();
48
+ });
49
+ });
50
+ describe('verifyInternalSignature', () => {
51
+ it('should verify valid signature successfully', () => {
52
+ const signature = generateInternalSignature(testMethod, testPath, testTimestamp, testSecret);
53
+ const result = verifyInternalSignature(testMethod, testPath, testTimestamp, signature, testSecret);
54
+ expect(result.valid).toBe(true);
55
+ expect(result.error).toBeUndefined();
56
+ });
57
+ it('should reject invalid signature', () => {
58
+ const result = verifyInternalSignature(testMethod, testPath, testTimestamp, 'invalid-signature', testSecret);
59
+ expect(result.valid).toBe(false);
60
+ expect(result.error).toBe('Signature mismatch');
61
+ });
62
+ it('should reject expired timestamp', () => {
63
+ const oldTimestamp = Date.now() - SIGNATURE_VALIDITY_MS - 1000; // 超过有效期
64
+ const signature = generateInternalSignature(testMethod, testPath, oldTimestamp, testSecret);
65
+ const result = verifyInternalSignature(testMethod, testPath, oldTimestamp, signature, testSecret);
66
+ expect(result.valid).toBe(false);
67
+ expect(result.error).toContain('Request expired');
68
+ });
69
+ it('should reject future timestamp', () => {
70
+ const futureTimestamp = Date.now() + 10000; // 未来时间
71
+ const signature = generateInternalSignature(testMethod, testPath, futureTimestamp, testSecret);
72
+ const result = verifyInternalSignature(testMethod, testPath, futureTimestamp, signature, testSecret);
73
+ expect(result.valid).toBe(false);
74
+ expect(result.error).toBe('Timestamp is in the future');
75
+ });
76
+ it('should accept timestamp within validity period', () => {
77
+ const recentTimestamp = Date.now() - 60000; // 1 分钟前
78
+ const signature = generateInternalSignature(testMethod, testPath, recentTimestamp, testSecret);
79
+ const result = verifyInternalSignature(testMethod, testPath, recentTimestamp, signature, testSecret);
80
+ expect(result.valid).toBe(true);
81
+ });
82
+ it('should reject missing parameters', () => {
83
+ const signature = generateInternalSignature(testMethod, testPath, testTimestamp, testSecret);
84
+ let result = verifyInternalSignature('', testPath, testTimestamp, signature, testSecret);
85
+ expect(result.valid).toBe(false);
86
+ expect(result.error).toContain('Missing required parameters');
87
+ result = verifyInternalSignature(testMethod, '', testTimestamp, signature, testSecret);
88
+ expect(result.valid).toBe(false);
89
+ result = verifyInternalSignature(testMethod, testPath, testTimestamp, '', testSecret);
90
+ expect(result.valid).toBe(false);
91
+ result = verifyInternalSignature(testMethod, testPath, testTimestamp, signature, '');
92
+ expect(result.valid).toBe(false);
93
+ });
94
+ it('should reject invalid timestamp format', () => {
95
+ const signature = generateInternalSignature(testMethod, testPath, testTimestamp, testSecret);
96
+ const result = verifyInternalSignature(testMethod, testPath, NaN, signature, testSecret);
97
+ expect(result.valid).toBe(false);
98
+ expect(result.error).toBe('Invalid timestamp format');
99
+ });
100
+ it('should reject signature with wrong method', () => {
101
+ const signature = generateInternalSignature('GET', testPath, testTimestamp, testSecret);
102
+ const result = verifyInternalSignature('POST', testPath, testTimestamp, signature, testSecret);
103
+ expect(result.valid).toBe(false);
104
+ expect(result.error).toBe('Signature mismatch');
105
+ });
106
+ it('should reject signature with wrong path', () => {
107
+ const signature = generateInternalSignature(testMethod, '/api/assets/internal/123', testTimestamp, testSecret);
108
+ const result = verifyInternalSignature(testMethod, '/api/scenes/internal/456', testTimestamp, signature, testSecret);
109
+ expect(result.valid).toBe(false);
110
+ expect(result.error).toBe('Signature mismatch');
111
+ });
112
+ });
113
+ describe('timingSafeEqual', () => {
114
+ it('should return true for identical strings', () => {
115
+ expect(timingSafeEqual('abc123', 'abc123')).toBe(true);
116
+ expect(timingSafeEqual('', '')).toBe(true);
117
+ });
118
+ it('should return false for different strings', () => {
119
+ expect(timingSafeEqual('abc123', 'abc124')).toBe(false);
120
+ expect(timingSafeEqual('abc', 'def')).toBe(false);
121
+ });
122
+ it('should return false for strings of different lengths', () => {
123
+ expect(timingSafeEqual('abc', 'abcd')).toBe(false);
124
+ expect(timingSafeEqual('abcd', 'abc')).toBe(false);
125
+ });
126
+ it('should return false for non-string inputs', () => {
127
+ expect(timingSafeEqual(null, 'abc')).toBe(false);
128
+ expect(timingSafeEqual('abc', undefined)).toBe(false);
129
+ expect(timingSafeEqual(123, 456)).toBe(false);
130
+ });
131
+ it('should take constant time regardless of where strings differ', () => {
132
+ // 这个测试验证时序安全性的概念
133
+ // 实际的时序测试需要更复杂的基准测试
134
+ const str1 = 'a'.repeat(100);
135
+ const str2Early = 'b' + 'a'.repeat(99); // 第一个字符不同
136
+ const str2Late = 'a'.repeat(99) + 'b'; // 最后一个字符不同
137
+ expect(timingSafeEqual(str1, str2Early)).toBe(false);
138
+ expect(timingSafeEqual(str1, str2Late)).toBe(false);
139
+ });
140
+ });
141
+ describe('generateSignedHeaders', () => {
142
+ it('should generate all required headers', () => {
143
+ const headers = generateSignedHeaders(testMethod, testPath, testSecret, 'realtime');
144
+ expect(headers['X-Internal-Timestamp']).toBeDefined();
145
+ expect(headers['X-Internal-Signature']).toBeDefined();
146
+ expect(headers['X-Internal-Service']).toBe('realtime');
147
+ });
148
+ it('should generate valid signature in headers', () => {
149
+ const headers = generateSignedHeaders(testMethod, testPath, testSecret, 'realtime');
150
+ const timestamp = parseInt(headers['X-Internal-Timestamp'], 10);
151
+ const signature = headers['X-Internal-Signature'];
152
+ const result = verifyInternalSignature(testMethod, testPath, timestamp, signature, testSecret);
153
+ expect(result.valid).toBe(true);
154
+ });
155
+ it('should generate headers for different services', () => {
156
+ const realtimeHeaders = generateSignedHeaders(testMethod, testPath, testSecret, 'realtime');
157
+ const messengerHeaders = generateSignedHeaders(testMethod, testPath, testSecret, 'messenger');
158
+ expect(realtimeHeaders['X-Internal-Service']).toBe('realtime');
159
+ expect(messengerHeaders['X-Internal-Service']).toBe('messenger');
160
+ });
161
+ it('should generate headers for different HTTP methods', () => {
162
+ const getHeaders = generateSignedHeaders('GET', testPath, testSecret, 'realtime');
163
+ const postHeaders = generateSignedHeaders('POST', testPath, testSecret, 'realtime');
164
+ expect(getHeaders['X-Internal-Signature']).not.toBe(postHeaders['X-Internal-Signature']);
165
+ });
166
+ });
167
+ describe('Integration scenarios', () => {
168
+ it('should handle complete request flow', () => {
169
+ // 1. 服务生成签名头
170
+ const headers = generateSignedHeaders('GET', '/api/assets/internal/123', testSecret, 'realtime');
171
+ // 2. Backend 验证签名
172
+ const timestamp = parseInt(headers['X-Internal-Timestamp'], 10);
173
+ const result = verifyInternalSignature('GET', '/api/assets/internal/123', timestamp, headers['X-Internal-Signature'], testSecret);
174
+ expect(result.valid).toBe(true);
175
+ });
176
+ it('should reject tampered signature', () => {
177
+ const headers = generateSignedHeaders('GET', testPath, testSecret, 'realtime');
178
+ // 篡改签名
179
+ const tamperedSignature = headers['X-Internal-Signature'].replace(/a/g, 'b');
180
+ const timestamp = parseInt(headers['X-Internal-Timestamp'], 10);
181
+ const result = verifyInternalSignature('GET', testPath, timestamp, tamperedSignature, testSecret);
182
+ expect(result.valid).toBe(false);
183
+ });
184
+ it('should reject replay attack with old timestamp', () => {
185
+ // 生成旧的签名
186
+ const oldTimestamp = Date.now() - SIGNATURE_VALIDITY_MS - 10000;
187
+ const oldSignature = generateInternalSignature('GET', testPath, oldTimestamp, testSecret);
188
+ // 尝试重放
189
+ const result = verifyInternalSignature('GET', testPath, oldTimestamp, oldSignature, testSecret);
190
+ expect(result.valid).toBe(false);
191
+ expect(result.error).toContain('Request expired');
192
+ });
193
+ });
194
+ });
195
+ //# sourceMappingURL=signature.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signature.spec.js","sourceRoot":"","sources":["../../src/auth/signature.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAExB,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,MAAM,UAAU,GAAG,uBAAuB,CAAC;IAC3C,MAAM,UAAU,GAAG,KAAK,CAAC;IACzB,MAAM,QAAQ,GAAG,0BAA0B,CAAC;IAC5C,IAAI,aAAqB,CAAC;IAE1B,UAAU,CAAC,GAAG,EAAE;QACd,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACzC,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,SAAS,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAE7F,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;YAChC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,6BAA6B;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uDAAuD,EAAE,GAAG,EAAE;YAC/D,MAAM,IAAI,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YACxF,MAAM,IAAI,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAExF,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;YACpE,MAAM,MAAM,GAAG,yBAAyB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YACrF,MAAM,OAAO,GAAG,yBAAyB,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAEvF,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;YAClE,MAAM,QAAQ,GAAG,yBAAyB,CAAC,UAAU,EAAE,0BAA0B,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAC9G,MAAM,QAAQ,GAAG,yBAAyB,CAAC,UAAU,EAAE,0BAA0B,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAE9G,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;YACvE,MAAM,IAAI,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YACxF,MAAM,IAAI,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC;YAE/F,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,QAAQ,GAAG,yBAAyB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YACvF,MAAM,QAAQ,GAAG,yBAAyB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAEvF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAC3F,MAAM,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC,UAAU,EAAE,EAAE,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YAC7F,MAAM,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;YACvF,MAAM,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAC7F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,SAAS,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAC7F,MAAM,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAEnG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,mBAAmB,EAAE,UAAU,CAAC,CAAC;YAE7G,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,qBAAqB,GAAG,IAAI,CAAC,CAAC,QAAQ;YACxE,MAAM,SAAS,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;YAC5F,MAAM,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAElG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO;YACnD,MAAM,SAAS,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;YAC/F,MAAM,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAErG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,QAAQ;YACpD,MAAM,SAAS,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;YAC/F,MAAM,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAErG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,SAAS,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAE7F,IAAI,MAAM,GAAG,uBAAuB,CAAC,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YACzF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;YAE9D,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,EAAE,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YACvF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEjC,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC;YACtF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEjC,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;YACrF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,SAAS,GAAG,yBAAyB,CAAC,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAC7F,MAAM,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAEzF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YACxF,MAAM,MAAM,GAAG,uBAAuB,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAE/F,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,SAAS,GAAG,yBAAyB,CAAC,UAAU,EAAE,0BAA0B,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;YAC/G,MAAM,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,0BAA0B,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAErH,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvD,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxD,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;YAC9D,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnD,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,CAAC,eAAe,CAAC,IAAW,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACxD,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,SAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC7D,MAAM,CAAC,eAAe,CAAC,GAAU,EAAE,GAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;YACtE,iBAAiB;YACjB,oBAAoB;YACpB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,SAAS,GAAG,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU;YAClD,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,CAAE,WAAW;YAEnD,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrD,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,OAAO,GAAG,qBAAqB,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAEpF,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACtD,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACtD,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,OAAO,GAAG,qBAAqB,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAEpF,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,EAAE,EAAE,CAAC,CAAC;YAChE,MAAM,SAAS,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;YAElD,MAAM,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YAC/F,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,MAAM,eAAe,GAAG,qBAAqB,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAC5F,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;YAE9F,MAAM,CAAC,eAAe,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC/D,MAAM,CAAC,gBAAgB,CAAC,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;YAC5D,MAAM,UAAU,GAAG,qBAAqB,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAClF,MAAM,WAAW,GAAG,qBAAqB,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAEpF,MAAM,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,aAAa;YACb,MAAM,OAAO,GAAG,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAEjG,kBAAkB;YAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,EAAE,EAAE,CAAC,CAAC;YAChE,MAAM,MAAM,GAAG,uBAAuB,CACpC,KAAK,EACL,0BAA0B,EAC1B,SAAS,EACT,OAAO,CAAC,sBAAsB,CAAC,EAC/B,UAAU,CACX,CAAC;YAEF,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,OAAO,GAAG,qBAAqB,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YAE/E,OAAO;YACP,MAAM,iBAAiB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC7E,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,sBAAsB,CAAC,EAAE,EAAE,CAAC,CAAC;YAEhE,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,UAAU,CAAC,CAAC;YAClG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;YACxD,SAAS;YACT,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,qBAAqB,GAAG,KAAK,CAAC;YAChE,MAAM,YAAY,GAAG,yBAAyB,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;YAE1F,OAAO;YACP,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;YAChG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -6,5 +6,6 @@ export * from './sharedb/index.js';
6
6
  export * from './messenger/index.js';
7
7
  export * from './websocket/index.js';
8
8
  export * from './storage/index.js';
9
+ export * from './mcp/index.js';
9
10
  export * from './utils/index.js';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
package/dist/index.js CHANGED
@@ -6,5 +6,6 @@ export * from './sharedb/index.js';
6
6
  export * from './messenger/index.js';
7
7
  export * from './websocket/index.js';
8
8
  export * from './storage/index.js';
9
+ export * from './mcp/index.js';
9
10
  export * from './utils/index.js';
10
11
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { TOOL_NAME_TO_HANDLER, EXECUTOR_ONLY_TOOLS, toolNameToHandler, MCP_TOOL_NAMES, MCP_TOOL_DEFINITIONS, } from './tools.js';
2
+ export type { McpToolDefinition } from './tools.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { TOOL_NAME_TO_HANDLER, EXECUTOR_ONLY_TOOLS, toolNameToHandler, MCP_TOOL_NAMES, MCP_TOOL_DEFINITIONS, } from './tools.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,cAAc,EACd,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Unified MCP tool definitions and name mapping.
3
+ * Maps tool names (snake_case / pc_*) used by Backend MCP and AI clients
4
+ * to Editor handler method names (camelCase).
5
+ */
6
+ /** Map from MCP tool name (as sent by backend/AI) to Editor handler method name */
7
+ export declare const TOOL_NAME_TO_HANDLER: Record<string, string>;
8
+ /** Tool names that are executed by executor directly (no handler) */
9
+ export declare const EXECUTOR_ONLY_TOOLS: Set<string>;
10
+ /**
11
+ * Resolve MCP tool name to handler method name.
12
+ * Returns undefined if tool is executor-only or unknown.
13
+ */
14
+ export declare function toolNameToHandler(tool: string): string | undefined;
15
+ /**
16
+ * All MCP tool names that can be invoked (handler-based + executor-only).
17
+ */
18
+ export declare const MCP_TOOL_NAMES: string[];
19
+ export type McpToolDefinition = {
20
+ name: string;
21
+ description: string;
22
+ inputSchema?: Record<string, unknown>;
23
+ };
24
+ /**
25
+ * Minimal tool definitions for MCP tools/list.
26
+ * Backend can use this to return full tool list to MCP clients.
27
+ */
28
+ export declare const MCP_TOOL_DEFINITIONS: McpToolDefinition[];
29
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,mFAAmF;AACnF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAqFvD,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,aAAiD,CAAC;AAElF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGlE;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,UAK1B,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,iBAAiB,EA0EnD,CAAC"}