๐Ÿ’ป Exercise: Exercise: A tool-access guardrail

๐Ÿ“ Instructions

Write guardrail_check(tool_name, allow=None, block=None) returning (allowed, reason). Precedence: if block is given and tool_name is in it, deny (reason mentions 'denylist'). Else if allow is given and tool_name is NOT in it, deny (reason mentions 'allowlist'). Otherwise allow with reason 'allowed'. Standard library only.

๐Ÿงช Initial Code / Tests

๐Ÿ“„ evaluate.py
from unittest import TestCase
from exercise import guardrail_check


class Evaluate(TestCase):
    def test_denylist_blocks(self):
        ok, reason = guardrail_check('rm', block=['rm'])
        self.assertFalse(ok)

    def test_denylist_wins_over_allowlist(self):
        ok, reason = guardrail_check('rm', allow=['rm'], block=['rm'])
        self.assertIn('denylist', reason)

    def test_allowlist_permits_listed(self):
        self.assertTrue(guardrail_check('search', allow=['search'])[0])

    def test_allowlist_blocks_unlisted(self):
        self.assertFalse(guardrail_check('delete', allow=['search'])[0])

โœ… Solutions

๐Ÿ“„ exercise.py
def guardrail_check(tool_name, allow=None, block=None):
    if block and tool_name in block:
        return False, "'" + tool_name + "' is on the denylist"
    if allow is not None and tool_name not in allow:
        return False, "'" + tool_name + "' is not on the allowlist"
    return True, 'allowed'