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
820 lines · 22.9 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 const stopPolicy = Fixtures.policyUntilStopped(
71 on,
72 Fixtures.NO_ALLOWLIST,
73 'managed settings unreadable',
74 )
75
76 const registered = Fixtures.toolsRegistered(on)
77
78 on('prompt.section', ($, e) => ({ text: e.text }))
79
80 await $.prompt.section(Fixtures.MEMORY)
81 stopPolicy()
82 await $.session.start(Fixtures.SESSION)
83
84 expect(registered).toEqual([])
85 },
86 )
87
88 test(
89 'the organization tools are listed as its tiers listed them',
90 { plugins: [Fixtures.relabeling, Fixtures.listing] },
91 async ($, on) => {
92 on('settings.read', () => ({ value: Fixtures.ALLOWLIST }))
93 on('tool.list', () => ({ value: [...Fixtures.TOOLS] }))
94
95 const { text } = await $.command.run(Fixtures.TOOLS_COMMAND)
96
97 expect(text?.split('\n')).toEqual([
98 'mcp__corp__search: Searches the corp wiki.',
99 'Bash: relabeled',
100 ])
101 },
102 )
103
104 test(
105 'a server policy delivers itself counts as a tool policy, unlisted',
106 { plugins: [Fixtures.relabeling, Fixtures.listing] },
107 async ($, on) => {
108 on('settings.read', () => ({ value: Fixtures.SERVER_POLICY }))
109 on('tool.list', () => ({ value: [...Fixtures.TOOLS] }))
110
111 const { text } = await $.command.run(Fixtures.TOOLS_COMMAND)
112
113 expect(text?.split('\n')).toEqual([
114 'mcp__corp__search: Searches the corp wiki.',
115 'Bash: relabeled',
116 ])
117 },
118 )
119
120 test(
121 "with no policy to read the organization's listing stands whole",
122 { plugins: [Fixtures.relabeling, Fixtures.listing] },
123 async ($, on) => {
124 const stopPolicy = Fixtures.policyUntilStopped(
125 on,
126 Fixtures.ALLOWLIST,
127 'settings unreadable',
128 )
129
130 on('prompt.section', ($, e) => ({ text: e.text }))
131 on('tool.list', () => ({ value: [...Fixtures.TOOLS] }))
132
133 await $.prompt.section(Fixtures.MEMORY)
134 stopPolicy()
135
136 const { text } = await $.command.run(Fixtures.TOOLS_COMMAND)
137
138 expect(text?.split('\n')).toEqual([
139 'mcp__corp__search: Searches the corp wiki.',
140 'Bash: Runs a command.',
141 ])
142 },
143 )
144
145 test(
146 'a prompt section passes over the plugins the person installed',
147 { plugins: [Fixtures.dropping, Fixtures.signing] },
148 async ($, on) => {
149 on('settings.read', () => ({ value: Fixtures.NO_ALLOWLIST }))
150 on('prompt.section', ($, e) => ({ text: e.text }))
151
152 expect(await $.prompt.section(Fixtures.MEMORY)).toEqual({
153 text: 'the org says hi (signed)',
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 on('settings.read', () => ({ value: Fixtures.NO_ALLOWLIST }))
192 Fixtures.subjectsEchoed(on)
193
194 for (const provider of Fixtures.ORG_PROVIDERS) {
195 expect(
196 await $.tool.describe(
197 Fixtures.toolDescribed('mcp__corp__search', provider),
198 ),
199 ).toEqual({ description: 'd' })
200
201 expect(
202 (
203 await $.command.describe(
204 Fixtures.commandDescribed('suite:deploy', provider),
205 )
206 ).isHidden,
207 ).toBe(false)
208
209 expect(
210 await $.agent.offer(
211 Fixtures.agentOffered('suite:reviewer', provider),
212 ),
213 ).toEqual({ isOffered: true })
214
215 expect(await $.agent.spawn(Fixtures.agentSpawned(provider))).toEqual({
216 model: 'core',
217 })
218 }
219
220 for (const provider of Fixtures.USER_REACHABLE_PROVIDERS) {
221 expect(
222 await $.tool.describe(
223 Fixtures.toolDescribed('mcp__mine__search', provider),
224 ),
225 ).toEqual({ description: 'user: d' })
226
227 expect(
228 (
229 await $.command.describe(
230 Fixtures.commandDescribed('mine:deploy', provider),
231 )
232 ).isHidden,
233 ).toBe(true)
234
235 expect(
236 await $.agent.offer(Fixtures.agentOffered('reviewer', provider)),
237 ).toEqual({ isOffered: false })
238
239 expect(await $.agent.spawn(Fixtures.agentSpawned(provider))).toEqual({
240 model: 'user',
241 })
242 }
243 },
244 )
245
246 test(
247 'an odd provider passes over the user plugins: it fails closed',
248 { plugins: [Fixtures.marking] },
249 async ($, on) => {
250 on('settings.read', () => ({ value: Fixtures.NO_ALLOWLIST }))
251 Fixtures.subjectsEchoed(on)
252
253 for (const provider of Fixtures.ODD_PROVIDERS) {
254 expect(
255 await $.tool.describe(Fixtures.toolDescribed('Bash', provider)),
256 ).toEqual({ description: 'd' })
257
258 expect(await $.agent.spawn(Fixtures.agentSpawned(provider))).toEqual({
259 model: 'core',
260 })
261 }
262 },
263 )
264
265 test(
266 'a subject decision reads no policy; a burst of listings reads once',
267 { plugins: [Fixtures.listing] },
268 async ($, on) => {
269 const reads = Fixtures.policyReads(on, Fixtures.MANAGED_POLICY)
270
271 Fixtures.subjectsEchoed(on)
272 on('tool.list', () => ({ value: [...Fixtures.TOOLS] }))
273
274 for (const provider of Fixtures.ORG_PROVIDERS) {
275 await $.tool.describe(Fixtures.toolDescribed('mcp__corp__x', provider))
276 await $.agent.spawn(Fixtures.agentSpawned(provider))
277 }
278
279 expect(reads(), "one read: the person's plugin was admitted").toBe(1)
280
281 await Promise.all([
282 $.command.run(Fixtures.TOOLS_COMMAND),
283 $.command.run(Fixtures.TOOLS_COMMAND),
284 $.command.run(Fixtures.TOOLS_COMMAND),
285 ])
286
287 expect(reads()).toBe(2)
288 },
289 )
290
291 test(
292 'the refusal a user-tier caller reads names the allowlist',
293 {
294 plugins: [
295 {
296 name: 'asking',
297 register(on) {
298 on('command.run', { command: 'greet' }, $ =>
299 $.tool
300 .register({
301 name: 'greet',
302 description: 'Says hello.',
303 inputSchema: { type: 'object' },
304 })
305 .then(
306 () => ({ text: 'registered' }),
307 (error: unknown) => ({ text: String(error) }),
308 ),
309 )
310 },
311 },
312 ],
313 },
314 async ($, on) => {
315 on('settings.read', () => ({ value: Fixtures.ALLOWLIST }))
316
317 const { text } = await $.command.run({
318 command: 'greet',
319 args: '',
320 origin: { kind: 'composer' },
321 presentation: Fixtures.FULLSCREEN,
322 })
323
324 expect(text).toEndWith(
325 `asking: $.tool.register: ${Hooks.TOOL_REGISTER_REFUSAL}`,
326 )
327 },
328 )
329
330 test(
331 "under allowManagedModsOnly a person's mod is kept out, told why",
332 { plugins: [Fixtures.registering('mine')] },
333 async ($, on) => {
334 on('settings.read', () => ({ value: Fixtures.MANAGED_MODS_ONLY }))
335
336 const registered = Fixtures.toolsRegistered(on)
337
338 await expect($.session.start(Fixtures.SESSION)).rejects.toThrow(
339 Hooks.managedModsOnlyRefusal('mine'),
340 )
341
342 expect(registered, 'no hook of it ever ran').toEqual([])
343 },
344 )
345
346 test(
347 "under it the organization's mods and the built-ins load",
348 {
349 plugins: [
350 Fixtures.registering('suite', 'prepend'),
351 Fixtures.registering('after', 'append'),
352 Fixtures.registering('bundled', 'builtin'),
353 ],
354 },
355 async ($, on) => {
356 on('settings.read', () => ({ value: Fixtures.MANAGED_MODS_ONLY }))
357
358 const registered = Fixtures.toolsRegistered(on)
359
360 await $.session.start(Fixtures.SESSION)
361
362 expect(registered).toEqual(['suite', 'after', 'bundled'])
363 },
364 )
365
366 test(
367 'set to false, a mod the person installed loads as before',
368 { plugins: [Fixtures.registering('mine')] },
369 async ($, on) => {
370 on('settings.read', () => ({ value: Fixtures.modsPolicyOf(false) }))
371
372 const registered = Fixtures.toolsRegistered(on)
373
374 await $.session.start(Fixtures.SESSION)
375
376 expect(registered).toEqual(['mine'])
377 },
378 )
379
380 test(
381 "a person's copy under an organization mod's name is still theirs",
382 { plugins: [Fixtures.registering('suite')] },
383 async ($, on) => {
384 on('settings.read', () => ({
385 value: { ...Fixtures.MANAGED_POLICY, ...Fixtures.MANAGED_MODS_ONLY },
386 }))
387
388 const registered = Fixtures.toolsRegistered(on)
389
390 await expect($.session.start(Fixtures.SESSION)).rejects.toThrow(
391 Hooks.managedModsOnlyRefusal('suite'),
392 )
393
394 expect(registered).toEqual([])
395 },
396 )
397
398 test(
399 "only managed settings are asked: a person's own cannot loosen it",
400 { plugins: [Fixtures.registering('mine')] },
401 async ($, on) => {
402 Fixtures.policyBySource(
403 on,
404 Fixtures.MANAGED_MODS_ONLY,
405 Fixtures.modsPolicyOf(false),
406 )
407
408 const registered = Fixtures.toolsRegistered(on)
409
410 await expect($.session.start(Fixtures.SESSION)).rejects.toThrow(
411 Hooks.managedModsOnlyRefusal('mine'),
412 )
413
414 expect(registered).toEqual([])
415 },
416 )
417
418 test(
419 "nor turn it on: set only in a person's settings, it is not read",
420 { plugins: [Fixtures.registering('mine')] },
421 async ($, on) => {
422 Fixtures.policyBySource(
423 on,
424 Fixtures.NO_ALLOWLIST,
425 Fixtures.MANAGED_MODS_ONLY,
426 )
427
428 const registered = Fixtures.toolsRegistered(on)
429
430 await $.session.start(Fixtures.SESSION)
431
432 expect(registered).toEqual(['mine'])
433 },
434 )
435
436 test(
437 "a policy that cannot be read keeps a person's mod out: the hook's catch",
438 { plugins: [Fixtures.registering('mine')] },
439 async ($, on) => {
440 on('settings.read', () => ({ deny: 'managed settings unreadable' }))
441
442 const lines = Fixtures.logged(on)
443 const registered = Fixtures.toolsRegistered(on)
444
445 await expect($.session.start(Fixtures.SESSION)).rejects.toThrow(
446 Hooks.managedModsOnlyRefusal('mine'),
447 )
448
449 expect({ registered, lines }).toEqual({
450 registered: [],
451 lines: [
452 'debug: plugin.register hook failed judging mine (throw): ' +
453 'sec-default: $.settings.read: managed settings unreadable',
454 ],
455 })
456 },
457 )
458
459 test(
460 'a deny rule holds over an allow from a plugin the person installed',
461 { plugins: [Fixtures.allowing('easy')] },
462 async ($, on) => {
463 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
464
465 const lines = Fixtures.logged(on)
466
467 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
468
469 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
470
471 expect(lines).toEqual([
472 `transcript: ${Hooks.heldNotice('easy', 'Bash', 'Bash(echo *)')}`,
473 ])
474 },
475 )
476
477 test(
478 'two plugins of the person chained are each named once in a session',
479 {
480 plugins: [Fixtures.allowing('first'), Fixtures.asking('second')],
481 },
482 async ($, on) => {
483 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
484
485 const lines = Fixtures.logged(on)
486
487 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
488
489 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
490 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
491
492 expect(lines.toSorted()).toEqual([
493 `transcript: ${Hooks.heldNotice('first', 'Bash', 'Bash(echo *)')}`,
494 `transcript: ${Hooks.heldNotice('second', 'Bash', 'Bash(echo *)')}`,
495 ])
496 },
497 )
498
499 test(
500 'a deny rule turned into an ask by a plugin of the person holds too',
501 { plugins: [Fixtures.asking('easy')] },
502 async ($, on) => {
503 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
504 Fixtures.logged(on)
505 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
506
507 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
508 },
509 )
510
511 test(
512 "an organization plugin's allow over a deny rule stands, above or below",
513 {
514 plugins: [
515 Fixtures.allowing('suite', 'append'),
516 Fixtures.allowing('easy'),
517 ],
518 },
519 async ($, on) => {
520 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
521
522 const lines = Fixtures.logged(on)
523
524 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
525
526 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.ALLOWED)
527 expect(lines).toEqual([])
528 },
529 )
530
531 test(
532 "a prepended organization plugin's allow over a deny rule stands",
533 { plugins: [Fixtures.allowing('guard', 'prepend')] },
534 async ($, on) => {
535 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
536
537 const lines = Fixtures.logged(on)
538
539 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
540
541 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.ALLOWED)
542 expect(lines).toEqual([])
543 },
544 )
545
546 test(
547 "a built-in's allow over a deny rule stands",
548 { plugins: [Fixtures.allowing('bundled', 'builtin')] },
549 async ($, on) => {
550 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
551
552 const lines = Fixtures.logged(on)
553
554 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
555
556 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.ALLOWED)
557 expect(lines).toEqual([])
558 },
559 )
560
561 test(
562 'an ask a plugin of the person allows, no deny rule behind it, stands',
563 { plugins: [Fixtures.allowing('easy')] },
564 async ($, on) => {
565 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
566
567 const lines = Fixtures.logged(on)
568
569 Fixtures.checksAnswered(on, Fixtures.ASKED)
570
571 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.ALLOWED)
572 expect(lines).toEqual([])
573 },
574 )
575
576 test(
577 'a deny no rule decided is still theirs to answer over',
578 { plugins: [Fixtures.allowing('easy')] },
579 async ($, on) => {
580 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
581
582 const lines = Fixtures.logged(on)
583
584 Fixtures.checksAnswered(on, Fixtures.PLAIN_DENY)
585
586 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.ALLOWED)
587 expect(lines).toEqual([])
588 },
589 )
590
591 test(
592 'a plugin of the person that tightens is heard, with one evaluation',
593 { plugins: [Fixtures.tightening] },
594 async ($, on) => {
595 const reads = Fixtures.policyReads(on, Fixtures.MANAGED_POLICY)
596 const evaluations = Fixtures.checksAnswered(on, Fixtures.ASKED)
597
598 await $.tool.check(Fixtures.CHECKED)
599
600 const loaded = { reads: reads(), evaluations: evaluations() }
601
602 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.PLAIN_DENY)
603
604 expect(
605 {
606 reads: reads() - loaded.reads,
607 evaluations: evaluations() - loaded.evaluations,
608 },
609 'once its plugins have loaded, a check reads no policy',
610 ).toEqual({ reads: 0, evaluations: 1 })
611 },
612 )
613
614 test(
615 "a deny rule holds when an organization's plugin listens above theirs",
616 {
617 plugins: [
618 Fixtures.listening('audit', 'prepend'),
619 Fixtures.allowing('easy'),
620 ],
621 },
622 async ($, on) => {
623 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
624
625 const lines = Fixtures.logged(on)
626
627 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
628
629 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
630
631 expect(
632 lines.map(line => line.includes('easy')),
633 'one line, naming the plugin of theirs, alone or in its batch',
634 ).toEqual([true])
635 },
636 )
637
638 test(
639 'a plugin of the person that only listens costs no second evaluation',
640 { plugins: [Fixtures.listening('listening')] },
641 async ($, on) => {
642 const reads = Fixtures.policyReads(on, Fixtures.MANAGED_POLICY)
643 const evaluations = Fixtures.checksAnswered(on, Fixtures.ASKED)
644
645 await $.tool.check(Fixtures.CHECKED)
646
647 const loaded = { reads: reads(), evaluations: evaluations() }
648
649 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.ASKED)
650
651 expect(
652 {
653 reads: reads() - loaded.reads,
654 evaluations: evaluations() - loaded.evaluations,
655 },
656 'once its plugins have loaded, a check reads no policy',
657 ).toEqual({ reads: 0, evaluations: 1 })
658 },
659 )
660
661 test('with none of their plugins the verdict passes once', async ($, on) => {
662 const reads = Fixtures.policyReads(on, Fixtures.MANAGED_POLICY)
663 const evaluations = Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
664
665 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
666
667 expect({ reads: reads(), evaluations: evaluations() }).toEqual({
668 reads: 0,
669 evaluations: 1,
670 })
671 })
672
673 test(
674 'an allow that never called next meets the deny rule all the same',
675 { plugins: [Fixtures.blindAllowing] },
676 async ($, on) => {
677 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
678
679 const lines = Fixtures.logged(on)
680 const evaluations = Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
681
682 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
683
684 expect({ lines, evaluations: evaluations() }).toEqual({
685 lines: [
686 `transcript: ${Hooks.heldNotice('blind', 'Bash', 'Bash(echo *)')}`,
687 ],
688 evaluations: 1,
689 })
690 },
691 )
692
693 test(
694 'a rule a plugin of the person writes into its answer is never read',
695 { plugins: [Fixtures.forging] },
696 async ($, on) => {
697 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
698
699 const lines = Fixtures.logged(on)
700
701 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
702
703 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
704
705 expect(lines).toEqual([
706 `transcript: ${Hooks.heldNotice('forging', 'Bash', 'Bash(echo *)')}`,
707 ])
708 },
709 )
710
711 test(
712 'a plugin of the person asking about another command is left out',
713 { plugins: [Fixtures.rewriting] },
714 async ($, on) => {
715 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
716 Fixtures.logged(on)
717
718 const asked: unknown[] = []
719
720 on('tool.check', ($, e) => {
721 asked.push(e.input)
722
723 return Fixtures.RULE_DENY
724 })
725
726 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
727
728 expect(
729 asked,
730 'the rules were asked about the command that would run, only',
731 ).toEqual([Fixtures.CHECKED.input])
732 },
733 )
734
735 test(
736 'managed settings may let the plugins a person installs override',
737 { plugins: [Fixtures.allowing('easy')] },
738 async ($, on) => {
739 on('settings.read', () => ({ value: Fixtures.overridePolicyOf(true) }))
740
741 const lines = Fixtures.logged(on)
742 const evaluations = Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
743
744 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.ALLOWED)
745
746 expect({ lines, evaluations: evaluations() }).toEqual({
747 lines: [],
748 evaluations: 1,
749 })
750 },
751 )
752
753 test(
754 "only managed settings are asked: a person's own cannot lift a deny rule",
755 { plugins: [Fixtures.allowing('easy')] },
756 async ($, on) => {
757 Fixtures.policyBySource(
758 on,
759 Fixtures.MANAGED_POLICY,
760 Fixtures.overridePolicyOf(true),
761 )
762
763 Fixtures.logged(on)
764 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
765
766 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
767 },
768 )
769
770 test(
771 'the option mistyped lifts nothing: only the literal true does',
772 { plugins: [Fixtures.allowing('easy')] },
773 async ($, on) => {
774 on('settings.read', () => ({ value: Fixtures.overridePolicyOf('true') }))
775 Fixtures.logged(on)
776 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
777
778 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Fixtures.RULE_DENY)
779 },
780 )
781
782 test(
783 'with a policy that cannot be read the deny rule holds: fails closed',
784 { plugins: [Fixtures.allowing('easy')] },
785 async ($, on) => {
786 const stopPolicy = Fixtures.policyUntilStopped(
787 on,
788 Fixtures.overridePolicyOf(true),
789 'managed settings unreadable',
790 )
791
792 Fixtures.logged(on)
793 Fixtures.checksAnswered(on, Fixtures.RULE_DENY)
794 on('prompt.section', ($, e) => ({ text: e.text }))
795
796 await $.prompt.section(Fixtures.MEMORY)
797 stopPolicy()
798
799 expect(
800 await $.tool.check(Fixtures.CHECKED),
801 'the policy that read let plugins override; unread, the rule holds',
802 ).toEqual(Fixtures.RULE_DENY)
803 },
804 )
805
806 test(
807 "when the rules cannot be evaluated the call is refused: the hook's catch",
808 { plugins: [Fixtures.blindAllowing] },
809 async ($, on) => {
810 on('settings.read', () => ({ value: Fixtures.MANAGED_POLICY }))
811 Fixtures.logged(on)
812
813 on('tool.check', () => {
814 throw new Error('the evaluation failed')
815 })
816
817 expect(await $.tool.check(Fixtures.CHECKED)).toEqual(Hooks.UNCHECKED_DENY)
818 },
819 )
820})