never executed always true always false
    1 module PureClaw.Security.Policy
    2   ( -- * Policy type
    3     SecurityPolicy (..)
    4     -- * Constructors and combinators
    5   , defaultPolicy
    6   , allowCommand
    7   , denyCommand
    8   , withAutonomy
    9     -- * Pure evaluation
   10   , isCommandAllowed
   11   ) where
   12 
   13 import Data.Set qualified as Set
   14 
   15 import PureClaw.Core.Types
   16 
   17 -- | Security policy governing what an agent can do.
   18 -- Policy evaluation is pure — no IO, fully testable with QuickCheck.
   19 data SecurityPolicy = SecurityPolicy
   20   { _sp_allowedCommands :: AllowList CommandName
   21   , _sp_autonomy        :: AutonomyLevel
   22   }
   23   deriving stock (Show, Eq)
   24 
   25 -- | Default policy: deny everything. Start here and open up explicitly.
   26 defaultPolicy :: SecurityPolicy
   27 defaultPolicy = SecurityPolicy
   28   { _sp_allowedCommands = AllowList Set.empty
   29   , _sp_autonomy        = Deny
   30   }
   31 
   32 -- | Add a command to the allowed set.
   33 -- If the policy already uses 'AllowAll', this is a no-op.
   34 allowCommand :: CommandName -> SecurityPolicy -> SecurityPolicy
   35 allowCommand cmd policy =
   36   case _sp_allowedCommands policy of
   37     AllowAll    -> policy
   38     AllowList s -> policy { _sp_allowedCommands = AllowList (Set.insert cmd s) }
   39 
   40 -- | Remove a command from the allowed set.
   41 -- If the policy uses 'AllowAll', this has no effect (you cannot deny
   42 -- individual commands from an AllowAll policy — switch to explicit list first).
   43 denyCommand :: CommandName -> SecurityPolicy -> SecurityPolicy
   44 denyCommand cmd policy =
   45   case _sp_allowedCommands policy of
   46     AllowAll    -> policy
   47     AllowList s -> policy { _sp_allowedCommands = AllowList (Set.delete cmd s) }
   48 
   49 -- | Set the autonomy level on a policy.
   50 withAutonomy :: AutonomyLevel -> SecurityPolicy -> SecurityPolicy
   51 withAutonomy level policy = policy { _sp_autonomy = level }
   52 
   53 -- | Check whether a command is allowed by this policy. Pure.
   54 isCommandAllowed :: SecurityPolicy -> CommandName -> Bool
   55 isCommandAllowed policy = isAllowed (_sp_allowedCommands policy)