spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

claude-code / mods / sec-default / tests / register.test.ts
340 lines · 9.1 KBRaw
1import { describe, expect, test, tier } from 'claude-code/testing'
2
3import Hooks from '../hooks'
4import Fixtures from './fixtures'
5
6tier('prepend')
7
8describe('register', () => {
9 test(
10 'under an MCP allowlist a plugin the person installed may not add a tool',
11 {
12 plugins: [
13 Fixtures.registering('suite', 'prepend'),
14 Fixtures.registering('mine'),
15 Fixtures.registering('bundled', 'builtin'),
16 ],
17 },
18 async ($, on) => {
19 on('settings.read', () => ({ value: Fixtures.ALLOWLIST }))
20
21 const registered = Fixtures.toolsRegistered(on)
22
23 await $.session.start(Fixtures.SESSION)
24
25 expect(registered).toEqual(['suite', 'bundled'])
26 },
27 )
28
29 test(
30 'with no allowlist, a plugin the person installed adds its tool',
31 { plugins: [Fixtures.registering('mine')] },
32 async ($, on) => {
33 on('settings.read', () => ({ value: Fixtures.NO_ALLOWLIST }))
34
35 const registered = Fixtures.toolsRegistered(on)
36
37 await $.session.start(Fixtures.SESSION)
38
39 expect(registered).toEqual(['mine'])
40 },
41 )
42
43 test(
44 "an organization's registration passes over a refusing user plugin",
45 {
46 plugins: [
47 Fixtures.registering('suite', 'prepend'),
48 Fixtures.denying,
49 Fixtures.registering('bundled', 'builtin'),
50 ],
51 },
52 async ($, on) => {
53 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
54
55 const registered = Fixtures.toolsRegistered(on)
56
57 await $.session.start(Fixtures.SESSION)
58
59 expect(
60 registered,
61 "a built-in's registration still meets the user's deny",
62 ).toEqual(['suite'])
63 },
64 )
65
66 test(
67 'a policy that cannot be read counts as one in force',
68 { plugins: [Fixtures.registering('mine')] },
69 async ($, on) => {
70 on('settings.read', () => ({ deny: 'managed settings unreadable' }))
71
72 const registered = Fixtures.toolsRegistered(on)
73
74 await $.session.start(Fixtures.SESSION)
75
76 expect(registered).toEqual([])
77 },
78 )
79
80 test(
81 'the organization tools are listed as its tiers listed them',
82 { plugins: [Fixtures.relabeling, Fixtures.listing] },
83 async ($, on) => {
84 on('settings.read', () => ({ value: Fixtures.ALLOWLIST }))
85 on('tool.list', () => ({ value: [...Fixtures.TOOLS] }))
86
87 const { text } = await $.command.run(Fixtures.TOOLS_COMMAND)
88
89 expect(text?.split('\n')).toEqual([
90 'mcp__corp__search: Searches the corp wiki.',
91 'Bash: relabeled',
92 ])
93 },
94 )
95
96 test(
97 'a server policy delivers itself counts as a tool policy, unlisted',
98 { plugins: [Fixtures.relabeling, Fixtures.listing] },
99 async ($, on) => {
100 on('settings.read', () => ({ value: Fixtures.SERVER_POLICY }))
101 on('tool.list', () => ({ value: [...Fixtures.TOOLS] }))
102
103 const { text } = await $.command.run(Fixtures.TOOLS_COMMAND)
104
105 expect(text?.split('\n')).toEqual([
106 'mcp__corp__search: Searches the corp wiki.',
107 'Bash: relabeled',
108 ])
109 },
110 )
111
112 test(
113 "with no policy to read the organization's listing stands whole",
114 { plugins: [Fixtures.relabeling, Fixtures.listing] },
115 async ($, on) => {
116 on('settings.read', () => ({ deny: 'settings unreadable' }))
117 on('tool.list', () => ({ value: [...Fixtures.TOOLS] }))
118
119 const { text } = await $.command.run(Fixtures.TOOLS_COMMAND)
120
121 expect(text?.split('\n')).toEqual([
122 'mcp__corp__search: Searches the corp wiki.',
123 'Bash: Runs a command.',
124 ])
125 },
126 )
127
128 test(
129 'a prompt section passes over the plugins the person installed',
130 { plugins: [Fixtures.dropping, Fixtures.signing] },
131 async ($, on) => {
132 on('prompt.section', ($, e) => ({ text: e.text }))
133
134 expect(await $.prompt.section(Fixtures.MEMORY)).toEqual({
135 text: 'the org says hi (signed)',
136 })
137 },
138 )
139
140 test(
141 'a collector record passes over the plugins the person installed',
142 { plugins: [Fixtures.withholding] },
143 async ($, on) => {
144 const reached: unknown[] = []
145 on('telemetry.log', { to: 'collector' }, ($, e) => {
146 reached.push([e.event, e.to === 'collector' && e.attributes.edited])
147
148 return { value: undefined }
149 })
150
151 await $.telemetry.log({
152 to: 'collector',
153 event: 'kept',
154 attributes: {},
155 loggedAt: '2026-09-26T10:00:00.000Z',
156 })
157 await $.telemetry.log({
158 to: 'collector',
159 event: 'withheld',
160 attributes: {},
161 loggedAt: '2026-09-26T10:00:01.000Z',
162 })
163
164 expect(reached).toEqual([
165 ['kept', undefined],
166 ['withheld', undefined],
167 ])
168 },
169 )
170
171 test(
172 "a user plugin's rewrite of policy is skipped for every other reader",
173 {
174 plugins: [
175 Fixtures.stripping,
176 Fixtures.reading,
177 Fixtures.registering('mine'),
178 ],
179 },
180 async ($, on) => {
181 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
182
183 const registered = Fixtures.toolsRegistered(on)
184 const { text } = await $.command.run(Fixtures.POLICY_COMMAND)
185
186 await $.session.start(Fixtures.SESSION)
187
188 expect(
189 JSON.parse(text ?? 'null'),
190 "another user plugin's read sees the allowlist the stripper hides",
191 ).toEqual(Fixtures.MANAGED_POLICY)
192
193 expect(
194 registered,
195 "sec-default's own tool.register hook still reads the allowlist",
196 ).toEqual([])
197 },
198 )
199
200 test(
201 "an organization provider's subject passes over the user plugins",
202 { plugins: [Fixtures.marking] },
203 async ($, on) => {
204 Fixtures.subjectsEchoed(on)
205
206 for (const provider of Fixtures.ORG_PROVIDERS) {
207 expect(
208 await $.tool.describe(
209 Fixtures.toolDescribed('mcp__corp__search', provider),
210 ),
211 ).toEqual({ description: 'd' })
212
213 expect(
214 (
215 await $.command.describe(
216 Fixtures.commandDescribed('suite:deploy', provider),
217 )
218 ).isHidden,
219 ).toBe(false)
220
221 expect(
222 await $.agent.offer(
223 Fixtures.agentOffered('suite:reviewer', provider),
224 ),
225 ).toEqual({ isOffered: true })
226
227 expect(await $.agent.spawn(Fixtures.agentSpawned(provider))).toEqual({
228 model: 'core',
229 })
230 }
231
232 for (const provider of Fixtures.USER_REACHABLE_PROVIDERS) {
233 expect(
234 await $.tool.describe(
235 Fixtures.toolDescribed('mcp__mine__search', provider),
236 ),
237 ).toEqual({ description: 'user: d' })
238
239 expect(
240 (
241 await $.command.describe(
242 Fixtures.commandDescribed('mine:deploy', provider),
243 )
244 ).isHidden,
245 ).toBe(true)
246
247 expect(
248 await $.agent.offer(Fixtures.agentOffered('reviewer', provider)),
249 ).toEqual({ isOffered: false })
250
251 expect(await $.agent.spawn(Fixtures.agentSpawned(provider))).toEqual({
252 model: 'user',
253 })
254 }
255 },
256 )
257
258 test(
259 'an odd provider passes over the user plugins: it fails closed',
260 { plugins: [Fixtures.marking] },
261 async ($, on) => {
262 Fixtures.subjectsEchoed(on)
263
264 for (const provider of Fixtures.ODD_PROVIDERS) {
265 expect(
266 await $.tool.describe(Fixtures.toolDescribed('Bash', provider)),
267 ).toEqual({ description: 'd' })
268
269 expect(await $.agent.spawn(Fixtures.agentSpawned(provider))).toEqual({
270 model: 'core',
271 })
272 }
273 },
274 )
275
276 test(
277 'a subject decision reads no policy; a burst of listings reads once',
278 { plugins: [Fixtures.listing] },
279 async ($, on) => {
280 const reads = Fixtures.policyReads(on, Fixtures.MANAGED_POLICY)
281
282 Fixtures.subjectsEchoed(on)
283 on('tool.list', () => ({ value: [...Fixtures.TOOLS] }))
284
285 for (const provider of Fixtures.ORG_PROVIDERS) {
286 await $.tool.describe(Fixtures.toolDescribed('mcp__corp__x', provider))
287 await $.agent.spawn(Fixtures.agentSpawned(provider))
288 }
289
290 expect(reads()).toBe(0)
291
292 await Promise.all([
293 $.command.run(Fixtures.TOOLS_COMMAND),
294 $.command.run(Fixtures.TOOLS_COMMAND),
295 $.command.run(Fixtures.TOOLS_COMMAND),
296 ])
297
298 expect(reads()).toBe(1)
299 },
300 )
301
302 test(
303 'the refusal a user-tier caller reads names the allowlist',
304 {
305 plugins: [
306 {
307 name: 'asking',
308 register(on) {
309 on('command.run', { command: 'greet' }, $ =>
310 $.tool
311 .register({
312 name: 'greet',
313 description: 'Says hello.',
314 inputSchema: { type: 'object' },
315 })
316 .then(
317 () => ({ text: 'registered' }),
318 (error: unknown) => ({ text: String(error) }),
319 ),
320 )
321 },
322 },
323 ],
324 },
325 async ($, on) => {
326 on('settings.read', () => ({ value: Fixtures.ALLOWLIST }))
327
328 const { text } = await $.command.run({
329 command: 'greet',
330 args: '',
331 origin: { kind: 'composer' },
332 presentation: Fixtures.FULLSCREEN,
333 })
334
335 expect(text).toEndWith(
336 `asking: $.tool.register: ${Hooks.TOOL_REGISTER_REFUSAL}`,
337 )
338 },
339 )
340})