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