@skillsmith/mcp-server 0.5.1 → 0.5.3
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 +32 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/src/__tests__/LocalIndexer.empty-dir.test.d.ts +21 -0
- package/dist/src/__tests__/LocalIndexer.empty-dir.test.d.ts.map +1 -0
- package/dist/src/__tests__/LocalIndexer.empty-dir.test.js +38 -0
- package/dist/src/__tests__/LocalIndexer.empty-dir.test.js.map +1 -0
- package/dist/src/__tests__/get-skill.test.js +5 -0
- package/dist/src/__tests__/get-skill.test.js.map +1 -1
- package/dist/src/__tests__/recommend-online-path.test.js +2 -0
- package/dist/src/__tests__/recommend-online-path.test.js.map +1 -1
- package/dist/src/__tests__/recommend.test.js +10 -2
- package/dist/src/__tests__/recommend.test.js.map +1 -1
- package/dist/src/__tests__/search-installable.test.d.ts +11 -0
- package/dist/src/__tests__/search-installable.test.d.ts.map +1 -0
- package/dist/src/__tests__/search-installable.test.js +154 -0
- package/dist/src/__tests__/search-installable.test.js.map +1 -0
- package/dist/src/__tests__/search-online-path.test.js +1 -0
- package/dist/src/__tests__/search-online-path.test.js.map +1 -1
- package/dist/src/__tests__/search.test.js +3 -0
- package/dist/src/__tests__/search.test.js.map +1 -1
- package/dist/src/cli-flags.d.ts +20 -0
- package/dist/src/cli-flags.d.ts.map +1 -0
- package/dist/src/cli-flags.js +36 -0
- package/dist/src/cli-flags.js.map +1 -0
- package/dist/src/index.js +23 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/middleware/license.gate.d.ts +2 -2
- package/dist/src/middleware/license.gate.d.ts.map +1 -1
- package/dist/src/middleware/license.gate.js +43 -1
- package/dist/src/middleware/license.gate.js.map +1 -1
- package/dist/src/middleware/telemetry-consent.d.ts +88 -0
- package/dist/src/middleware/telemetry-consent.d.ts.map +1 -0
- package/dist/src/middleware/telemetry-consent.js +177 -0
- package/dist/src/middleware/telemetry-consent.js.map +1 -0
- package/dist/src/middleware/telemetry-consent.test.d.ts +12 -0
- package/dist/src/middleware/telemetry-consent.test.d.ts.map +1 -0
- package/dist/src/middleware/telemetry-consent.test.js +291 -0
- package/dist/src/middleware/telemetry-consent.test.js.map +1 -0
- package/dist/src/tools/LocalSkillSearch.d.ts.map +1 -1
- package/dist/src/tools/LocalSkillSearch.js +3 -0
- package/dist/src/tools/LocalSkillSearch.js.map +1 -1
- package/dist/src/tools/__meta__/telemetry-coverage.test.d.ts +25 -0
- package/dist/src/tools/__meta__/telemetry-coverage.test.d.ts.map +1 -0
- package/dist/src/tools/__meta__/telemetry-coverage.test.js +210 -0
- package/dist/src/tools/__meta__/telemetry-coverage.test.js.map +1 -0
- package/dist/src/tools/analytics.d.ts +15 -28
- package/dist/src/tools/analytics.d.ts.map +1 -1
- package/dist/src/tools/analytics.js +26 -4
- package/dist/src/tools/analytics.js.map +1 -1
- package/dist/src/tools/analytics.supabase.service.d.ts +103 -0
- package/dist/src/tools/analytics.supabase.service.d.ts.map +1 -0
- package/dist/src/tools/analytics.supabase.service.js +171 -0
- package/dist/src/tools/analytics.supabase.service.js.map +1 -0
- package/dist/src/tools/analytics.supabase.service.test.d.ts +10 -0
- package/dist/src/tools/analytics.supabase.service.test.d.ts.map +1 -0
- package/dist/src/tools/analytics.supabase.service.test.js +375 -0
- package/dist/src/tools/analytics.supabase.service.test.js.map +1 -0
- package/dist/src/tools/analyze.d.ts +6 -19
- package/dist/src/tools/analyze.d.ts.map +1 -1
- package/dist/src/tools/analyze.js +8 -1
- package/dist/src/tools/analyze.js.map +1 -1
- package/dist/src/tools/apply-namespace-rename.d.ts +1 -8
- package/dist/src/tools/apply-namespace-rename.d.ts.map +1 -1
- package/dist/src/tools/apply-namespace-rename.js +8 -1
- package/dist/src/tools/apply-namespace-rename.js.map +1 -1
- package/dist/src/tools/apply-recommended-edit.d.ts +1 -6
- package/dist/src/tools/apply-recommended-edit.d.ts.map +1 -1
- package/dist/src/tools/apply-recommended-edit.js +8 -1
- package/dist/src/tools/apply-recommended-edit.js.map +1 -1
- package/dist/src/tools/audit-tools.d.ts +20 -3
- package/dist/src/tools/audit-tools.d.ts.map +1 -1
- package/dist/src/tools/audit-tools.js +20 -3
- package/dist/src/tools/audit-tools.js.map +1 -1
- package/dist/src/tools/compare.d.ts +7 -23
- package/dist/src/tools/compare.d.ts.map +1 -1
- package/dist/src/tools/compare.js +12 -5
- package/dist/src/tools/compare.js.map +1 -1
- package/dist/src/tools/compare.types.js +3 -3
- package/dist/src/tools/compare.types.js.map +1 -1
- package/dist/src/tools/compliance-tools.d.ts +5 -1
- package/dist/src/tools/compliance-tools.d.ts.map +1 -1
- package/dist/src/tools/compliance-tools.js +8 -1
- package/dist/src/tools/compliance-tools.js.map +1 -1
- package/dist/src/tools/get-skill.d.ts +6 -25
- package/dist/src/tools/get-skill.d.ts.map +1 -1
- package/dist/src/tools/get-skill.js +30 -10
- package/dist/src/tools/get-skill.js.map +1 -1
- package/dist/src/tools/index-local.d.ts +1 -15
- package/dist/src/tools/index-local.d.ts.map +1 -1
- package/dist/src/tools/index-local.js +8 -1
- package/dist/src/tools/index-local.js.map +1 -1
- package/dist/src/tools/install.d.ts +1 -17
- package/dist/src/tools/install.d.ts.map +1 -1
- package/dist/src/tools/install.js +8 -1
- package/dist/src/tools/install.js.map +1 -1
- package/dist/src/tools/install.tool.js +1 -1
- package/dist/src/tools/install.tool.js.map +1 -1
- package/dist/src/tools/integration-tools.d.ts +14 -2
- package/dist/src/tools/integration-tools.d.ts.map +1 -1
- package/dist/src/tools/integration-tools.js +14 -2
- package/dist/src/tools/integration-tools.js.map +1 -1
- package/dist/src/tools/outdated.d.ts +3 -14
- package/dist/src/tools/outdated.d.ts.map +1 -1
- package/dist/src/tools/outdated.js +8 -1
- package/dist/src/tools/outdated.js.map +1 -1
- package/dist/src/tools/outdated.test.js +3 -0
- package/dist/src/tools/outdated.test.js.map +1 -1
- package/dist/src/tools/publish-private.d.ts +4 -7
- package/dist/src/tools/publish-private.d.ts.map +1 -1
- package/dist/src/tools/publish-private.js +8 -1
- package/dist/src/tools/publish-private.js.map +1 -1
- package/dist/src/tools/publish.d.ts +9 -11
- package/dist/src/tools/publish.d.ts.map +1 -1
- package/dist/src/tools/publish.js +8 -1
- package/dist/src/tools/publish.js.map +1 -1
- package/dist/src/tools/rbac-tools.d.ts +20 -3
- package/dist/src/tools/rbac-tools.d.ts.map +1 -1
- package/dist/src/tools/rbac-tools.js +20 -3
- package/dist/src/tools/rbac-tools.js.map +1 -1
- package/dist/src/tools/rbac-tools.test.js +2 -0
- package/dist/src/tools/rbac-tools.test.js.map +1 -1
- package/dist/src/tools/recommend.d.ts +9 -9
- package/dist/src/tools/recommend.d.ts.map +1 -1
- package/dist/src/tools/recommend.js +8 -1
- package/dist/src/tools/recommend.js.map +1 -1
- package/dist/src/tools/recommend.types.js +1 -1
- package/dist/src/tools/recommend.types.js.map +1 -1
- package/dist/src/tools/registry-tools.d.ts +10 -8
- package/dist/src/tools/registry-tools.d.ts.map +1 -1
- package/dist/src/tools/registry-tools.js +14 -2
- package/dist/src/tools/registry-tools.js.map +1 -1
- package/dist/src/tools/search.d.ts +9 -42
- package/dist/src/tools/search.d.ts.map +1 -1
- package/dist/src/tools/search.formatter.d.ts.map +1 -1
- package/dist/src/tools/search.formatter.js +4 -0
- package/dist/src/tools/search.formatter.js.map +1 -1
- package/dist/src/tools/search.js +51 -30
- package/dist/src/tools/search.js.map +1 -1
- package/dist/src/tools/skill-audit.d.ts +3 -13
- package/dist/src/tools/skill-audit.d.ts.map +1 -1
- package/dist/src/tools/skill-audit.js +8 -1
- package/dist/src/tools/skill-audit.js.map +1 -1
- package/dist/src/tools/skill-diff.d.ts +9 -11
- package/dist/src/tools/skill-diff.d.ts.map +1 -1
- package/dist/src/tools/skill-diff.js +8 -1
- package/dist/src/tools/skill-diff.js.map +1 -1
- package/dist/src/tools/skill-inventory-audit.d.ts +1 -6
- package/dist/src/tools/skill-inventory-audit.d.ts.map +1 -1
- package/dist/src/tools/skill-inventory-audit.js +8 -1
- package/dist/src/tools/skill-inventory-audit.js.map +1 -1
- package/dist/src/tools/skill-pack-audit.d.ts +4 -12
- package/dist/src/tools/skill-pack-audit.d.ts.map +1 -1
- package/dist/src/tools/skill-pack-audit.js +8 -1
- package/dist/src/tools/skill-pack-audit.js.map +1 -1
- package/dist/src/tools/skill-rescan.d.ts +3 -11
- package/dist/src/tools/skill-rescan.d.ts.map +1 -1
- package/dist/src/tools/skill-rescan.js +8 -1
- package/dist/src/tools/skill-rescan.js.map +1 -1
- package/dist/src/tools/skill-rescan.test.js +2 -0
- package/dist/src/tools/skill-rescan.test.js.map +1 -1
- package/dist/src/tools/skill-updates.d.ts +3 -12
- package/dist/src/tools/skill-updates.d.ts.map +1 -1
- package/dist/src/tools/skill-updates.js +8 -1
- package/dist/src/tools/skill-updates.js.map +1 -1
- package/dist/src/tools/sso-tools.d.ts +9 -8
- package/dist/src/tools/sso-tools.d.ts.map +1 -1
- package/dist/src/tools/sso-tools.js +14 -2
- package/dist/src/tools/sso-tools.js.map +1 -1
- package/dist/src/tools/suggest.d.ts +10 -18
- package/dist/src/tools/suggest.d.ts.map +1 -1
- package/dist/src/tools/suggest.js +10 -3
- package/dist/src/tools/suggest.js.map +1 -1
- package/dist/src/tools/team-workspace.d.ts +11 -16
- package/dist/src/tools/team-workspace.d.ts.map +1 -1
- package/dist/src/tools/team-workspace.js +14 -2
- package/dist/src/tools/team-workspace.js.map +1 -1
- package/dist/src/tools/uninstall.d.ts +4 -10
- package/dist/src/tools/uninstall.d.ts.map +1 -1
- package/dist/src/tools/uninstall.js +9 -2
- package/dist/src/tools/uninstall.js.map +1 -1
- package/dist/src/tools/validate.d.ts +5 -23
- package/dist/src/tools/validate.d.ts.map +1 -1
- package/dist/src/tools/validate.js +8 -1
- package/dist/src/tools/validate.js.map +1 -1
- package/dist/src/validation.d.ts +2 -2
- package/dist/src/validation.d.ts.map +1 -1
- package/dist/src/validation.js +6 -0
- package/dist/src/validation.js.map +1 -1
- package/dist/src/webhooks/stripe-webhook-endpoint.d.ts +28 -1
- package/dist/src/webhooks/stripe-webhook-endpoint.d.ts.map +1 -1
- package/dist/src/webhooks/stripe-webhook-endpoint.js.map +1 -1
- package/dist/tests/cli-flags.test.d.ts +2 -0
- package/dist/tests/cli-flags.test.d.ts.map +1 -0
- package/dist/tests/cli-flags.test.js +33 -0
- package/dist/tests/cli-flags.test.js.map +1 -0
- package/dist/tests/compare.test.js +3 -0
- package/dist/tests/compare.test.js.map +1 -1
- package/dist/tests/e2e/compare.e2e.test.js +3 -1
- package/dist/tests/e2e/compare.e2e.test.js.map +1 -1
- package/dist/tests/e2e/recommend.e2e.test.js +6 -1
- package/dist/tests/e2e/recommend.e2e.test.js.map +1 -1
- package/dist/tests/e2e/skill-flow.e2e.test.js +8 -0
- package/dist/tests/e2e/skill-flow.e2e.test.js.map +1 -1
- package/dist/tests/e2e/suggest.e2e.test.js +5 -1
- package/dist/tests/e2e/suggest.e2e.test.js.map +1 -1
- package/dist/tests/integration/analyze.integration.test.js +7 -0
- package/dist/tests/integration/analyze.integration.test.js.map +1 -1
- package/dist/tests/integration/recommend.integration.test.js +6 -0
- package/dist/tests/integration/recommend.integration.test.js.map +1 -1
- package/dist/tests/integration/validate.integration.test.js +7 -1
- package/dist/tests/integration/validate.integration.test.js.map +1 -1
- package/dist/tests/performance/search-performance.test.js +9 -1
- package/dist/tests/performance/search-performance.test.js.map +1 -1
- package/dist/tests/recommend.test.js +11 -2
- package/dist/tests/recommend.test.js.map +1 -1
- package/dist/tests/startup-probe.test.d.ts +17 -0
- package/dist/tests/startup-probe.test.d.ts.map +1 -0
- package/dist/tests/startup-probe.test.js +214 -0
- package/dist/tests/startup-probe.test.js.map +1 -0
- package/dist/tests/tool-descriptions.test.js +1 -1
- package/dist/tests/tool-descriptions.test.js.map +1 -1
- package/dist/tests/unit/skill-pack-audit.test.js +14 -1
- package/dist/tests/unit/skill-pack-audit.test.js.map +1 -1
- package/dist/tests/validate.test.js +28 -8
- package/dist/tests/validate.test.js.map +1 -1
- package/package.json +3 -11
- package/server.json +2 -2
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tests for the telemetry consent gate — SMI-5019 W2
|
|
3
|
+
*
|
|
4
|
+
* Mocking style matches analytics.supabase.service.test.ts:
|
|
5
|
+
* vi.mock('../supabase-client.js') at module scope, then
|
|
6
|
+
* vi.mocked(getSupabaseClient).mockResolvedValue / mockRejectedValue per test.
|
|
7
|
+
*
|
|
8
|
+
* `_resetConsentCacheForTests()` is called in beforeEach so every test starts
|
|
9
|
+
* with an empty process-level cache.
|
|
10
|
+
*/
|
|
11
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
12
|
+
import { resolveConsent, shouldEmitTelemetry, invalidateConsentCache, annotateResponseWithConsent, _resetConsentCacheForTests, TELEMETRY_PRIVACY_URL, } from './telemetry-consent.js';
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Supabase module mock
|
|
15
|
+
// ============================================================================
|
|
16
|
+
vi.mock('../supabase-client.js', () => ({
|
|
17
|
+
getSupabaseClient: vi.fn(),
|
|
18
|
+
}));
|
|
19
|
+
import { getSupabaseClient } from '../supabase-client.js';
|
|
20
|
+
const mockGetClient = vi.mocked(getSupabaseClient);
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Helper — build a chainable Supabase query mock
|
|
23
|
+
// ============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Creates a mock Supabase client whose `.from().select().eq().maybeSingle()`
|
|
26
|
+
* chain resolves with `resolvedValue`. Returns the `maybeSingle` spy so
|
|
27
|
+
* callers can assert call counts.
|
|
28
|
+
*/
|
|
29
|
+
function createQueryMock(resolvedValue) {
|
|
30
|
+
const maybeSingle = vi.fn().mockResolvedValue(resolvedValue);
|
|
31
|
+
const eq = vi.fn().mockReturnValue({ maybeSingle });
|
|
32
|
+
const select = vi.fn().mockReturnValue({ eq });
|
|
33
|
+
const from = vi.fn().mockReturnValue({ select });
|
|
34
|
+
const client = { from };
|
|
35
|
+
return { client, from, select, eq, maybeSingle };
|
|
36
|
+
}
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Setup
|
|
39
|
+
// ============================================================================
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
_resetConsentCacheForTests();
|
|
42
|
+
vi.clearAllMocks();
|
|
43
|
+
});
|
|
44
|
+
afterEach(() => {
|
|
45
|
+
_resetConsentCacheForTests();
|
|
46
|
+
});
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// (1) Default-no-id: empty / null / undefined anonymous_id
|
|
49
|
+
// ============================================================================
|
|
50
|
+
describe('resolveConsent — default-no-id branch', () => {
|
|
51
|
+
it('returns DEFAULT_NO_ID for empty string without querying Supabase', async () => {
|
|
52
|
+
const state = await resolveConsent('');
|
|
53
|
+
expect(state.enabled).toBe(false);
|
|
54
|
+
expect(state.consentRequired).toBe(false);
|
|
55
|
+
expect(state.privacyUrl).toBe(TELEMETRY_PRIVACY_URL);
|
|
56
|
+
expect(mockGetClient).not.toHaveBeenCalled();
|
|
57
|
+
});
|
|
58
|
+
it('returns DEFAULT_NO_ID for null without querying Supabase', async () => {
|
|
59
|
+
const state = await resolveConsent(null);
|
|
60
|
+
expect(state.enabled).toBe(false);
|
|
61
|
+
expect(state.consentRequired).toBe(false);
|
|
62
|
+
expect(mockGetClient).not.toHaveBeenCalled();
|
|
63
|
+
});
|
|
64
|
+
it('returns DEFAULT_NO_ID for undefined without querying Supabase', async () => {
|
|
65
|
+
const state = await resolveConsent(undefined);
|
|
66
|
+
expect(state.enabled).toBe(false);
|
|
67
|
+
expect(state.consentRequired).toBe(false);
|
|
68
|
+
expect(mockGetClient).not.toHaveBeenCalled();
|
|
69
|
+
});
|
|
70
|
+
it('shouldEmitTelemetry returns false for empty string', async () => {
|
|
71
|
+
expect(await shouldEmitTelemetry('')).toBe(false);
|
|
72
|
+
expect(mockGetClient).not.toHaveBeenCalled();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// (2) Unknown anonymous_id — no row in DB
|
|
77
|
+
// ============================================================================
|
|
78
|
+
describe('resolveConsent — unknown anonymous_id (no row)', () => {
|
|
79
|
+
it('returns consent_required: true when Supabase returns no row', async () => {
|
|
80
|
+
const { client } = createQueryMock({ data: null, error: null });
|
|
81
|
+
mockGetClient.mockResolvedValue(client);
|
|
82
|
+
const state = await resolveConsent('unknown-xyz');
|
|
83
|
+
expect(state.consentRequired).toBe(true);
|
|
84
|
+
expect(state.enabled).toBe(false);
|
|
85
|
+
expect(state.privacyUrl).toBe(TELEMETRY_PRIVACY_URL);
|
|
86
|
+
});
|
|
87
|
+
it('shouldEmitTelemetry returns false for unknown anonymous_id', async () => {
|
|
88
|
+
const { client } = createQueryMock({ data: null, error: null });
|
|
89
|
+
mockGetClient.mockResolvedValue(client);
|
|
90
|
+
expect(await shouldEmitTelemetry('unknown-xyz')).toBe(false);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// (3) Enabled preference
|
|
95
|
+
// ============================================================================
|
|
96
|
+
describe('resolveConsent — enabled preference', () => {
|
|
97
|
+
it('returns consentRequired: false and enabled: true when row has enabled=true', async () => {
|
|
98
|
+
const { client } = createQueryMock({ data: { enabled: true }, error: null });
|
|
99
|
+
mockGetClient.mockResolvedValue(client);
|
|
100
|
+
const state = await resolveConsent('user-abc');
|
|
101
|
+
expect(state.enabled).toBe(true);
|
|
102
|
+
expect(state.consentRequired).toBe(false);
|
|
103
|
+
expect(state.privacyUrl).toBe(TELEMETRY_PRIVACY_URL);
|
|
104
|
+
});
|
|
105
|
+
it('shouldEmitTelemetry returns true when preference is enabled', async () => {
|
|
106
|
+
const { client } = createQueryMock({ data: { enabled: true }, error: null });
|
|
107
|
+
mockGetClient.mockResolvedValue(client);
|
|
108
|
+
expect(await shouldEmitTelemetry('user-abc')).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// (4) Disabled preference
|
|
113
|
+
// ============================================================================
|
|
114
|
+
describe('resolveConsent — disabled preference', () => {
|
|
115
|
+
it('returns consentRequired: false and enabled: false when row has enabled=false', async () => {
|
|
116
|
+
const { client } = createQueryMock({ data: { enabled: false }, error: null });
|
|
117
|
+
mockGetClient.mockResolvedValue(client);
|
|
118
|
+
const state = await resolveConsent('user-abc');
|
|
119
|
+
// User has answered — no prompt needed, but telemetry is off.
|
|
120
|
+
expect(state.consentRequired).toBe(false);
|
|
121
|
+
expect(state.enabled).toBe(false);
|
|
122
|
+
});
|
|
123
|
+
it('shouldEmitTelemetry returns false when preference is disabled', async () => {
|
|
124
|
+
const { client } = createQueryMock({ data: { enabled: false }, error: null });
|
|
125
|
+
mockGetClient.mockResolvedValue(client);
|
|
126
|
+
expect(await shouldEmitTelemetry('user-abc')).toBe(false);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
// ============================================================================
|
|
130
|
+
// (5) Idempotent under concurrent calls — single in-flight query
|
|
131
|
+
// ============================================================================
|
|
132
|
+
describe('resolveConsent — concurrent call deduplication', () => {
|
|
133
|
+
it('issues exactly one Supabase query for two parallel calls on the same id', async () => {
|
|
134
|
+
const { client, maybeSingle } = createQueryMock({ data: { enabled: true }, error: null });
|
|
135
|
+
mockGetClient.mockResolvedValue(client);
|
|
136
|
+
const [s1, s2] = await Promise.all([resolveConsent('user-def'), resolveConsent('user-def')]);
|
|
137
|
+
// Both calls must have resolved to the same consent state.
|
|
138
|
+
expect(s1).toEqual(s2);
|
|
139
|
+
// The DB was only hit once — the cache stored the in-flight Promise.
|
|
140
|
+
expect(maybeSingle).toHaveBeenCalledTimes(1);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
// ============================================================================
|
|
144
|
+
// (6) Fail-safe on Supabase error
|
|
145
|
+
// ============================================================================
|
|
146
|
+
describe('resolveConsent — fail-safe on Supabase error', () => {
|
|
147
|
+
it('returns consent_required: true when maybeSingle rejects', async () => {
|
|
148
|
+
const maybeSingle = vi.fn().mockRejectedValue(new Error('network error'));
|
|
149
|
+
const eq = vi.fn().mockReturnValue({ maybeSingle });
|
|
150
|
+
const select = vi.fn().mockReturnValue({ eq });
|
|
151
|
+
const from = vi.fn().mockReturnValue({ select });
|
|
152
|
+
const client = { from };
|
|
153
|
+
mockGetClient.mockResolvedValue(client);
|
|
154
|
+
const state = await resolveConsent('user-ghi');
|
|
155
|
+
// Fail-safe: consent_required must be true — never silently emit.
|
|
156
|
+
expect(state.consentRequired).toBe(true);
|
|
157
|
+
expect(state.enabled).toBe(false);
|
|
158
|
+
});
|
|
159
|
+
it('returns consent_required: true when query returns an error object', async () => {
|
|
160
|
+
const { client } = createQueryMock({ data: null, error: { message: 'permission denied' } });
|
|
161
|
+
mockGetClient.mockResolvedValue(client);
|
|
162
|
+
const state = await resolveConsent('user-ghi');
|
|
163
|
+
expect(state.consentRequired).toBe(true);
|
|
164
|
+
expect(state.enabled).toBe(false);
|
|
165
|
+
});
|
|
166
|
+
it('shouldEmitTelemetry returns false when Supabase errors', async () => {
|
|
167
|
+
const { client } = createQueryMock({ data: null, error: { message: 'db error' } });
|
|
168
|
+
mockGetClient.mockResolvedValue(client);
|
|
169
|
+
expect(await shouldEmitTelemetry('user-ghi')).toBe(false);
|
|
170
|
+
});
|
|
171
|
+
it('returns no-id state (no prompt) when getSupabaseClient itself throws', async () => {
|
|
172
|
+
// This covers the "Supabase not configured" offline branch.
|
|
173
|
+
mockGetClient.mockRejectedValue(new Error('Supabase not configured'));
|
|
174
|
+
const state = await resolveConsent('user-ghi-offline');
|
|
175
|
+
// Offline: suppress telemetry but do NOT demand consent (no network surface).
|
|
176
|
+
expect(state.enabled).toBe(false);
|
|
177
|
+
// consentRequired is false in the offline/unconfigured branch — matches DEFAULT_NO_ID.
|
|
178
|
+
expect(state.consentRequired).toBe(false);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
// ============================================================================
|
|
182
|
+
// (7) Cache invalidation
|
|
183
|
+
// ============================================================================
|
|
184
|
+
describe('invalidateConsentCache', () => {
|
|
185
|
+
it('causes next resolveConsent call to re-query Supabase after invalidation', async () => {
|
|
186
|
+
const { client, maybeSingle } = createQueryMock({ data: { enabled: true }, error: null });
|
|
187
|
+
mockGetClient.mockResolvedValue(client);
|
|
188
|
+
// First call — populates cache.
|
|
189
|
+
await resolveConsent('user-jkl');
|
|
190
|
+
expect(maybeSingle).toHaveBeenCalledTimes(1);
|
|
191
|
+
// Invalidate.
|
|
192
|
+
invalidateConsentCache('user-jkl');
|
|
193
|
+
// Second call — must re-query.
|
|
194
|
+
await resolveConsent('user-jkl');
|
|
195
|
+
expect(maybeSingle).toHaveBeenCalledTimes(2);
|
|
196
|
+
});
|
|
197
|
+
it('does not affect cache entries for other anonymous_ids', async () => {
|
|
198
|
+
const { client, maybeSingle } = createQueryMock({ data: { enabled: true }, error: null });
|
|
199
|
+
mockGetClient.mockResolvedValue(client);
|
|
200
|
+
await resolveConsent('user-jkl');
|
|
201
|
+
await resolveConsent('user-other');
|
|
202
|
+
expect(maybeSingle).toHaveBeenCalledTimes(2);
|
|
203
|
+
invalidateConsentCache('user-jkl');
|
|
204
|
+
// Only user-jkl re-queries; user-other is still cached.
|
|
205
|
+
await resolveConsent('user-jkl');
|
|
206
|
+
await resolveConsent('user-other');
|
|
207
|
+
expect(maybeSingle).toHaveBeenCalledTimes(3);
|
|
208
|
+
});
|
|
209
|
+
it('clears entire cache when called without argument', async () => {
|
|
210
|
+
const { client, maybeSingle } = createQueryMock({ data: { enabled: true }, error: null });
|
|
211
|
+
mockGetClient.mockResolvedValue(client);
|
|
212
|
+
await resolveConsent('user-a');
|
|
213
|
+
await resolveConsent('user-b');
|
|
214
|
+
expect(maybeSingle).toHaveBeenCalledTimes(2);
|
|
215
|
+
invalidateConsentCache();
|
|
216
|
+
await resolveConsent('user-a');
|
|
217
|
+
await resolveConsent('user-b');
|
|
218
|
+
expect(maybeSingle).toHaveBeenCalledTimes(4);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
// ============================================================================
|
|
222
|
+
// (8–11) annotateResponseWithConsent
|
|
223
|
+
// ============================================================================
|
|
224
|
+
/** Minimal MCP CallToolResult-shaped envelope. */
|
|
225
|
+
function makeEnvelope(text) {
|
|
226
|
+
return { content: [{ type: 'text', text }] };
|
|
227
|
+
}
|
|
228
|
+
const UNRESOLVED_CONSENT = {
|
|
229
|
+
enabled: false,
|
|
230
|
+
consentRequired: true,
|
|
231
|
+
privacyUrl: TELEMETRY_PRIVACY_URL,
|
|
232
|
+
};
|
|
233
|
+
const RESOLVED_CONSENT = {
|
|
234
|
+
enabled: true,
|
|
235
|
+
consentRequired: false,
|
|
236
|
+
privacyUrl: TELEMETRY_PRIVACY_URL,
|
|
237
|
+
};
|
|
238
|
+
describe('annotateResponseWithConsent', () => {
|
|
239
|
+
it('(8) splices consent_required and privacy_url when consent is unresolved', () => {
|
|
240
|
+
const envelope = makeEnvelope(JSON.stringify({ result: 'ok' }));
|
|
241
|
+
const out = annotateResponseWithConsent(envelope, UNRESOLVED_CONSENT);
|
|
242
|
+
const parsed = JSON.parse(out.content[0].text);
|
|
243
|
+
expect(parsed.result).toBe('ok');
|
|
244
|
+
expect(parsed.consent_required).toBe(true);
|
|
245
|
+
expect(parsed.privacy_url).toBe(TELEMETRY_PRIVACY_URL);
|
|
246
|
+
});
|
|
247
|
+
it('(9) returns envelope unchanged when consent is resolved (passthrough)', () => {
|
|
248
|
+
const text = JSON.stringify({ result: 'ok' });
|
|
249
|
+
const envelope = makeEnvelope(text);
|
|
250
|
+
const out = annotateResponseWithConsent(envelope, RESOLVED_CONSENT);
|
|
251
|
+
// Same reference (or at minimum identical content) — nothing added.
|
|
252
|
+
expect(out).toBe(envelope);
|
|
253
|
+
const parsed = JSON.parse(out.content[0].text);
|
|
254
|
+
expect(parsed).not.toHaveProperty('consent_required');
|
|
255
|
+
});
|
|
256
|
+
it('(10) is idempotent — does not re-annotate if fields already present', () => {
|
|
257
|
+
const alreadyAnnotated = { result: 'ok', consent_required: true, privacy_url: 'https://x.y' };
|
|
258
|
+
const envelope = makeEnvelope(JSON.stringify(alreadyAnnotated));
|
|
259
|
+
const out = annotateResponseWithConsent(envelope, UNRESOLVED_CONSENT);
|
|
260
|
+
// Must return the same reference — no mutation of pre-existing annotation.
|
|
261
|
+
expect(out).toBe(envelope);
|
|
262
|
+
const parsed = JSON.parse(out.content[0].text);
|
|
263
|
+
// privacy_url should remain the original value, not overwritten.
|
|
264
|
+
expect(parsed.privacy_url).toBe('https://x.y');
|
|
265
|
+
});
|
|
266
|
+
it('(11) returns envelope unchanged when text is malformed JSON (no throw)', () => {
|
|
267
|
+
const envelope = makeEnvelope('not-valid-json{{');
|
|
268
|
+
expect(() => annotateResponseWithConsent(envelope, UNRESOLVED_CONSENT)).not.toThrow();
|
|
269
|
+
const out = annotateResponseWithConsent(envelope, UNRESOLVED_CONSENT);
|
|
270
|
+
expect(out).toBe(envelope);
|
|
271
|
+
});
|
|
272
|
+
it('returns envelope unchanged when content array is empty', () => {
|
|
273
|
+
const envelope = { content: [] };
|
|
274
|
+
const out = annotateResponseWithConsent(envelope, UNRESOLVED_CONSENT);
|
|
275
|
+
expect(out).toBe(envelope);
|
|
276
|
+
});
|
|
277
|
+
it('returns envelope unchanged when first content item is not type=text', () => {
|
|
278
|
+
const envelope = { content: [{ type: 'image', url: 'https://example.com/img.png' }] };
|
|
279
|
+
const out = annotateResponseWithConsent(envelope, UNRESOLVED_CONSENT);
|
|
280
|
+
expect(out).toBe(envelope);
|
|
281
|
+
});
|
|
282
|
+
});
|
|
283
|
+
// ============================================================================
|
|
284
|
+
// (12) Privacy URL literal
|
|
285
|
+
// ============================================================================
|
|
286
|
+
describe('TELEMETRY_PRIVACY_URL', () => {
|
|
287
|
+
it('equals the canonical consent dashboard URL', () => {
|
|
288
|
+
expect(TELEMETRY_PRIVACY_URL).toBe('https://skillsmith.app/account/telemetry');
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
//# sourceMappingURL=telemetry-consent.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-consent.test.js","sourceRoot":"","sources":["../../../src/middleware/telemetry-consent.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalSkillSearch.d.ts","sourceRoot":"","sources":["../../../src/tools/LocalSkillSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAK1E;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAK9C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,iBAAiB,
|
|
1
|
+
{"version":3,"file":"LocalSkillSearch.d.ts","sourceRoot":"","sources":["../../../src/tools/LocalSkillSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAEnB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAE,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAK1E;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAK9C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,iBAAiB,CAmB7E;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CA8B9B"}
|
|
@@ -36,6 +36,9 @@ export function localSkillToSearchResult(skill) {
|
|
|
36
36
|
trustTier: 'local',
|
|
37
37
|
score: skill.qualityScore,
|
|
38
38
|
source: 'local',
|
|
39
|
+
// SMI-4954: local skills already exist on disk in ~/.claude/skills/ — they
|
|
40
|
+
// are usable as-is and never discovery-only, so always installable:true.
|
|
41
|
+
installable: true,
|
|
39
42
|
// SMI-2759: Surface repository link for source transparency
|
|
40
43
|
repository: skill.repository || undefined,
|
|
41
44
|
// SMI-2760: Compatibility tags from frontmatter
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocalSkillSearch.js","sourceRoot":"","sources":["../../../src/tools/LocalSkillSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAE,YAAY,EAAmB,MAAM,4BAA4B,CAAA;AAE1E,0CAA0C;AAC1C,IAAI,YAAY,GAAwB,IAAI,CAAA;AAE5C;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,IAAI,YAAY,EAAE,CAAA;IACnC,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAiB;IACxD,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;QACpC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC;QAC7C,SAAS,EAAE,OAAoB;QAC/B,KAAK,EAAE,KAAK,CAAC,YAAY;QACzB,MAAM,EAAE,OAAO;QACf,4DAA4D;QAC5D,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS;QACzC,gDAAgD;QAChD,aAAa,EACX,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;KAC1F,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,OAAsB;IAEtB,MAAM,OAAO,GAAG,eAAe,EAAE,CAAA;IAEjC,2CAA2C;IAC3C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA;IAEzC,mCAAmC;IACnC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAA;IACX,CAAC;IAED,8BAA8B;IAC9B,IAAI,cAAc,GAAiB,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAA;IAE3F,yBAAyB;IACzB,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAA,CAAC,4BAA4B;QAC3E,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,IAAI,eAAe,CAAC,CAAA;IAC1F,CAAC;IAED,wBAAwB;IACxB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAC/C,MAAM,aAAa,GAAG,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACzD,OAAO,aAAa,KAAK,OAAO,CAAC,QAAQ,CAAA;QAC3C,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,sCAAsC;IACtC,OAAO,cAAc,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAA;AACrD,CAAC"}
|
|
1
|
+
{"version":3,"file":"LocalSkillSearch.js","sourceRoot":"","sources":["../../../src/tools/LocalSkillSearch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAA;AAChE,OAAO,EAAE,YAAY,EAAmB,MAAM,4BAA4B,CAAA;AAE1E,0CAA0C;AAC1C,IAAI,YAAY,GAAwB,IAAI,CAAA;AAE5C;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,YAAY,GAAG,IAAI,YAAY,EAAE,CAAA;IACnC,CAAC;IACD,OAAO,YAAY,CAAA;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAiB;IACxD,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;QACpC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,QAAQ,EAAE,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC;QAC7C,SAAS,EAAE,OAAoB;QAC/B,KAAK,EAAE,KAAK,CAAC,YAAY;QACzB,MAAM,EAAE,OAAO;QACf,2EAA2E;QAC3E,yEAAyE;QACzE,WAAW,EAAE,IAAI;QACjB,4DAA4D;QAC5D,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS;QACzC,gDAAgD;QAChD,aAAa,EACX,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;KAC1F,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAAa,EACb,OAAsB;IAEtB,MAAM,OAAO,GAAG,eAAe,EAAE,CAAA;IAEjC,2CAA2C;IAC3C,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,CAAA;IAEzC,mCAAmC;IACnC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAA;IACX,CAAC;IAED,8BAA8B;IAC9B,IAAI,cAAc,GAAiB,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAA;IAE3F,yBAAyB;IACzB,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAA,CAAC,4BAA4B;QAC3E,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,IAAI,eAAe,CAAC,CAAA;IAC1F,CAAC;IAED,wBAAwB;IACxB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;YAC/C,MAAM,aAAa,GAAG,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACzD,OAAO,aAAa,KAAK,OAAO,CAAC,QAAQ,CAAA;QAC3C,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,sCAAsC;IACtC,OAAO,cAAc,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAA;AACrD,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-5018 W2.S3 — MCP-tree telemetry coverage snapshot test.
|
|
3
|
+
*
|
|
4
|
+
* Scope: `packages/mcp-server/src/tools/` only (v1).
|
|
5
|
+
* CLI + VS Code trees are NOT checked here — they are blocked by SMI-5040
|
|
6
|
+
* (anonymous-closure incompatibility). When SMI-5040 lands this test will
|
|
7
|
+
* be extended to cover those trees.
|
|
8
|
+
*
|
|
9
|
+
* Risk guarded (plan line 798, risk #8):
|
|
10
|
+
* "A new dispatcher ships without a telemetry wrap."
|
|
11
|
+
*
|
|
12
|
+
* Strategy: explicit allowlist (40 entries) cross-checked against the live
|
|
13
|
+
* withTelemetry import-site count. Allowlist chosen over heuristic-walk
|
|
14
|
+
* because it is trivially auditable — each entry maps 1-to-1 to a
|
|
15
|
+
* `grep "= withTelemetry"` result, and the SOURCE_FILE_COUNT sentinel
|
|
16
|
+
* independently guards against drift in either direction.
|
|
17
|
+
*
|
|
18
|
+
* When you add a new dispatcher:
|
|
19
|
+
* 1. Wrap it with withTelemetry in its source file (as SMI-5017 did).
|
|
20
|
+
* 2. Add its export name to EXPECTED_DISPATCHERS below.
|
|
21
|
+
* 3. Update SOURCE_FILE_COUNT if the dispatcher lives in a new file.
|
|
22
|
+
* The test will fail in CI until all three steps are done.
|
|
23
|
+
*/
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=telemetry-coverage.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-coverage.test.d.ts","sourceRoot":"","sources":["../../../../src/tools/__meta__/telemetry-coverage.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SMI-5018 W2.S3 — MCP-tree telemetry coverage snapshot test.
|
|
3
|
+
*
|
|
4
|
+
* Scope: `packages/mcp-server/src/tools/` only (v1).
|
|
5
|
+
* CLI + VS Code trees are NOT checked here — they are blocked by SMI-5040
|
|
6
|
+
* (anonymous-closure incompatibility). When SMI-5040 lands this test will
|
|
7
|
+
* be extended to cover those trees.
|
|
8
|
+
*
|
|
9
|
+
* Risk guarded (plan line 798, risk #8):
|
|
10
|
+
* "A new dispatcher ships without a telemetry wrap."
|
|
11
|
+
*
|
|
12
|
+
* Strategy: explicit allowlist (40 entries) cross-checked against the live
|
|
13
|
+
* withTelemetry import-site count. Allowlist chosen over heuristic-walk
|
|
14
|
+
* because it is trivially auditable — each entry maps 1-to-1 to a
|
|
15
|
+
* `grep "= withTelemetry"` result, and the SOURCE_FILE_COUNT sentinel
|
|
16
|
+
* independently guards against drift in either direction.
|
|
17
|
+
*
|
|
18
|
+
* When you add a new dispatcher:
|
|
19
|
+
* 1. Wrap it with withTelemetry in its source file (as SMI-5017 did).
|
|
20
|
+
* 2. Add its export name to EXPECTED_DISPATCHERS below.
|
|
21
|
+
* 3. Update SOURCE_FILE_COUNT if the dispatcher lives in a new file.
|
|
22
|
+
* The test will fail in CI until all three steps are done.
|
|
23
|
+
*/
|
|
24
|
+
import { describe, it, expect } from 'vitest';
|
|
25
|
+
import { readdir } from 'node:fs/promises';
|
|
26
|
+
import { join } from 'node:path';
|
|
27
|
+
import { isTelemetered } from '@skillsmith/core/telemetry';
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Allowlist — every export that must be telemetry-wrapped (v1, MCP tree only)
|
|
30
|
+
// Derived by: grep -rn "^export const.*= withTelemetry" packages/mcp-server/src/tools/
|
|
31
|
+
// Count must equal SOURCE_FILE_COUNT's withTelemetry site total.
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
/**
|
|
34
|
+
* Maps source-file base name (no extension) to the list of dispatcher export
|
|
35
|
+
* names that live in that file. Both the file and every listed export must be
|
|
36
|
+
* telemetry-wrapped.
|
|
37
|
+
*
|
|
38
|
+
* Files NOT in this map are skipped even if they live under tools/:
|
|
39
|
+
* *.types.ts, *.helpers.ts, *.test.ts, *.dep.test.ts — infrastructure only.
|
|
40
|
+
* *.stub.ts, *.service.ts, *.tool.ts, *.live.ts — helpers/services, not dispatchers.
|
|
41
|
+
* merge.ts, LocalSkillSearch.ts, team-resolver.ts — pure utilities.
|
|
42
|
+
* index.ts — barrel re-export, no dispatch logic.
|
|
43
|
+
* namespace-audit/ directory — telemetry helper, not a dispatcher.
|
|
44
|
+
*
|
|
45
|
+
* ADDING A NEW DISPATCHER: append to the correct inner array, or add a new
|
|
46
|
+
* key if the dispatcher lives in a new file. Increment EXPECTED_TOTAL.
|
|
47
|
+
*/
|
|
48
|
+
const DISPATCHER_MAP = {
|
|
49
|
+
analytics: [
|
|
50
|
+
'executeTeamAnalyticsDashboard',
|
|
51
|
+
'executeTeamUsageReport',
|
|
52
|
+
'executeAnalyticsDashboard',
|
|
53
|
+
'executeUsageReport',
|
|
54
|
+
],
|
|
55
|
+
analyze: ['executeAnalyze'],
|
|
56
|
+
'apply-namespace-rename': ['applyNamespaceRename'],
|
|
57
|
+
'apply-recommended-edit': ['applyRecommendedEditTool'],
|
|
58
|
+
'audit-tools': ['executeAuditExport', 'executeAuditQuery', 'executeSiemExport'],
|
|
59
|
+
compare: ['executeCompare'],
|
|
60
|
+
'compliance-tools': ['executeComplianceReport'],
|
|
61
|
+
'get-skill': ['executeGetSkill'],
|
|
62
|
+
'index-local': ['executeIndexLocal'],
|
|
63
|
+
install: ['installSkill'],
|
|
64
|
+
'integration-tools': ['executeWebhookConfigure', 'executeApiKeyManage'],
|
|
65
|
+
outdated: ['executeOutdated'],
|
|
66
|
+
publish: ['executePublish'],
|
|
67
|
+
'publish-private': ['executePublishPrivate'],
|
|
68
|
+
'rbac-tools': ['executeRbacManage', 'executeRbacAssignRole', 'executeRbacCreatePolicy'],
|
|
69
|
+
recommend: ['executeRecommend'],
|
|
70
|
+
'registry-tools': ['executePrivateRegistryPublish', 'executePrivateRegistryManage'],
|
|
71
|
+
search: ['executeSearch'],
|
|
72
|
+
'skill-audit': ['executeSkillAudit'],
|
|
73
|
+
'skill-diff': ['executeSkillDiff'],
|
|
74
|
+
'skill-inventory-audit': ['skillInventoryAudit'],
|
|
75
|
+
'skill-pack-audit': ['executeSkillPackAudit'],
|
|
76
|
+
'skill-rescan': ['executeSkillRescan'],
|
|
77
|
+
'skill-updates': ['executeSkillUpdates'],
|
|
78
|
+
'sso-tools': ['executeConfigureSso', 'executeSsoSettings'],
|
|
79
|
+
suggest: ['executeSuggest'],
|
|
80
|
+
'team-workspace': ['executeTeamWorkspace', 'executeShareSkill'],
|
|
81
|
+
uninstall: ['uninstallSkill'],
|
|
82
|
+
validate: ['executeValidate'],
|
|
83
|
+
};
|
|
84
|
+
/** Expected total dispatcher count. Must match sum of DISPATCHER_MAP values. */
|
|
85
|
+
const EXPECTED_TOTAL = Object.values(DISPATCHER_MAP).reduce((n, arr) => n + arr.length, 0);
|
|
86
|
+
// Resolve the absolute path to the tools directory using import.meta.url so
|
|
87
|
+
// the test works regardless of cwd (CI runner vs local Docker vs worktree).
|
|
88
|
+
const TOOLS_DIR = new URL('../', import.meta.url).pathname;
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Helpers
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
/**
|
|
93
|
+
* Returns the list of .ts source files directly under TOOLS_DIR (non-recursive
|
|
94
|
+
* for the flat layer, plus the namespace-audit sub-directory is intentionally
|
|
95
|
+
* excluded). Used only for the drift-sentinel assertion.
|
|
96
|
+
*/
|
|
97
|
+
async function listToolSourceFiles() {
|
|
98
|
+
const entries = await readdir(TOOLS_DIR, { withFileTypes: true });
|
|
99
|
+
return entries
|
|
100
|
+
.filter((e) => e.isFile() && e.name.endsWith('.ts') && !e.name.endsWith('.test.ts'))
|
|
101
|
+
.map((e) => e.name);
|
|
102
|
+
}
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
// Suite
|
|
105
|
+
// ---------------------------------------------------------------------------
|
|
106
|
+
describe('SMI-5018: MCP tool telemetry coverage (v1, MCP tree only)', () => {
|
|
107
|
+
/**
|
|
108
|
+
* Sentinel: the DISPATCHER_MAP covers the expected total.
|
|
109
|
+
* This catches a copy-paste error where an entry was added to one list but
|
|
110
|
+
* not the other.
|
|
111
|
+
*/
|
|
112
|
+
it('EXPECTED_TOTAL matches sum of DISPATCHER_MAP entries', () => {
|
|
113
|
+
const actualSum = Object.values(DISPATCHER_MAP).reduce((n, arr) => n + arr.length, 0);
|
|
114
|
+
expect(actualSum).toBe(EXPECTED_TOTAL);
|
|
115
|
+
});
|
|
116
|
+
/**
|
|
117
|
+
* Main coverage assertion: for every (file, exportName) pair in
|
|
118
|
+
* DISPATCHER_MAP, dynamically import the module and call isTelemetered on
|
|
119
|
+
* the exported value.
|
|
120
|
+
*
|
|
121
|
+
* Dynamic import is used (not static) so the test can iterate the allowlist
|
|
122
|
+
* without requiring explicit top-level imports for all 40 symbols.
|
|
123
|
+
*
|
|
124
|
+
* IMPORTANT: the dispatchers are NOT called — only imported and checked.
|
|
125
|
+
* This avoids the need for a live ToolContext.
|
|
126
|
+
*/
|
|
127
|
+
it('every listed dispatcher export is telemetry-wrapped', async () => {
|
|
128
|
+
const failures = [];
|
|
129
|
+
for (const [fileBase, exportNames] of Object.entries(DISPATCHER_MAP)) {
|
|
130
|
+
// Resolve to the .js extension as Vitest resolves ESM source via the
|
|
131
|
+
// package's TypeScript source map (ts files under src/ are importable
|
|
132
|
+
// directly in Vitest without pre-compilation).
|
|
133
|
+
const modulePath = join(TOOLS_DIR, `${fileBase}.ts`);
|
|
134
|
+
let mod;
|
|
135
|
+
try {
|
|
136
|
+
mod = (await import(modulePath));
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
// If the import itself throws (e.g. a service initializer crashes),
|
|
140
|
+
// record a failure with a clear message rather than letting the whole
|
|
141
|
+
// test throw an opaque error.
|
|
142
|
+
failures.push(`[IMPORT ERROR] ${fileBase}.ts — ${err instanceof Error ? err.message : String(err)}`);
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
for (const exportName of exportNames) {
|
|
146
|
+
const exported = mod[exportName];
|
|
147
|
+
if (typeof exported !== 'function') {
|
|
148
|
+
failures.push(`${fileBase}.ts :: ${exportName} — not a function (got ${typeof exported})`);
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
// After `typeof === 'function'` narrow, TS infers `Function`; cast to
|
|
152
|
+
// the structural shape `isTelemetered` accepts (SMI-5076).
|
|
153
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
154
|
+
if (!isTelemetered(exported)) {
|
|
155
|
+
failures.push(`${fileBase}.ts :: ${exportName} — function exists but isTelemetered() returned false`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (failures.length > 0) {
|
|
160
|
+
throw new Error(`Telemetry coverage failures (${failures.length}):\n` +
|
|
161
|
+
failures.map((f) => ` • ${f}`).join('\n') +
|
|
162
|
+
'\n\nTo fix: wrap the dispatcher with withTelemetry(...) and add it to DISPATCHER_MAP.');
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
/**
|
|
166
|
+
* Drift sentinel: the DISPATCHER_MAP must have at least EXPECTED_TOTAL
|
|
167
|
+
* entries. This test catches the scenario where:
|
|
168
|
+
* - A developer adds a new withTelemetry wrap in a tool file (SMI-5017
|
|
169
|
+
* pattern), but forgets to add the export name to DISPATCHER_MAP.
|
|
170
|
+
*
|
|
171
|
+
* It works by counting the files listed in DISPATCHER_MAP against the actual
|
|
172
|
+
* tool source files on disk. A new file with dispatchers that is absent from
|
|
173
|
+
* the map will not be caught by the "every listed dispatcher" test above
|
|
174
|
+
* (which only checks known entries). This test surfaces that gap.
|
|
175
|
+
*
|
|
176
|
+
* Note: this is a lower-bound sentinel, not a strict equality check on file
|
|
177
|
+
* count — infrastructure files (*.types.ts, *.helpers.ts, etc.) are
|
|
178
|
+
* intentionally absent from DISPATCHER_MAP and will always outnumber it.
|
|
179
|
+
* The meaningful assertion is that no *dispatcher file* is silently absent.
|
|
180
|
+
*/
|
|
181
|
+
it('all files in DISPATCHER_MAP exist on disk', async () => {
|
|
182
|
+
const diskFiles = await listToolSourceFiles();
|
|
183
|
+
const diskBaseNames = new Set(diskFiles.map((f) => f.replace(/\.ts$/, '')));
|
|
184
|
+
const missingFromDisk = [];
|
|
185
|
+
for (const fileBase of Object.keys(DISPATCHER_MAP)) {
|
|
186
|
+
if (!diskBaseNames.has(fileBase)) {
|
|
187
|
+
missingFromDisk.push(`${fileBase}.ts`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (missingFromDisk.length > 0) {
|
|
191
|
+
throw new Error(`DISPATCHER_MAP references files that do not exist on disk:\n` +
|
|
192
|
+
missingFromDisk.map((f) => ` • ${f}`).join('\n') +
|
|
193
|
+
'\n\nEither the file was deleted (remove from DISPATCHER_MAP) or renamed (update the key).');
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
/**
|
|
197
|
+
* Completeness report: log the discovered dispatcher count so CI output
|
|
198
|
+
* makes it easy to see coverage at a glance without running a separate script.
|
|
199
|
+
* This test always passes — it is informational only.
|
|
200
|
+
*/
|
|
201
|
+
it('reports dispatcher coverage to CI output', () => {
|
|
202
|
+
const fileCount = Object.keys(DISPATCHER_MAP).length;
|
|
203
|
+
const dispatcherCount = EXPECTED_TOTAL;
|
|
204
|
+
// Using console.info so it appears in Vitest's verbose output.
|
|
205
|
+
console.info(`[SMI-5018] MCP telemetry coverage: ${dispatcherCount} dispatchers across ${fileCount} files.`);
|
|
206
|
+
console.info('[SMI-5018] Scope: MCP tree only (v1). CLI + VS Code: blocked by SMI-5040.');
|
|
207
|
+
expect(dispatcherCount).toBeGreaterThanOrEqual(40);
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
//# sourceMappingURL=telemetry-coverage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-coverage.test.js","sourceRoot":"","sources":["../../../../src/tools/__meta__/telemetry-coverage.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -124,32 +124,19 @@ export declare const usageReportToolSchema: {
|
|
|
124
124
|
};
|
|
125
125
|
};
|
|
126
126
|
};
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
* Enterprise analytics dashboard handler.
|
|
143
|
-
* Returns recommendation accuracy, adoption curves, and team aggregation as markdown.
|
|
144
|
-
*
|
|
145
|
-
* Uses real service when db is available, falls back to stub
|
|
146
|
-
*/
|
|
147
|
-
export declare function executeAnalyticsDashboard(input: AnalyticsDashboardInput, context: ToolContext): Promise<string>;
|
|
148
|
-
/**
|
|
149
|
-
* Enterprise usage report handler.
|
|
150
|
-
* Returns comprehensive report with all metrics as markdown (or CSV).
|
|
151
|
-
*
|
|
152
|
-
* Uses real service when db is available, falls back to stub
|
|
153
|
-
*/
|
|
154
|
-
export declare function executeUsageReport(input: UsageReportInput, context: ToolContext): Promise<string>;
|
|
127
|
+
export declare const executeTeamAnalyticsDashboard: (input: {
|
|
128
|
+
period: "7d" | "90d" | "30d";
|
|
129
|
+
}, context: ToolContext) => Promise<string>;
|
|
130
|
+
export declare const executeTeamUsageReport: (input: {
|
|
131
|
+
format: "summary" | "detailed";
|
|
132
|
+
period: "7d" | "90d" | "30d";
|
|
133
|
+
}, context: ToolContext) => Promise<string>;
|
|
134
|
+
export declare const executeAnalyticsDashboard: (input: {
|
|
135
|
+
period: "7d" | "90d" | "30d";
|
|
136
|
+
includeRecommendations: boolean;
|
|
137
|
+
}, context: ToolContext) => Promise<string>;
|
|
138
|
+
export declare const executeUsageReport: (input: {
|
|
139
|
+
format: "summary" | "detailed" | "csv";
|
|
140
|
+
period: "7d" | "90d" | "30d";
|
|
141
|
+
}, context: ToolContext) => Promise<string>;
|
|
155
142
|
//# sourceMappingURL=analytics.d.ts.map
|