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