@skillsmith/mcp-server 0.4.7 → 0.4.9

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 (213) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +21 -0
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/__tests__/tool-dispatch.test.d.ts +8 -0
  5. package/dist/src/__tests__/tool-dispatch.test.d.ts.map +1 -0
  6. package/dist/src/__tests__/tool-dispatch.test.js +144 -0
  7. package/dist/src/__tests__/tool-dispatch.test.js.map +1 -0
  8. package/dist/src/index.js +31 -2
  9. package/dist/src/index.js.map +1 -1
  10. package/dist/src/middleware/license.d.ts +23 -0
  11. package/dist/src/middleware/license.d.ts.map +1 -1
  12. package/dist/src/middleware/license.js +28 -0
  13. package/dist/src/middleware/license.js.map +1 -1
  14. package/dist/src/middleware/toolFeatureMapping.d.ts.map +1 -1
  15. package/dist/src/middleware/toolFeatureMapping.js +4 -1
  16. package/dist/src/middleware/toolFeatureMapping.js.map +1 -1
  17. package/dist/src/supabase-client.d.ts +24 -0
  18. package/dist/src/supabase-client.d.ts.map +1 -0
  19. package/dist/src/supabase-client.js +63 -0
  20. package/dist/src/supabase-client.js.map +1 -0
  21. package/dist/src/tool-dispatch.d.ts.map +1 -1
  22. package/dist/src/tool-dispatch.js +71 -62
  23. package/dist/src/tool-dispatch.js.map +1 -1
  24. package/dist/src/tools/analytics.d.ts +155 -0
  25. package/dist/src/tools/analytics.d.ts.map +1 -0
  26. package/dist/src/tools/analytics.js +321 -0
  27. package/dist/src/tools/analytics.js.map +1 -0
  28. package/dist/src/tools/analytics.service.d.ts +46 -0
  29. package/dist/src/tools/analytics.service.d.ts.map +1 -0
  30. package/dist/src/tools/analytics.service.js +69 -0
  31. package/dist/src/tools/analytics.service.js.map +1 -0
  32. package/dist/src/tools/analytics.service.test.d.ts +6 -0
  33. package/dist/src/tools/analytics.service.test.d.ts.map +1 -0
  34. package/dist/src/tools/analytics.service.test.js +151 -0
  35. package/dist/src/tools/analytics.service.test.js.map +1 -0
  36. package/dist/src/tools/analytics.stub.d.ts +27 -0
  37. package/dist/src/tools/analytics.stub.d.ts.map +1 -0
  38. package/dist/src/tools/analytics.stub.js +200 -0
  39. package/dist/src/tools/analytics.stub.js.map +1 -0
  40. package/dist/src/tools/analytics.test.d.ts +6 -0
  41. package/dist/src/tools/analytics.test.d.ts.map +1 -0
  42. package/dist/src/tools/analytics.test.js +146 -0
  43. package/dist/src/tools/analytics.test.js.map +1 -0
  44. package/dist/src/tools/analyze.d.ts.map +1 -1
  45. package/dist/src/tools/analyze.js +7 -1
  46. package/dist/src/tools/analyze.js.map +1 -1
  47. package/dist/src/tools/audit-tools.d.ts +172 -0
  48. package/dist/src/tools/audit-tools.d.ts.map +1 -0
  49. package/dist/src/tools/audit-tools.js +187 -0
  50. package/dist/src/tools/audit-tools.js.map +1 -0
  51. package/dist/src/tools/audit-tools.test.d.ts +10 -0
  52. package/dist/src/tools/audit-tools.test.d.ts.map +1 -0
  53. package/dist/src/tools/audit-tools.test.js +147 -0
  54. package/dist/src/tools/audit-tools.test.js.map +1 -0
  55. package/dist/src/tools/compliance-tools.d.ts +103 -0
  56. package/dist/src/tools/compliance-tools.d.ts.map +1 -0
  57. package/dist/src/tools/compliance-tools.js +257 -0
  58. package/dist/src/tools/compliance-tools.js.map +1 -0
  59. package/dist/src/tools/compliance-tools.service.d.ts +19 -0
  60. package/dist/src/tools/compliance-tools.service.d.ts.map +1 -0
  61. package/dist/src/tools/compliance-tools.service.js +107 -0
  62. package/dist/src/tools/compliance-tools.service.js.map +1 -0
  63. package/dist/src/tools/compliance-tools.service.test.d.ts +6 -0
  64. package/dist/src/tools/compliance-tools.service.test.d.ts.map +1 -0
  65. package/dist/src/tools/compliance-tools.service.test.js +140 -0
  66. package/dist/src/tools/compliance-tools.service.test.js.map +1 -0
  67. package/dist/src/tools/compliance-tools.test.d.ts +6 -0
  68. package/dist/src/tools/compliance-tools.test.d.ts.map +1 -0
  69. package/dist/src/tools/compliance-tools.test.js +136 -0
  70. package/dist/src/tools/compliance-tools.test.js.map +1 -0
  71. package/dist/src/tools/get-skill.d.ts.map +1 -1
  72. package/dist/src/tools/get-skill.js +24 -1
  73. package/dist/src/tools/get-skill.js.map +1 -1
  74. package/dist/src/tools/index-local.d.ts.map +1 -1
  75. package/dist/src/tools/index-local.js +4 -0
  76. package/dist/src/tools/index-local.js.map +1 -1
  77. package/dist/src/tools/install.d.ts.map +1 -1
  78. package/dist/src/tools/install.js +11 -1
  79. package/dist/src/tools/install.js.map +1 -1
  80. package/dist/src/tools/install.tool.d.ts +4 -0
  81. package/dist/src/tools/install.tool.d.ts.map +1 -1
  82. package/dist/src/tools/install.tool.js +4 -0
  83. package/dist/src/tools/install.tool.js.map +1 -1
  84. package/dist/src/tools/install.types.d.ts +4 -0
  85. package/dist/src/tools/install.types.d.ts.map +1 -1
  86. package/dist/src/tools/install.types.js +5 -0
  87. package/dist/src/tools/install.types.js.map +1 -1
  88. package/dist/src/tools/integration-tools.d.ts +210 -0
  89. package/dist/src/tools/integration-tools.d.ts.map +1 -0
  90. package/dist/src/tools/integration-tools.js +264 -0
  91. package/dist/src/tools/integration-tools.js.map +1 -0
  92. package/dist/src/tools/integration-tools.service.d.ts +54 -0
  93. package/dist/src/tools/integration-tools.service.d.ts.map +1 -0
  94. package/dist/src/tools/integration-tools.service.js +299 -0
  95. package/dist/src/tools/integration-tools.service.js.map +1 -0
  96. package/dist/src/tools/integration-tools.service.test.d.ts +8 -0
  97. package/dist/src/tools/integration-tools.service.test.d.ts.map +1 -0
  98. package/dist/src/tools/integration-tools.service.test.js +401 -0
  99. package/dist/src/tools/integration-tools.service.test.js.map +1 -0
  100. package/dist/src/tools/integration-tools.stub.d.ts +13 -0
  101. package/dist/src/tools/integration-tools.stub.d.ts.map +1 -0
  102. package/dist/src/tools/integration-tools.stub.js +133 -0
  103. package/dist/src/tools/integration-tools.stub.js.map +1 -0
  104. package/dist/src/tools/integration-tools.test.d.ts +6 -0
  105. package/dist/src/tools/integration-tools.test.d.ts.map +1 -0
  106. package/dist/src/tools/integration-tools.test.js +259 -0
  107. package/dist/src/tools/integration-tools.test.js.map +1 -0
  108. package/dist/src/tools/publish-private.d.ts +60 -0
  109. package/dist/src/tools/publish-private.d.ts.map +1 -0
  110. package/dist/src/tools/publish-private.js +85 -0
  111. package/dist/src/tools/publish-private.js.map +1 -0
  112. package/dist/src/tools/publish-private.test.d.ts +6 -0
  113. package/dist/src/tools/publish-private.test.d.ts.map +1 -0
  114. package/dist/src/tools/publish-private.test.js +118 -0
  115. package/dist/src/tools/publish-private.test.js.map +1 -0
  116. package/dist/src/tools/publish.types.d.ts +2 -2
  117. package/dist/src/tools/rbac-tools.d.ts +180 -0
  118. package/dist/src/tools/rbac-tools.d.ts.map +1 -0
  119. package/dist/src/tools/rbac-tools.js +300 -0
  120. package/dist/src/tools/rbac-tools.js.map +1 -0
  121. package/dist/src/tools/rbac-tools.test.d.ts +6 -0
  122. package/dist/src/tools/rbac-tools.test.d.ts.map +1 -0
  123. package/dist/src/tools/rbac-tools.test.js +299 -0
  124. package/dist/src/tools/rbac-tools.test.js.map +1 -0
  125. package/dist/src/tools/rbac-tools.types.d.ts +70 -0
  126. package/dist/src/tools/rbac-tools.types.d.ts.map +1 -0
  127. package/dist/src/tools/rbac-tools.types.js +119 -0
  128. package/dist/src/tools/rbac-tools.types.js.map +1 -0
  129. package/dist/src/tools/recommend.helpers.d.ts.map +1 -1
  130. package/dist/src/tools/recommend.helpers.js +2 -1
  131. package/dist/src/tools/recommend.helpers.js.map +1 -1
  132. package/dist/src/tools/recommend.js +3 -3
  133. package/dist/src/tools/recommend.js.map +1 -1
  134. package/dist/src/tools/registry-tools.d.ts +133 -0
  135. package/dist/src/tools/registry-tools.d.ts.map +1 -0
  136. package/dist/src/tools/registry-tools.js +246 -0
  137. package/dist/src/tools/registry-tools.js.map +1 -0
  138. package/dist/src/tools/registry-tools.test.d.ts +6 -0
  139. package/dist/src/tools/registry-tools.test.d.ts.map +1 -0
  140. package/dist/src/tools/registry-tools.test.js +167 -0
  141. package/dist/src/tools/registry-tools.test.js.map +1 -0
  142. package/dist/src/tools/search.formatter.d.ts.map +1 -1
  143. package/dist/src/tools/search.formatter.js +11 -1
  144. package/dist/src/tools/search.formatter.js.map +1 -1
  145. package/dist/src/tools/skill-audit.d.ts +3 -3
  146. package/dist/src/tools/skill-audit.d.ts.map +1 -1
  147. package/dist/src/tools/skill-audit.js +5 -5
  148. package/dist/src/tools/skill-audit.js.map +1 -1
  149. package/dist/src/tools/skill-audit.test.js +5 -5
  150. package/dist/src/tools/skill-audit.test.js.map +1 -1
  151. package/dist/src/tools/skill-pack-audit.d.ts +22 -1
  152. package/dist/src/tools/skill-pack-audit.d.ts.map +1 -1
  153. package/dist/src/tools/skill-pack-audit.helpers.d.ts +53 -0
  154. package/dist/src/tools/skill-pack-audit.helpers.d.ts.map +1 -0
  155. package/dist/src/tools/skill-pack-audit.helpers.js +181 -0
  156. package/dist/src/tools/skill-pack-audit.helpers.js.map +1 -0
  157. package/dist/src/tools/skill-pack-audit.js +122 -5
  158. package/dist/src/tools/skill-pack-audit.js.map +1 -1
  159. package/dist/src/tools/skill-pack-audit.types.d.ts +70 -0
  160. package/dist/src/tools/skill-pack-audit.types.d.ts.map +1 -0
  161. package/dist/src/tools/skill-pack-audit.types.js +8 -0
  162. package/dist/src/tools/skill-pack-audit.types.js.map +1 -0
  163. package/dist/src/tools/skill-rescan.d.ts.map +1 -1
  164. package/dist/src/tools/skill-rescan.js +2 -3
  165. package/dist/src/tools/skill-rescan.js.map +1 -1
  166. package/dist/src/tools/skill-rescan.test.js +2 -2
  167. package/dist/src/tools/skill-rescan.test.js.map +1 -1
  168. package/dist/src/tools/sso-tools.d.ts +136 -0
  169. package/dist/src/tools/sso-tools.d.ts.map +1 -0
  170. package/dist/src/tools/sso-tools.js +214 -0
  171. package/dist/src/tools/sso-tools.js.map +1 -0
  172. package/dist/src/tools/sso-tools.test.d.ts +6 -0
  173. package/dist/src/tools/sso-tools.test.d.ts.map +1 -0
  174. package/dist/src/tools/sso-tools.test.js +167 -0
  175. package/dist/src/tools/sso-tools.test.js.map +1 -0
  176. package/dist/src/tools/suggest.d.ts.map +1 -1
  177. package/dist/src/tools/suggest.js +7 -1
  178. package/dist/src/tools/suggest.js.map +1 -1
  179. package/dist/src/tools/team-workspace.d.ts +179 -0
  180. package/dist/src/tools/team-workspace.d.ts.map +1 -0
  181. package/dist/src/tools/team-workspace.js +243 -0
  182. package/dist/src/tools/team-workspace.js.map +1 -0
  183. package/dist/src/tools/team-workspace.stub.d.ts +13 -0
  184. package/dist/src/tools/team-workspace.stub.d.ts.map +1 -0
  185. package/dist/src/tools/team-workspace.stub.js +76 -0
  186. package/dist/src/tools/team-workspace.stub.js.map +1 -0
  187. package/dist/src/tools/team-workspace.test.d.ts +7 -0
  188. package/dist/src/tools/team-workspace.test.d.ts.map +1 -0
  189. package/dist/src/tools/team-workspace.test.js +273 -0
  190. package/dist/src/tools/team-workspace.test.js.map +1 -0
  191. package/dist/src/tools/validate.helpers.d.ts.map +1 -1
  192. package/dist/src/tools/validate.helpers.js +15 -0
  193. package/dist/src/tools/validate.helpers.js.map +1 -1
  194. package/dist/src/utils/team-resolver.d.ts +20 -0
  195. package/dist/src/utils/team-resolver.d.ts.map +1 -0
  196. package/dist/src/utils/team-resolver.js +52 -0
  197. package/dist/src/utils/team-resolver.js.map +1 -0
  198. package/dist/src/utils/url-validator.d.ts +24 -0
  199. package/dist/src/utils/url-validator.d.ts.map +1 -0
  200. package/dist/src/utils/url-validator.js +59 -0
  201. package/dist/src/utils/url-validator.js.map +1 -0
  202. package/dist/tests/integration/recommend.integration.test.js +1 -1
  203. package/dist/tests/integration/recommend.integration.test.js.map +1 -1
  204. package/dist/tests/recommend.test.js +1 -1
  205. package/dist/tests/recommend.test.js.map +1 -1
  206. package/dist/tests/unit/skill-pack-audit.test.js +225 -0
  207. package/dist/tests/unit/skill-pack-audit.test.js.map +1 -1
  208. package/package.json +3 -3
  209. package/server.json +2 -2
  210. package/dist/vitest.config.d.ts +0 -6
  211. package/dist/vitest.config.d.ts.map +0 -1
  212. package/dist/vitest.config.js +0 -23
  213. package/dist/vitest.config.js.map +0 -1
