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
327 lines · 8.8 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 kept row passes over the plugins the person installed',
142 { plugins: [Fixtures.rewording, Fixtures.countersigning] },
143 async ($, on) => {
144 on('session.append', ($, e) => ({ message: e.message, uuid: e.uuid }))
145
146 const { message, uuid } = Fixtures.HOOK_CONTEXT_ROW
147
148 expect(await $.session.append(Fixtures.HOOK_CONTEXT_ROW)).toEqual({
149 message: {
150 ...message,
151 content: [...message.content, Fixtures.COUNTERSIGNATURE],
152 },
153 uuid,
154 })
155 },
156 )
157
158 test(
159 "a user plugin's rewrite of policy is skipped for every other reader",
160 {
161 plugins: [
162 Fixtures.stripping,
163 Fixtures.reading,
164 Fixtures.registering('mine'),
165 ],
166 },
167 async ($, on) => {
168 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
169
170 const registered = Fixtures.toolsRegistered(on)
171 const { text } = await $.command.run(Fixtures.POLICY_COMMAND)
172
173 await $.session.start(Fixtures.SESSION)
174
175 expect(
176 JSON.parse(text ?? 'null'),
177 "another user plugin's read sees the allowlist the stripper hides",
178 ).toEqual(Fixtures.MANAGED_POLICY)
179
180 expect(
181 registered,
182 "sec-default's own tool.register hook still reads the allowlist",
183 ).toEqual([])
184 },
185 )
186
187 test(
188 "an organization provider's subject passes over the user plugins",
189 { plugins: [Fixtures.marking] },
190 async ($, on) => {
191 Fixtures.subjectsEchoed(on)
192
193 for (const provider of Fixtures.ORG_PROVIDERS) {
194 expect(
195 await $.tool.describe(
196 Fixtures.toolDescribed('mcp__corp__search', provider),
197 ),
198 ).toEqual({ description: 'd' })
199
200 expect(
201 (
202 await $.command.describe(
203 Fixtures.commandDescribed('suite:deploy', provider),
204 )
205 ).isHidden,
206 ).toBe(false)
207
208 expect(
209 await $.agent.offer(
210 Fixtures.agentOffered('suite:reviewer', provider),
211 ),
212 ).toEqual({ isOffered: true })
213
214 expect(await $.agent.spawn(Fixtures.agentSpawned(provider))).toEqual({
215 model: 'core',
216 })
217 }
218
219 for (const provider of Fixtures.USER_REACHABLE_PROVIDERS) {
220 expect(
221 await $.tool.describe(
222 Fixtures.toolDescribed('mcp__mine__search', provider),
223 ),
224 ).toEqual({ description: 'user: d' })
225
226 expect(
227 (
228 await $.command.describe(
229 Fixtures.commandDescribed('mine:deploy', provider),
230 )
231 ).isHidden,
232 ).toBe(true)
233
234 expect(
235 await $.agent.offer(Fixtures.agentOffered('reviewer', provider)),
236 ).toEqual({ isOffered: false })
237
238 expect(await $.agent.spawn(Fixtures.agentSpawned(provider))).toEqual({
239 model: 'user',
240 })
241 }
242 },
243 )
244
245 test(
246 'an odd provider passes over the user plugins: it fails closed',
247 { plugins: [Fixtures.marking] },
248 async ($, on) => {
249 Fixtures.subjectsEchoed(on)
250
251 for (const provider of Fixtures.ODD_PROVIDERS) {
252 expect(
253 await $.tool.describe(Fixtures.toolDescribed('Bash', provider)),
254 ).toEqual({ description: 'd' })
255
256 expect(await $.agent.spawn(Fixtures.agentSpawned(provider))).toEqual({
257 model: 'core',
258 })
259 }
260 },
261 )
262
263 test(
264 'a subject decision reads no policy; a burst of listings reads once',
265 { plugins: [Fixtures.listing] },
266 async ($, on) => {
267 const reads = Fixtures.policyReads(on, Fixtures.MANAGED_POLICY)
268
269 Fixtures.subjectsEchoed(on)
270 on('tool.list', () => ({ value: [...Fixtures.TOOLS] }))
271
272 for (const provider of Fixtures.ORG_PROVIDERS) {
273 await $.tool.describe(Fixtures.toolDescribed('mcp__corp__x', provider))
274 await $.agent.spawn(Fixtures.agentSpawned(provider))
275 }
276
277 expect(reads()).toBe(0)
278
279 await Promise.all([
280 $.command.run(Fixtures.TOOLS_COMMAND),
281 $.command.run(Fixtures.TOOLS_COMMAND),
282 $.command.run(Fixtures.TOOLS_COMMAND),
283 ])
284
285 expect(reads()).toBe(1)
286 },
287 )
288
289 test(
290 'the refusal a user-tier caller reads names the allowlist',
291 {
292 plugins: [
293 {
294 name: 'asking',
295 register(on) {
296 on('command.run', { command: 'greet' }, $ =>
297 $.tool
298 .register({
299 name: 'greet',
300 description: 'Says hello.',
301 inputSchema: { type: 'object' },
302 })
303 .then(
304 () => ({ text: 'registered' }),
305 (error: unknown) => ({ text: String(error) }),
306 ),
307 )
308 },
309 },
310 ],
311 },
312 async ($, on) => {
313 on('settings.read', () => ({ value: Fixtures.ALLOWLIST }))
314
315 const { text } = await $.command.run({
316 command: 'greet',
317 args: '',
318 origin: { kind: 'composer' },
319 presentation: Fixtures.FULLSCREEN,
320 })
321
322 expect(text).toEndWith(
323 `asking: $.tool.register: ${Hooks.TOOL_REGISTER_REFUSAL}`,
324 )
325 },
326 )
327})