@skillsmith/mcp-server 0.4.7 → 0.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +20 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/__tests__/tool-dispatch.test.d.ts +8 -0
- package/dist/src/__tests__/tool-dispatch.test.d.ts.map +1 -0
- package/dist/src/__tests__/tool-dispatch.test.js +144 -0
- package/dist/src/__tests__/tool-dispatch.test.js.map +1 -0
- package/dist/src/index.js +31 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/middleware/license.d.ts +23 -0
- package/dist/src/middleware/license.d.ts.map +1 -1
- package/dist/src/middleware/license.js +28 -0
- package/dist/src/middleware/license.js.map +1 -1
- package/dist/src/middleware/toolFeatureMapping.d.ts.map +1 -1
- package/dist/src/middleware/toolFeatureMapping.js +4 -1
- package/dist/src/middleware/toolFeatureMapping.js.map +1 -1
- package/dist/src/supabase-client.d.ts +24 -0
- package/dist/src/supabase-client.d.ts.map +1 -0
- package/dist/src/supabase-client.js +63 -0
- package/dist/src/supabase-client.js.map +1 -0
- package/dist/src/tool-dispatch.d.ts.map +1 -1
- package/dist/src/tool-dispatch.js +71 -62
- package/dist/src/tool-dispatch.js.map +1 -1
- package/dist/src/tools/analytics.d.ts +155 -0
- package/dist/src/tools/analytics.d.ts.map +1 -0
- package/dist/src/tools/analytics.js +321 -0
- package/dist/src/tools/analytics.js.map +1 -0
- package/dist/src/tools/analytics.service.d.ts +46 -0
- package/dist/src/tools/analytics.service.d.ts.map +1 -0
- package/dist/src/tools/analytics.service.js +69 -0
- package/dist/src/tools/analytics.service.js.map +1 -0
- package/dist/src/tools/analytics.service.test.d.ts +6 -0
- package/dist/src/tools/analytics.service.test.d.ts.map +1 -0
- package/dist/src/tools/analytics.service.test.js +151 -0
- package/dist/src/tools/analytics.service.test.js.map +1 -0
- package/dist/src/tools/analytics.stub.d.ts +27 -0
- package/dist/src/tools/analytics.stub.d.ts.map +1 -0
- package/dist/src/tools/analytics.stub.js +200 -0
- package/dist/src/tools/analytics.stub.js.map +1 -0
- package/dist/src/tools/analytics.test.d.ts +6 -0
- package/dist/src/tools/analytics.test.d.ts.map +1 -0
- package/dist/src/tools/analytics.test.js +146 -0
- package/dist/src/tools/analytics.test.js.map +1 -0
- package/dist/src/tools/analyze.d.ts.map +1 -1
- package/dist/src/tools/analyze.js +7 -1
- package/dist/src/tools/analyze.js.map +1 -1
- package/dist/src/tools/audit-tools.d.ts +172 -0
- package/dist/src/tools/audit-tools.d.ts.map +1 -0
- package/dist/src/tools/audit-tools.js +187 -0
- package/dist/src/tools/audit-tools.js.map +1 -0
- package/dist/src/tools/audit-tools.test.d.ts +10 -0
- package/dist/src/tools/audit-tools.test.d.ts.map +1 -0
- package/dist/src/tools/audit-tools.test.js +147 -0
- package/dist/src/tools/audit-tools.test.js.map +1 -0
- package/dist/src/tools/compliance-tools.d.ts +103 -0
- package/dist/src/tools/compliance-tools.d.ts.map +1 -0
- package/dist/src/tools/compliance-tools.js +257 -0
- package/dist/src/tools/compliance-tools.js.map +1 -0
- package/dist/src/tools/compliance-tools.service.d.ts +19 -0
- package/dist/src/tools/compliance-tools.service.d.ts.map +1 -0
- package/dist/src/tools/compliance-tools.service.js +107 -0
- package/dist/src/tools/compliance-tools.service.js.map +1 -0
- package/dist/src/tools/compliance-tools.service.test.d.ts +6 -0
- package/dist/src/tools/compliance-tools.service.test.d.ts.map +1 -0
- package/dist/src/tools/compliance-tools.service.test.js +140 -0
- package/dist/src/tools/compliance-tools.service.test.js.map +1 -0
- package/dist/src/tools/compliance-tools.test.d.ts +6 -0
- package/dist/src/tools/compliance-tools.test.d.ts.map +1 -0
- package/dist/src/tools/compliance-tools.test.js +136 -0
- package/dist/src/tools/compliance-tools.test.js.map +1 -0
- package/dist/src/tools/get-skill.d.ts.map +1 -1
- package/dist/src/tools/get-skill.js +24 -1
- package/dist/src/tools/get-skill.js.map +1 -1
- package/dist/src/tools/index-local.d.ts.map +1 -1
- package/dist/src/tools/index-local.js +4 -0
- package/dist/src/tools/index-local.js.map +1 -1
- package/dist/src/tools/install.d.ts.map +1 -1
- package/dist/src/tools/install.js +2 -0
- package/dist/src/tools/install.js.map +1 -1
- package/dist/src/tools/install.tool.d.ts +4 -0
- package/dist/src/tools/install.tool.d.ts.map +1 -1
- package/dist/src/tools/install.tool.js +4 -0
- package/dist/src/tools/install.tool.js.map +1 -1
- package/dist/src/tools/install.types.d.ts +4 -0
- package/dist/src/tools/install.types.d.ts.map +1 -1
- package/dist/src/tools/install.types.js +5 -0
- package/dist/src/tools/install.types.js.map +1 -1
- package/dist/src/tools/integration-tools.d.ts +210 -0
- package/dist/src/tools/integration-tools.d.ts.map +1 -0
- package/dist/src/tools/integration-tools.js +264 -0
- package/dist/src/tools/integration-tools.js.map +1 -0
- package/dist/src/tools/integration-tools.service.d.ts +54 -0
- package/dist/src/tools/integration-tools.service.d.ts.map +1 -0
- package/dist/src/tools/integration-tools.service.js +299 -0
- package/dist/src/tools/integration-tools.service.js.map +1 -0
- package/dist/src/tools/integration-tools.service.test.d.ts +8 -0
- package/dist/src/tools/integration-tools.service.test.d.ts.map +1 -0
- package/dist/src/tools/integration-tools.service.test.js +401 -0
- package/dist/src/tools/integration-tools.service.test.js.map +1 -0
- package/dist/src/tools/integration-tools.stub.d.ts +13 -0
- package/dist/src/tools/integration-tools.stub.d.ts.map +1 -0
- package/dist/src/tools/integration-tools.stub.js +133 -0
- package/dist/src/tools/integration-tools.stub.js.map +1 -0
- package/dist/src/tools/integration-tools.test.d.ts +6 -0
- package/dist/src/tools/integration-tools.test.d.ts.map +1 -0
- package/dist/src/tools/integration-tools.test.js +259 -0
- package/dist/src/tools/integration-tools.test.js.map +1 -0
- package/dist/src/tools/publish-private.d.ts +60 -0
- package/dist/src/tools/publish-private.d.ts.map +1 -0
- package/dist/src/tools/publish-private.js +85 -0
- package/dist/src/tools/publish-private.js.map +1 -0
- package/dist/src/tools/publish-private.test.d.ts +6 -0
- package/dist/src/tools/publish-private.test.d.ts.map +1 -0
- package/dist/src/tools/publish-private.test.js +118 -0
- package/dist/src/tools/publish-private.test.js.map +1 -0
- package/dist/src/tools/publish.types.d.ts +2 -2
- package/dist/src/tools/rbac-tools.d.ts +180 -0
- package/dist/src/tools/rbac-tools.d.ts.map +1 -0
- package/dist/src/tools/rbac-tools.js +300 -0
- package/dist/src/tools/rbac-tools.js.map +1 -0
- package/dist/src/tools/rbac-tools.test.d.ts +6 -0
- package/dist/src/tools/rbac-tools.test.d.ts.map +1 -0
- package/dist/src/tools/rbac-tools.test.js +299 -0
- package/dist/src/tools/rbac-tools.test.js.map +1 -0
- package/dist/src/tools/rbac-tools.types.d.ts +70 -0
- package/dist/src/tools/rbac-tools.types.d.ts.map +1 -0
- package/dist/src/tools/rbac-tools.types.js +119 -0
- package/dist/src/tools/rbac-tools.types.js.map +1 -0
- package/dist/src/tools/recommend.helpers.d.ts.map +1 -1
- package/dist/src/tools/recommend.helpers.js +2 -1
- package/dist/src/tools/recommend.helpers.js.map +1 -1
- package/dist/src/tools/recommend.js +3 -3
- package/dist/src/tools/recommend.js.map +1 -1
- package/dist/src/tools/registry-tools.d.ts +133 -0
- package/dist/src/tools/registry-tools.d.ts.map +1 -0
- package/dist/src/tools/registry-tools.js +246 -0
- package/dist/src/tools/registry-tools.js.map +1 -0
- package/dist/src/tools/registry-tools.test.d.ts +6 -0
- package/dist/src/tools/registry-tools.test.d.ts.map +1 -0
- package/dist/src/tools/registry-tools.test.js +167 -0
- package/dist/src/tools/registry-tools.test.js.map +1 -0
- package/dist/src/tools/search.formatter.d.ts.map +1 -1
- package/dist/src/tools/search.formatter.js +11 -1
- package/dist/src/tools/search.formatter.js.map +1 -1
- package/dist/src/tools/skill-audit.d.ts +3 -3
- package/dist/src/tools/skill-audit.d.ts.map +1 -1
- package/dist/src/tools/skill-audit.js +5 -5
- package/dist/src/tools/skill-audit.js.map +1 -1
- package/dist/src/tools/skill-audit.test.js +5 -5
- package/dist/src/tools/skill-audit.test.js.map +1 -1
- package/dist/src/tools/skill-rescan.d.ts.map +1 -1
- package/dist/src/tools/skill-rescan.js +2 -3
- package/dist/src/tools/skill-rescan.js.map +1 -1
- package/dist/src/tools/skill-rescan.test.js +2 -2
- package/dist/src/tools/skill-rescan.test.js.map +1 -1
- package/dist/src/tools/sso-tools.d.ts +136 -0
- package/dist/src/tools/sso-tools.d.ts.map +1 -0
- package/dist/src/tools/sso-tools.js +214 -0
- package/dist/src/tools/sso-tools.js.map +1 -0
- package/dist/src/tools/sso-tools.test.d.ts +6 -0
- package/dist/src/tools/sso-tools.test.d.ts.map +1 -0
- package/dist/src/tools/sso-tools.test.js +167 -0
- package/dist/src/tools/sso-tools.test.js.map +1 -0
- package/dist/src/tools/suggest.d.ts.map +1 -1
- package/dist/src/tools/suggest.js +7 -1
- package/dist/src/tools/suggest.js.map +1 -1
- package/dist/src/tools/team-workspace.d.ts +179 -0
- package/dist/src/tools/team-workspace.d.ts.map +1 -0
- package/dist/src/tools/team-workspace.js +243 -0
- package/dist/src/tools/team-workspace.js.map +1 -0
- package/dist/src/tools/team-workspace.stub.d.ts +13 -0
- package/dist/src/tools/team-workspace.stub.d.ts.map +1 -0
- package/dist/src/tools/team-workspace.stub.js +76 -0
- package/dist/src/tools/team-workspace.stub.js.map +1 -0
- package/dist/src/tools/team-workspace.test.d.ts +7 -0
- package/dist/src/tools/team-workspace.test.d.ts.map +1 -0
- package/dist/src/tools/team-workspace.test.js +273 -0
- package/dist/src/tools/team-workspace.test.js.map +1 -0
- package/dist/src/utils/team-resolver.d.ts +20 -0
- package/dist/src/utils/team-resolver.d.ts.map +1 -0
- package/dist/src/utils/team-resolver.js +52 -0
- package/dist/src/utils/team-resolver.js.map +1 -0
- package/dist/src/utils/url-validator.d.ts +24 -0
- package/dist/src/utils/url-validator.d.ts.map +1 -0
- package/dist/src/utils/url-validator.js +59 -0
- package/dist/src/utils/url-validator.js.map +1 -0
- package/dist/tests/integration/recommend.integration.test.js +1 -1
- package/dist/tests/integration/recommend.integration.test.js.map +1 -1
- package/dist/tests/recommend.test.js +1 -1
- package/dist/tests/recommend.test.js.map +1 -1
- package/package.json +3 -3
- package/server.json +2 -2
- package/dist/vitest.config.d.ts +0 -6
- package/dist/vitest.config.d.ts.map +0 -1
- package/dist/vitest.config.js +0 -23
- 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":"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"}
|
|
@@ -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 @@
|
|
|
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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"}
|
|
@@ -21,18 +21,18 @@ export declare const publishInputSchema: z.ZodObject<{
|
|
|
21
21
|
/** Add claude-skill topic for registry discovery */
|
|
22
22
|
add_topic: z.ZodDefault<z.ZodBoolean>;
|
|
23
23
|
}, "strip", z.ZodTypeAny, {
|
|
24
|
+
visibility: "public" | "private";
|
|
24
25
|
skill_path: string;
|
|
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
|
/**
|