@@ -0,0 +1,259 @@
1
+ /**
2
+ * @fileoverview Tests for custom integrations MCP tools
3
+ * @see SMI-3903: Custom Integrations MCP Tools
4
+ */
5
+ import { describe, it, expect, beforeEach } from 'vitest';
6
+ import { webhookConfigureInputSchema, apiKeyManageInputSchema, executeWebhookConfigure, executeApiKeyManage, createStubIntegrationService, setIntegrationService, } from './integration-tools.js';
7
+ const mockContext = {};
8
+ describe('integration-tools', () => {
9
+ beforeEach(() => {
10
+ setIntegrationService(createStubIntegrationService());
11
+ });
12
+ // ==========================================================================
13
+ // Schema validation
14
+ // ==========================================================================
15
+ describe('webhookConfigureInputSchema', () => {
16
+ it('should accept valid create input', () => {
17
+ const parsed = webhookConfigureInputSchema.parse({
18
+ action: 'create',
19
+ url: 'https://example.com/webhook',
20
+ events: ['skill.install'],
21
+ });
22
+ expect(parsed.action).toBe('create');
23
+ expect(parsed.url).toBe('https://example.com/webhook');
24
+ });
25
+ it('should accept list action', () => {
26
+ const parsed = webhookConfigureInputSchema.parse({ action: 'list' });
27
+ expect(parsed.action).toBe('list');
28
+ });
29
+ it('should reject invalid action', () => {
30
+ expect(() => webhookConfigureInputSchema.parse({ action: 'bad' })).toThrow();
31
+ });
32
+ it('should reject invalid URL', () => {
33
+ expect(() => webhookConfigureInputSchema.parse({
34
+ action: 'create',
35
+ url: 'not-a-url',
36
+ events: ['skill.install'],
37
+ })).toThrow();
38
+ });
39
+ });
40
+ describe('apiKeyManageInputSchema', () => {
41
+ it('should accept valid create input', () => {
42
+ const parsed = apiKeyManageInputSchema.parse({ action: 'create', name: 'ci-key' });
43
+ expect(parsed.action).toBe('create');
44
+ expect(parsed.expiresIn).toBe('90d');
45
+ });
46
+ it('should accept custom expiration', () => {
47
+ const parsed = apiKeyManageInputSchema.parse({
48
+ action: 'create',
49
+ name: 'long-lived',
50
+ expiresIn: 'never',
51
+ });
52
+ expect(parsed.expiresIn).toBe('never');
53
+ });
54
+ it('should reject invalid action', () => {
55
+ expect(() => apiKeyManageInputSchema.parse({ action: 'bad' })).toThrow();
56
+ });
57
+ it('should reject invalid expiration', () => {
58
+ expect(() => apiKeyManageInputSchema.parse({ action: 'create', name: 'test', expiresIn: '7d' })).toThrow();
59
+ });
60
+ });
61
+ // ==========================================================================
62
+ // webhook_configure handler
63
+ // ==========================================================================
64
+ describe('executeWebhookConfigure', () => {
65
+ it('should create a webhook', async () => {
66
+ const input = {
67
+ action: 'create',
68
+ url: 'https://example.com/webhook',
69
+ events: ['skill.install', 'skill.publish'],
70
+ description: 'CI webhook',
71
+ };
72
+ const result = await executeWebhookConfigure(input, mockContext);
73
+ expect(result.success).toBe(true);
74
+ expect(result.dataSource).toBe('stub');
75
+ expect(result.webhook).toBeDefined();
76
+ expect(result.webhook.url).toBe('https://example.com/webhook');
77
+ // Full signing secret is returned on create
78
+ expect('signingSecret' in result.webhook).toBe(true);
79
+ expect(result.message).toContain('Webhook Created');
80
+ expect(result.message).toContain('HMAC-SHA256');
81
+ expect(result.message).toContain('Store this secret now');
82
+ });
83
+ it('should fail create without url', async () => {
84
+ const result = await executeWebhookConfigure({ action: 'create', events: ['skill.install'] }, mockContext);
85
+ expect(result.success).toBe(false);
86
+ expect(result.error).toContain('url is required');
87
+ });
88
+ it('should fail create without events', async () => {
89
+ const result = await executeWebhookConfigure({ action: 'create', url: 'https://example.com/wh' }, mockContext);
90
+ expect(result.success).toBe(false);
91
+ expect(result.error).toContain('events is required');
92
+ });
93
+ it('should list webhooks', async () => {
94
+ await executeWebhookConfigure({
95
+ action: 'create',
96
+ url: 'https://example.com/wh1',
97
+ events: ['skill.install'],
98
+ }, mockContext);
99
+ const result = await executeWebhookConfigure({ action: 'list' }, mockContext);
100
+ expect(result.success).toBe(true);
101
+ expect(result.webhooks).toHaveLength(1);
102
+ // List returns masked secrets
103
+ expect('signingSecretLast4' in result.webhooks[0]).toBe(true);
104
+ });
105
+ it('should list empty webhooks', async () => {
106
+ const result = await executeWebhookConfigure({ action: 'list' }, mockContext);
107
+ expect(result.success).toBe(true);
108
+ expect(result.webhooks).toHaveLength(0);
109
+ expect(result.message).toContain('No webhooks');
110
+ });
111
+ it('should get a webhook by ID', async () => {
112
+ const createResult = await executeWebhookConfigure({ action: 'create', url: 'https://example.com/wh', events: ['skill.install'] }, mockContext);
113
+ const webhookId = createResult.webhook.id;
114
+ const result = await executeWebhookConfigure({ action: 'get', webhookId }, mockContext);
115
+ expect(result.success).toBe(true);
116
+ expect(result.webhook).toBeDefined();
117
+ });
118
+ it('should fail get without webhookId', async () => {
119
+ const result = await executeWebhookConfigure({ action: 'get' }, mockContext);
120
+ expect(result.success).toBe(false);
121
+ expect(result.error).toContain('webhookId is required');
122
+ });
123
+ it('should fail get for nonexistent webhook', async () => {
124
+ const result = await executeWebhookConfigure({ action: 'get', webhookId: 'wh_999' }, mockContext);
125
+ expect(result.success).toBe(false);
126
+ expect(result.error).toContain('not found');
127
+ });
128
+ it('should delete a webhook', async () => {
129
+ const createResult = await executeWebhookConfigure({ action: 'create', url: 'https://example.com/wh', events: ['skill.install'] }, mockContext);
130
+ const webhookId = createResult.webhook.id;
131
+ const result = await executeWebhookConfigure({ action: 'delete', webhookId }, mockContext);
132
+ expect(result.success).toBe(true);
133
+ expect(result.message).toContain('deleted');
134
+ });
135
+ it('should fail delete without webhookId', async () => {
136
+ const result = await executeWebhookConfigure({ action: 'delete' }, mockContext);
137
+ expect(result.success).toBe(false);
138
+ expect(result.error).toContain('webhookId is required');
139
+ });
140
+ it('should test a webhook', async () => {
141
+ const createResult = await executeWebhookConfigure({ action: 'create', url: 'https://example.com/wh', events: ['skill.install'] }, mockContext);
142
+ const webhookId = createResult.webhook.id;
143
+ const result = await executeWebhookConfigure({ action: 'test', webhookId }, mockContext);
144
+ expect(result.success).toBe(true);
145
+ expect(result.test).toBeDefined();
146
+ expect(result.test.statusCode).toBe(200);
147
+ });
148
+ it('should fail test without webhookId', async () => {
149
+ const result = await executeWebhookConfigure({ action: 'test' }, mockContext);
150
+ expect(result.success).toBe(false);
151
+ expect(result.error).toContain('webhookId is required');
152
+ });
153
+ it('should rotate webhook secret', async () => {
154
+ const createResult = await executeWebhookConfigure({ action: 'create', url: 'https://example.com/wh', events: ['skill.install'] }, mockContext);
155
+ const webhookId = createResult.webhook.id;
156
+ const result = await executeWebhookConfigure({ action: 'rotate_secret', webhookId }, mockContext);
157
+ expect(result.success).toBe(true);
158
+ expect(result.rotated).toBeDefined();
159
+ expect(result.rotated.newSigningSecret).toContain('whsec_');
160
+ expect(result.message).toContain('Secret Rotated');
161
+ });
162
+ it('should fail rotate_secret without webhookId', async () => {
163
+ const result = await executeWebhookConfigure({ action: 'rotate_secret' }, mockContext);
164
+ expect(result.success).toBe(false);
165
+ expect(result.error).toContain('webhookId is required');
166
+ });
167
+ it('should fail rotate_secret for nonexistent webhook', async () => {
168
+ const result = await executeWebhookConfigure({ action: 'rotate_secret', webhookId: 'wh_999' }, mockContext);
169
+ expect(result.success).toBe(false);
170
+ expect(result.error).toContain('not found');
171
+ });
172
+ });
173
+ // ==========================================================================
174
+ // api_key_manage handler
175
+ // ==========================================================================
176
+ describe('executeApiKeyManage', () => {
177
+ it('should create an API key', async () => {
178
+ const input = {
179
+ action: 'create',
180
+ name: 'ci-key',
181
+ permissions: ['read', 'write'],
182
+ expiresIn: '90d',
183
+ };
184
+ const result = await executeApiKeyManage(input, mockContext);
185
+ expect(result.success).toBe(true);
186
+ expect(result.key).toBeDefined();
187
+ // Full key value returned on create
188
+ expect('keyValue' in result.key).toBe(true);
189
+ expect(result.message).toContain('API Key Created');
190
+ expect(result.message).toContain("won't be shown again");
191
+ });
192
+ it('should create key with never expiration', async () => {
193
+ const result = await executeApiKeyManage({ action: 'create', name: 'forever-key', expiresIn: 'never' }, mockContext);
194
+ expect(result.success).toBe(true);
195
+ const key = result.key;
196
+ expect(key.expiresAt).toBeNull();
197
+ });
198
+ it('should fail create without name', async () => {
199
+ const result = await executeApiKeyManage({ action: 'create', expiresIn: '90d' }, mockContext);
200
+ expect(result.success).toBe(false);
201
+ expect(result.error).toContain('name is required');
202
+ });
203
+ it('should list API keys with masked values', async () => {
204
+ await executeApiKeyManage({ action: 'create', name: 'key-1', expiresIn: '90d' }, mockContext);
205
+ const result = await executeApiKeyManage({ action: 'list', expiresIn: '90d' }, mockContext);
206
+ expect(result.success).toBe(true);
207
+ expect(result.keys).toHaveLength(1);
208
+ // Masked: keyLast4 not full keyValue
209
+ expect('keyLast4' in result.keys[0]).toBe(true);
210
+ expect('keyValue' in result.keys[0]).toBe(false);
211
+ });
212
+ it('should list empty keys', async () => {
213
+ const result = await executeApiKeyManage({ action: 'list', expiresIn: '90d' }, mockContext);
214
+ expect(result.success).toBe(true);
215
+ expect(result.keys).toHaveLength(0);
216
+ expect(result.message).toContain('No API keys');
217
+ });
218
+ it('should get a key by ID', async () => {
219
+ const createResult = await executeApiKeyManage({ action: 'create', name: 'test-key', expiresIn: '90d' }, mockContext);
220
+ const keyId = createResult.key.id;
221
+ const result = await executeApiKeyManage({ action: 'get', keyId, expiresIn: '90d' }, mockContext);
222
+ expect(result.success).toBe(true);
223
+ expect(result.key).toBeDefined();
224
+ // Get returns masked
225
+ expect('keyLast4' in result.key).toBe(true);
226
+ });
227
+ it('should fail get without keyId', async () => {
228
+ const result = await executeApiKeyManage({ action: 'get', expiresIn: '90d' }, mockContext);
229
+ expect(result.success).toBe(false);
230
+ expect(result.error).toContain('keyId is required');
231
+ });
232
+ it('should fail get for nonexistent key', async () => {
233
+ const result = await executeApiKeyManage({ action: 'get', keyId: 'key_999', expiresIn: '90d' }, mockContext);
234
+ expect(result.success).toBe(false);
235
+ expect(result.error).toContain('not found');
236
+ });
237
+ it('should revoke a key', async () => {
238
+ const createResult = await executeApiKeyManage({ action: 'create', name: 'revokable', expiresIn: '90d' }, mockContext);
239
+ const keyId = createResult.key.id;
240
+ const result = await executeApiKeyManage({ action: 'revoke', keyId, expiresIn: '90d' }, mockContext);
241
+ expect(result.success).toBe(true);
242
+ expect(result.message).toContain('revoked');
243
+ });
244
+ it('should fail revoke without keyId', async () => {
245
+ const result = await executeApiKeyManage({ action: 'revoke', expiresIn: '90d' }, mockContext);
246
+ expect(result.success).toBe(false);
247
+ expect(result.error).toContain('keyId is required');
248
+ });
249
+ it('should fail double revoke', async () => {
250
+ const createResult = await executeApiKeyManage({ action: 'create', name: 'double-revoke', expiresIn: '90d' }, mockContext);
251
+ const keyId = createResult.key.id;
252
+ await executeApiKeyManage({ action: 'revoke', keyId, expiresIn: '90d' }, mockContext);
253
+ const result = await executeApiKeyManage({ action: 'revoke', keyId, expiresIn: '90d' }, mockContext);
254
+ expect(result.success).toBe(false);
255
+ expect(result.error).toContain('already revoked');
256
+ });
257
+ });
258
+ });
259
+ //# sourceMappingURL=integration-tools.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration-tools.test.js","sourceRoot":"","sources":["../../../src/tools/integration-tools.test.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAEzD,OAAO,EACL,2BAA2B,EAC3B,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,4BAA4B,EAC5B,qBAAqB,GAGtB,MAAM,wBAAwB,CAAA;AAE/B,MAAM,WAAW,GAAG,EAAiB,CAAA;AAErC,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,UAAU,CAAC,GAAG,EAAE;QACd,qBAAqB,CAAC,4BAA4B,EAAE,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;IAEF,6EAA6E;IAC7E,oBAAoB;IACpB,6EAA6E;IAE7E,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC3C,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,MAAM,GAAG,2BAA2B,CAAC,KAAK,CAAC;gBAC/C,MAAM,EAAE,QAAQ;gBAChB,GAAG,EAAE,6BAA6B;gBAClC,MAAM,EAAE,CAAC,eAAe,CAAC;aAC1B,CAAC,CAAA;YACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YACpC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;QACxD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;YACnC,MAAM,MAAM,GAAG,2BAA2B,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;YACpE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,CAAC,GAAG,EAAE,CAAC,2BAA2B,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA;QAC9E,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;YACnC,MAAM,CAAC,GAAG,EAAE,CACV,2BAA2B,CAAC,KAAK,CAAC;gBAChC,MAAM,EAAE,QAAQ;gBAChB,GAAG,EAAE,WAAW;gBAChB,MAAM,EAAE,CAAC,eAAe,CAAC;aAC1B,CAAC,CACH,CAAC,OAAO,EAAE,CAAA;QACb,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;YAClF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YACpC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACtC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC;gBAC3C,MAAM,EAAE,QAAQ;gBAChB,IAAI,EAAE,YAAY;gBAClB,SAAS,EAAE,OAAO;aACnB,CAAC,CAAA;YACF,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACxC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;YACtC,MAAM,CAAC,GAAG,EAAE,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA;QAC1E,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,CAAC,GAAG,EAAE,CACV,uBAAuB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CACnF,CAAC,OAAO,EAAE,CAAA;QACb,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,6EAA6E;IAC7E,4BAA4B;IAC5B,6EAA6E;IAE7E,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,KAAK,GAA0B;gBACnC,MAAM,EAAE,QAAQ;gBAChB,GAAG,EAAE,6BAA6B;gBAClC,MAAM,EAAE,CAAC,eAAe,EAAE,eAAe,CAAC;gBAC1C,WAAW,EAAE,YAAY;aAC1B,CAAA;YACD,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;YAChE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACtC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAA;YACpC,MAAM,CAAC,MAAM,CAAC,OAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;YAC/D,4CAA4C;YAC5C,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,OAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACrD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAA;YACnD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;YAC/C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QAC3D,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;YAC9C,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAC1C,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,EAC/C,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAA;QACnD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;YACjD,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAC1C,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,wBAAwB,EAAE,EACnD,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAA;QACtD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,uBAAuB,CAC3B;gBACE,MAAM,EAAE,QAAQ;gBAChB,GAAG,EAAE,yBAAyB;gBAC9B,MAAM,EAAE,CAAC,eAAe,CAAC;aAC1B,EACD,WAAW,CACZ,CAAA;YACD,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,CAAA;YAC7E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;YACvC,8BAA8B;YAC9B,MAAM,CAAC,oBAAoB,IAAI,MAAM,CAAC,QAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChE,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,CAAA;YAC7E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;YACvC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;QACjD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;YAC1C,MAAM,YAAY,GAAG,MAAM,uBAAuB,CAChD,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,EAC9E,WAAW,CACZ,CAAA;YACD,MAAM,SAAS,GAAI,YAAY,CAAC,OAA0B,CAAC,EAAE,CAAA;YAE7D,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,WAAW,CAAC,CAAA;YACvF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAA;QACtC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;YACjD,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,CAAC,CAAA;YAC5E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QACzD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAC1C,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EACtC,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,yBAAyB,EAAE,KAAK,IAAI,EAAE;YACvC,MAAM,YAAY,GAAG,MAAM,uBAAuB,CAChD,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,EAC9E,WAAW,CACZ,CAAA;YACD,MAAM,SAAS,GAAI,YAAY,CAAC,OAA0B,CAAC,EAAE,CAAA;YAE7D,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,WAAW,CAAC,CAAA;YAC1F,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,sCAAsC,EAAE,KAAK,IAAI,EAAE;YACpD,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,WAAW,CAAC,CAAA;YAC/E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QACzD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;YACrC,MAAM,YAAY,GAAG,MAAM,uBAAuB,CAChD,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,EAC9E,WAAW,CACZ,CAAA;YACD,MAAM,SAAS,GAAI,YAAY,CAAC,OAA0B,CAAC,EAAE,CAAA;YAE7D,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,WAAW,CAAC,CAAA;YACxF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,IAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;YAClD,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,WAAW,CAAC,CAAA;YAC7E,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QACzD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;YAC5C,MAAM,YAAY,GAAG,MAAM,uBAAuB,CAChD,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,wBAAwB,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,EAC9E,WAAW,CACZ,CAAA;YACD,MAAM,SAAS,GAAI,YAAY,CAAC,OAA0B,CAAC,EAAE,CAAA;YAE7D,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAC1C,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,EACtC,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAA;YACpC,MAAM,CAAC,MAAM,CAAC,OAAQ,CAAC,gBAAgB,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAA;YAC5D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAA;QACpD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;YAC3D,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,WAAW,CAAC,CAAA;YACtF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAA;QACzD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAC1C,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,EAChD,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,6EAA6E;IAC7E,yBAAyB;IACzB,6EAA6E;IAE7E,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;YACxC,MAAM,KAAK,GAAsB;gBAC/B,MAAM,EAAE,QAAQ;gBAChB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;gBAC9B,SAAS,EAAE,KAAK;aACjB,CAAA;YACD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;YAC5D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;YAChC,oCAAoC;YACpC,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,GAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC5C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAA;YACnD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAA;QAC1D,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,EAC7D,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAmC,CAAA;YACtD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAA;QAClC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,CAAC,CAAA;YAC7F,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAA;QACpD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;YACvD,MAAM,mBAAmB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,CAAC,CAAA;YAC7F,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,CAAC,CAAA;YAC3F,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;YACnC,qCAAqC;YACrC,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,IAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAChD,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,IAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACnD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;YACtC,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,CAAC,CAAA;YAC3F,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;YACnC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;QACjD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,wBAAwB,EAAE,KAAK,IAAI,EAAE;YACtC,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAC5C,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,EACxD,WAAW,CACZ,CAAA;YACD,MAAM,KAAK,GAAI,YAAY,CAAC,GAAsB,CAAC,EAAE,CAAA;YAErD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAC1C,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;YAChC,qBAAqB;YACrB,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC,GAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;YAC7C,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,CAAC,CAAA;YAC1F,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAA;QACrD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EACrD,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;YACnC,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAC5C,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,EACzD,WAAW,CACZ,CAAA;YACD,MAAM,KAAK,GAAI,YAAY,CAAC,GAAsB,CAAC,EAAE,CAAA;YAErD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAC7C,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QAC7C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;YAChD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,CAAC,CAAA;YAC7F,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAA;QACrD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE;YACzC,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAC5C,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,KAAK,EAAE,EAC7D,WAAW,CACZ,CAAA;YACD,MAAM,KAAK,GAAI,YAAY,CAAC,GAAsB,CAAC,EAAE,CAAA;YAErD,MAAM,mBAAmB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,WAAW,CAAC,CAAA;YACrF,MAAM,MAAM,GAAG,MAAM,mBAAmB,CACtC,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAC7C,WAAW,CACZ,CAAA;YACD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAA;QACnD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @fileoverview publish_private MCP tool -- mark a skill as team-private
3
+ * @module @skillsmith/mcp-server/tools/publish-private
4
+ * @see SMI-3896: Private Skills Publishing
5
+ *
6
+ * Sets `visibility = 'private'` and `team_id` on a skill record in the
7
+ * local SQLite database. Private skills are excluded from community search
8
+ * results and only visible to members of the owning team.
9
+ *
10
+ * Tier gate: Team (private_skills feature flag).
11
+ */
12
+ import { z } from 'zod';
13
+ import type { ToolContext } from '../context.js';
14
+ export declare const publishPrivateInputSchema: z.ZodObject<{
15
+ /** Skill identifier in author/name format */
16
+ skillId: z.ZodString;
17
+ /** Team ID to assign (resolved from license if not provided) */
18
+ teamId: z.ZodOptional<z.ZodString>;
19
+ }, "strip", z.ZodTypeAny, {
20
+ skillId: string;
21
+ teamId?: string | undefined;
22
+ }, {
23
+ skillId: string;
24
+ teamId?: string | undefined;
25
+ }>;
26
+ export type PublishPrivateInput = z.infer<typeof publishPrivateInputSchema>;
27
+ export interface PublishPrivateResult {
28
+ success: boolean;
29
+ skillId: string;
30
+ visibility: 'private' | 'public';
31
+ teamId: string | null;
32
+ message?: string;
33
+ error?: string;
34
+ }
35
+ export declare const publishPrivateToolSchema: {
36
+ name: string;
37
+ description: string;
38
+ inputSchema: {
39
+ type: "object";
40
+ properties: {
41
+ skillId: {
42
+ type: string;
43
+ description: string;
44
+ };
45
+ teamId: {
46
+ type: string;
47
+ description: string;
48
+ };
49
+ };
50
+ required: string[];
51
+ };
52
+ };
53
+ /**
54
+ * Execute publish_private: sets visibility = 'private' and team_id on the skill.
55
+ *
56
+ * @param input - Validated publish-private input
57
+ * @param context - Tool context with database access
58
+ */
59
+ export declare function executePublishPrivate(input: PublishPrivateInput, context: ToolContext): Promise<PublishPrivateResult>;
60
+ //# sourceMappingURL=publish-private.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-private.d.ts","sourceRoot":"","sources":["../../../src/tools/publish-private.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAOhD,eAAO,MAAM,yBAAyB;IACpC,6CAA6C;;IAE7C,gEAAgE;;;;;;;;EAEhE,CAAA;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAE3E,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,SAAS,GAAG,QAAQ,CAAA;IAChC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAMD,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;CAkBpC,CAAA;AAMD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,mBAAmB,EAC1B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAwC/B"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @fileoverview publish_private MCP tool -- mark a skill as team-private
3
+ * @module @skillsmith/mcp-server/tools/publish-private
4
+ * @see SMI-3896: Private Skills Publishing
5
+ *
6
+ * Sets `visibility = 'private'` and `team_id` on a skill record in the
7
+ * local SQLite database. Private skills are excluded from community search
8
+ * results and only visible to members of the owning team.
9
+ *
10
+ * Tier gate: Team (private_skills feature flag).
11
+ */
12
+ import { z } from 'zod';
13
+ import { getTeamWorkspaceService } from './team-workspace.js';
14
+ // ============================================================================
15
+ // Input / Output types
16
+ // ============================================================================
17
+ export const publishPrivateInputSchema = z.object({
18
+ /** Skill identifier in author/name format */
19
+ skillId: z.string().regex(/^[^/]+\/[^/]+$/, 'Must be author/name format'),
20
+ /** Team ID to assign (resolved from license if not provided) */
21
+ teamId: z.string().optional(),
22
+ });
23
+ // ============================================================================
24
+ // Tool schema for MCP registration
25
+ // ============================================================================
26
+ export const publishPrivateToolSchema = {
27
+ name: 'publish_private',
28
+ description: 'Mark a skill as private to your team. Private skills are hidden from community search. Requires Team tier license.',
29
+ inputSchema: {
30
+ type: 'object',
31
+ properties: {
32
+ skillId: {
33
+ type: 'string',
34
+ description: 'Skill ID in author/name format',
35
+ },
36
+ teamId: {
37
+ type: 'string',
38
+ description: 'Team ID (resolved from license if not provided)',
39
+ },
40
+ },
41
+ required: ['skillId'],
42
+ },
43
+ };
44
+ // ============================================================================
45
+ // Handler
46
+ // ============================================================================
47
+ /**
48
+ * Execute publish_private: sets visibility = 'private' and team_id on the skill.
49
+ *
50
+ * @param input - Validated publish-private input
51
+ * @param context - Tool context with database access
52
+ */
53
+ export async function executePublishPrivate(input, context) {
54
+ const { skillId } = input;
55
+ // Resolve team_id: explicit param or from license
56
+ let teamId = input.teamId ?? null;
57
+ if (!teamId) {
58
+ const licenseKey = process.env.SKILLSMITH_LICENSE_KEY ?? '';
59
+ const svc = getTeamWorkspaceService();
60
+ teamId = await svc.resolveTeamId(licenseKey);
61
+ }
62
+ // Check skill exists in local DB
63
+ const skill = context.db.prepare('SELECT id FROM skills WHERE id = ?').get(skillId);
64
+ if (!skill) {
65
+ return {
66
+ success: false,
67
+ skillId,
68
+ visibility: 'public',
69
+ teamId: null,
70
+ error: `Skill "${skillId}" not found in local database. Index or install it first.`,
71
+ };
72
+ }
73
+ // Update visibility and team_id
74
+ context.db
75
+ .prepare("UPDATE skills SET visibility = ?, team_id = ?, updated_at = datetime('now') WHERE id = ?")
76
+ .run('private', teamId, skillId);
77
+ return {
78
+ success: true,
79
+ skillId,
80
+ visibility: 'private',
81
+ teamId,
82
+ message: `Skill "${skillId}" is now private (team: ${teamId}).`,
83
+ };
84
+ }
85
+ //# sourceMappingURL=publish-private.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-private.js","sourceRoot":"","sources":["../../../src/tools/publish-private.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAE7D,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,6CAA6C;IAC7C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,gBAAgB,EAAE,4BAA4B,CAAC;IACzE,gEAAgE;IAChE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAA;AAaF,+EAA+E;AAC/E,mCAAmC;AACnC,+EAA+E;AAE/E,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,oHAAoH;IACtH,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,gCAAgC;aAC9C;YACD,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,iDAAiD;aAC/D;SACF;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;CACF,CAAA;AAED,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAA0B,EAC1B,OAAoB;IAEpB,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAA;IAEzB,kDAAkD;IAClD,IAAI,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,CAAA;IACjC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAA;QAC3D,MAAM,GAAG,GAAG,uBAAuB,EAAE,CAAA;QACrC,MAAM,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,UAAU,CAAC,CAAA;IAC9C,CAAC;IAED,iCAAiC;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,CAAC,OAAO,CAErE,CAAA;IAEb,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,OAAO,EAAE,KAAK;YACd,OAAO;YACP,UAAU,EAAE,QAAQ;YACpB,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,UAAU,OAAO,2DAA2D;SACpF,CAAA;IACH,CAAC;IAED,gCAAgC;IAChC,OAAO,CAAC,EAAE;SACP,OAAO,CACN,0FAA0F,CAC3F;SACA,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;IAElC,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO;QACP,UAAU,EAAE,SAAS;QACrB,MAAM;QACN,OAAO,EAAE,UAAU,OAAO,2BAA2B,MAAM,IAAI;KAChE,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @fileoverview Unit tests for publish_private MCP tool
3
+ * @see SMI-3896: Private Skills Publishing
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=publish-private.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-private.test.d.ts","sourceRoot":"","sources":["../../../src/tools/publish-private.test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @fileoverview Unit tests for publish_private MCP tool
3
+ * @see SMI-3896: Private Skills Publishing
4
+ */
5
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
6
+ import { createTestDatabase, closeDatabase } from '@skillsmith/core/testkit';
7
+ import { publishPrivateInputSchema, executePublishPrivate } from './publish-private.js';
8
+ import { setTeamWorkspaceService, createStubService } from './team-workspace.js';
9
+ // ============================================================================
10
+ // Helpers
11
+ // ============================================================================
12
+ function makeContext(db) {
13
+ return { db };
14
+ }
15
+ function insertSkill(db, id, extra = {}) {
16
+ const defaults = {
17
+ name: id.split('/')[1] ?? id,
18
+ author: id.split('/')[0] ?? 'unknown',
19
+ description: 'A test skill',
20
+ visibility: 'public',
21
+ };
22
+ const merged = { ...defaults, ...extra };
23
+ db.prepare(`INSERT INTO skills (id, name, author, description, visibility)
24
+ VALUES (?, ?, ?, ?, ?)`).run(id, merged.name, merged.author, merged.description, merged.visibility);
25
+ }
26
+ // ============================================================================
27
+ // Schema validation
28
+ // ============================================================================
29
+ describe('publishPrivateInputSchema', () => {
30
+ it('accepts valid input', () => {
31
+ const result = publishPrivateInputSchema.parse({ skillId: 'author/my-skill' });
32
+ expect(result.skillId).toBe('author/my-skill');
33
+ });
34
+ it('accepts input with explicit teamId', () => {
35
+ const result = publishPrivateInputSchema.parse({
36
+ skillId: 'author/my-skill',
37
+ teamId: 'team-123',
38
+ });
39
+ expect(result.teamId).toBe('team-123');
40
+ });
41
+ it('rejects skillId without slash', () => {
42
+ expect(() => publishPrivateInputSchema.parse({ skillId: 'noslash' })).toThrow();
43
+ });
44
+ it('rejects empty skillId', () => {
45
+ expect(() => publishPrivateInputSchema.parse({ skillId: '' })).toThrow();
46
+ });
47
+ });
48
+ // ============================================================================
49
+ // executePublishPrivate
50
+ // ============================================================================
51
+ describe('executePublishPrivate', () => {
52
+ let db;
53
+ beforeEach(() => {
54
+ db = createTestDatabase();
55
+ setTeamWorkspaceService(createStubService());
56
+ });
57
+ afterEach(() => {
58
+ closeDatabase(db);
59
+ });
60
+ it('marks a skill as private', async () => {
61
+ insertSkill(db, 'author/my-skill');
62
+ const result = await executePublishPrivate({ skillId: 'author/my-skill' }, makeContext(db));
63
+ expect(result.success).toBe(true);
64
+ expect(result.visibility).toBe('private');
65
+ expect(result.teamId).toBeTruthy();
66
+ // Verify database was updated
67
+ const row = db
68
+ .prepare('SELECT visibility, team_id FROM skills WHERE id = ?')
69
+ .get('author/my-skill');
70
+ expect(row.visibility).toBe('private');
71
+ expect(row.team_id).toBeTruthy();
72
+ });
73
+ it('uses explicit teamId when provided', async () => {
74
+ insertSkill(db, 'author/my-skill');
75
+ const result = await executePublishPrivate({ skillId: 'author/my-skill', teamId: 'explicit-team-id' }, makeContext(db));
76
+ expect(result.success).toBe(true);
77
+ expect(result.teamId).toBe('explicit-team-id');
78
+ const row = db.prepare('SELECT team_id FROM skills WHERE id = ?').get('author/my-skill');
79
+ expect(row.team_id).toBe('explicit-team-id');
80
+ });
81
+ it('returns error for nonexistent skill', async () => {
82
+ const result = await executePublishPrivate({ skillId: 'ghost/missing' }, makeContext(db));
83
+ expect(result.success).toBe(false);
84
+ expect(result.error).toContain('not found');
85
+ });
86
+ it('backward compat: skill_publish without visibility stays public', async () => {
87
+ insertSkill(db, 'author/public-skill');
88
+ // Verify default is public
89
+ const row = db
90
+ .prepare('SELECT visibility FROM skills WHERE id = ?')
91
+ .get('author/public-skill');
92
+ expect(row.visibility).toBe('public');
93
+ });
94
+ it('community user searching must NOT see private skills', async () => {
95
+ insertSkill(db, 'author/private-skill', { visibility: 'private' });
96
+ insertSkill(db, 'author/public-skill', { visibility: 'public' });
97
+ // Query as community user (no team_id) — only public skills visible
98
+ const publicRows = db.prepare('SELECT id FROM skills WHERE visibility = ?').all('public');
99
+ expect(publicRows).toHaveLength(1);
100
+ expect(publicRows[0].id).toBe('author/public-skill');
101
+ });
102
+ it('team user sees own private skills', async () => {
103
+ const teamId = 'my-team-123';
104
+ insertSkill(db, 'author/private-skill');
105
+ // Mark as private
106
+ db.prepare('UPDATE skills SET visibility = ?, team_id = ? WHERE id = ?').run('private', teamId, 'author/private-skill');
107
+ insertSkill(db, 'other/public-skill');
108
+ // Query with team_id filter
109
+ const rows = db
110
+ .prepare('SELECT id FROM skills WHERE (visibility = ? OR team_id = ?)')
111
+ .all('public', teamId);
112
+ expect(rows).toHaveLength(2);
113
+ const ids = rows.map((r) => r.id);
114
+ expect(ids).toContain('author/private-skill');
115
+ expect(ids).toContain('other/public-skill');
116
+ });
117
+ });
118
+ //# sourceMappingURL=publish-private.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-private.test.js","sourceRoot":"","sources":["../../../src/tools/publish-private.test.ts"],"names":[],"mappings":"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"}
@@ -22,17 +22,17 @@ export declare const publishInputSchema: z.ZodObject<{
22
22
  add_topic: z.ZodDefault<z.ZodBoolean>;
23
23
  }, "strip", z.ZodTypeAny, {
24
24
  skill_path: string;
25
+ visibility: "public" | "private";
25
26
  check_references: boolean;
26
27
  create_repo: boolean;
27
- visibility: "public" | "private";
28
28
  add_topic: boolean;
29
29
  reference_patterns?: string[] | undefined;
30
30
  }, {
31
31
  skill_path: string;
32
+ visibility?: "public" | "private" | undefined;
32
33
  check_references?: boolean | undefined;
33
34
  reference_patterns?: string[] | undefined;
34
35
  create_repo?: boolean | undefined;
35
- visibility?: "public" | "private" | undefined;
36
36
  add_topic?: boolean | undefined;
37
37
  }>;
38
38
  /**