Policies
Policies is a concept that drives the application. It is a new paradigm focussed on achieving truly dynamic applications. It is different from usual concepts for applications. Although the reference architecture is one that is widely known and is worked on by each and every organization. The basis for the policy system can be found in the security realm.
Consider 2 types of applications:
- Data driven: Data is highest good, we have input and need to convert it to output
- Process driven: A process defines how an object moves through its different states, the data in that object becomes secondary
Here we define a new way to approach a dynamic system. Policies are the highest goods and they influence the data/fields shown in the UI. They define the process to follow, security to be applied, where data can be resolved, and much more.
How can we use all fields across our application and have them influence all other aspects of the system? The answer is policies.
Reference architecture can be found in any/all security systems. We will use firewall rules
and policies
as
an example to model this system.
Policy Definition Language (PDL)
Following the example within security, policies are defined in a single file. They have a specific syntax that is flexible and extensible. The base of the system is this ruleset of policies. It will drive the application.
General structure could be:
FOR [TARGET] WHEN [SELECTOR]
RESULT [TARGET SPECIFIC KEYS]
ON [DATETIME] TO [DATETIME]
ROLE [ROLE NAMES] ;
Our system is mostly Json based, so json would be a better fit. It would be easier to integrate with the existing software and methodologies. The downside is that it is not really readable for non-technical people. The idea is that knowledgeable people can quickly perform changes to this file. Therefor Yaml would be a better fit. It allows for easy conversion to and from Json and has the added benefit that it is more readable for non-technical people. So our implementation will be Yaml based.
The policies will have a json structure trough the entire system, except for the policy file editor. There a conversion will be made to Yaml.
The structure from above in Yaml would have this structure:
|
|
Parts explained:
- TARGET: Denotes the effect of a policy (e.g: filtering lists, defining parameters, security constraints, …)
- TARGET SPECIFIC KEYS: Each target has its own specific keys/implementation. This is where they are defined.
- ON and TO (optional): Allows for versioning policies by date and time
- ROLE NAMES (optional): Specifies specific roles for whom the rule applies
Comments
You can add comments to the file with the #
character.
|
|
Targets
Parameter
Parameters are used inside (payroll) components. Components denote different aspects that make up the compensation and benefits an employee
receives in exchange for their labour/services. Business requirement states that these parameters can come from anywhere. PDL is dynamic and allows
for resolving these parameters from different sources. The job of the PARAMETER
query is to describe how to resolve these parameters.
For resolving paranmeters, we need a way to define a value for all components. Therefor the parameter selector
will support wildcards. E.g.: when: *.companyVat
. This specifies that all parameters named companyVat
will
have the same value. Notice that we can still overwrite the value if the need should arise.
Static resolver
The static resolver is perhaps the simplest. It defines the value as part of the policy.
e.g.:
|
|
The above policies define a fixed value. This value will be applicable to all employees since the WHEN
specification was omitted. The effect
is that in every calculation of the components mobilePhone
and mobileSubscription
will have a benefitInKind
with the value of 3
.
Considder the following adaptations:
|
|
To note here is that both rules affect the same parameter. Rules are processed in order as found in the ruleset. The effect off the above configuration is:
- if the function of the employee is of type
management
then the result of thebenefitInKind
for a mobile phone will be4
- for all other employees the result would be
3
Rules need to be ordered correctly, from most relevent to least relevant.
Considder the following adaptation:
|
|
To note here is the addition of the on
and to
parameters that limit the policy in time. The effect of these rules are:
- Before januari 1st 2020 all employees in management would have a benefit in kind for a mobile phone equal to
4
. The first rule does not evaluate to true because of the date specification. - For the entire year 2020 all employees in management would have a benefit in kind for a mobile phone equal to
2
. The rule applies since the date falls betwween the dates specified in theON
and theTO
date constraints. - All other employees, at any given time will have a benefit in kind of
3
To help with the dates, the dates should be handled as:
on
date is inclusiveto
date is exclusive
This allows for easy definition of start dates, and eliminates the need to do arithmatic on the end date to subtract one tick
.
Entity resolver
The entity resolver will implement a method that allows values to be obtained from other parts of the system. It effectively allows linking a parameter to a field anywhere in the application.
|
|
This policy has the effect of resolving the benefitInKind
parameter for the mobilePhone
component from the entity
com.platfohrm.employer.BikMobilePhone
. To achieve this the service responsible for the employer
data needs information to retrieve the
correct record. Here we specified that the records Id
should equal the EmployerId
of the environment where this ruleset is active.
The environment variables are specified on the top of the file. You can define variables and use them throughout the ruleset. This allows for copying over rules between environments. You would only need to override the variables for each environment. You can use the following format:
|
|
Hierarchy
An important reason for this implementation is the concept of hierarchies. To explain hierarchies we first need to look to the structure of clients of the application.
The structure is as follows:
--- title: Hierarchy --- graph TD; A[Platfohrm] -->|has| B(Expert A) A -->|has| C(Expert B) B -->|supports| E[Employer 1] B -->|supports| G[Empoloyer 2] C -->|supports| H[Employer 4] C -->|supports| I[Employer 5] G -->|devided in| J(Establishment A) G -->|devided in| K(Establishment B) K -->|structures| L(Department 1) K -->|structures| M(Department 2) L -->|employs| O(Employee A) L -->|employs| P(Employee B) P -->|contract| Q[Contract 1] P -->|contract| R[Contract 2]
Requirement: Policies from the top level are applied, unless they are overwritten on a lower level.
To achieve hierarchy we need a file that structures the policies in sequence. This ties together with rules that are structured from most relevant to least relevant.
Now lets structure the policies as they are defined following this hierarchy.
Remember: The first rule to match will be applied.
We will start to build this hierarchical structure from the ground up. We will start with an example to determine the cost for mealVouchers
. In our example this would represent a
component that is part of the compensation for an employee.
Level 0: Platfohrm
So lets start from the top down. At the top level we define that the value of one meal voucher is 5.00
. The business reason for specifying this can be all sorts. In this case we would
assume its the legal minimum. So the policy for Platfohrm
would become:
|
|
Let’s say law changes starting the 1st of 2025. The value would become 6.00
due to regulatory changes. To achieve this, we would change the policy to:
|
|
Note the TO
and ON
parts of the policies above. When TO
is specified without a corresponding ON
. It means that all dates before the TO
date will evaluate this condition as true.
In contrast to this, a ON
without a TO
denotes that there is no end date specified for the given policy. All dates starting from the given date would evaluate to true.
The effect of this policy is that prior to 20250101 the value would always be 5.00
. Starting from 20250101 the value would always be 6.00
.
If you want to specify more constraints like the function classification of an employee, you can look at the previous sections of this documentation.
To keep this example simple we will continue to the next level.
Level 1: Expert
The next level in the hierarchy is that of the expert. This organisation can again specify their own policies. For example: the expert wants to create a more attractive payroll packet for staff in an accounting function. One of the measures they take, is to change the value of the meal vouchers. This would result in this policy:
FOR PARAMETER "mealVoucher.value" WHEN "employee.function.type" = "accounting" RESULT STATIC 10.00
|
|
This policy states that when employees occupy a function of type accounting
then meal vouchers would get a value of 10.00
.
Level 2: Employer
The next level in the hierarchy is that of the employer/client. He is of the opinion that 10.00
is to high. His organization is an accountancy firm and that would cost to much. Therefor
the employer wants to change this value to 8.00
. To achieve this he creates a policy:
|
|
Note: The policy created here is the exact same as the Expert, but with a different value.
Level 3: Establishment
The organization has many establishments, but one of their establishment has an in house kitchen. They serve hot meals every day at discounted prices. Management feels that this is already a big plus for the employee at this location and wants to change the value of the meal vouchers accordingly. The employer would add a new policy to achieve this:
|
|
Note that the new policy was added above the previous policy. It is more specific and therefor must be above the other statements. This because the first to match will be applied.
Level 4: Department
The organization has sales representatives on the road and would like to support the expensive food prices by increasing the value of the meal vouchers. The organization would update the policy:
|
|
Level 5: Individual employee
The employer got the chance to attract a senior sales representative. This person has a proven track record and getting him to join the company had proven tough. Negotiations were tough.
One of the extra benefits this person asked was for a higher value of meal vouchers. He/she negotiated a value of 10
. The company updated their policy to reflect this:
|
|
The individual rule was placed on top to make sure it was applied before other rules were processed.
Level 6: Individual contract
Since the acquisition of the new sales representative sales were going great. So great the company could hardly keep up. This meant some of the sales representatives have been asked to work part-time.
Their contract was amended to a part-time function. One of these employees had experience in ICT and agreed to take on additional work as a support agent within the ICT department. HR drew up an additional
contract for the employee, again for a part-time, but this time in the ICT department as a support agent. An agreement was made that this person would get a value 7.50
for his meal vouchers while
working the function of support agent. The company added a policy to the new contract:
|
|
This completes the example of hierarchies. All that is left is putting it all together.
Putting it all together
Policy file structure
For our example of meal vouchers. All levels have created their policies. All that is left is combining these policies so that the correct policy would apply for each level of the hierarchy. The answer is simple, we load all policy files in reverse order, from the bottom of the hierarchy to the top. This would result in the following policy:
|
|
This structure will ensure that the policies are applied for the correct conditions.
The top level platfohrm
can define default values for almost any parameter in the system. As long as there is no policy that overrides this, the top level would always be applied.
Adapting over time
One last part of the system has to do with changes in policy on any of the levels. To achieve this we can use a similar approach as we did for the environment variables. We would start the policy file by specifying the variables on top and add a similar structure for the hierarchy:
|
|
The above file specifies that additional policy sets are loaded from other levels. This employer works with the base as defined by Platfohrm
. And they have chosen for ExpertA
.
The implementation will process this HIERARCHY
block and add the files as specified above.
Note the :latest
addition. This specifies that the latest version of these files will be included. If needed, an organization can choose to pin it to a previous version.
The entry can then be changed to BASE "platfohrm:3.0.2
and that ruleset will always be applied. Updates would not be automatic until the client updates the version, or specifies latest
again.
The entire file would look like this:
|
|
Notice that the policies that are included in via the hierarchy
are not present in this file. They will be added automatically. Here we focus on 1 file for a particular client.
User Interface
Dynamic UI
|
|
Our example above defines that the entity com.platfohrm.employer
should have a field BikMobilePhone
. The type of the field can be deduced from the parameter mobilePhone.benefitInKind
.
This definition allows the system to dynamically add this field to the UI responsible for the employer
data. All that was needed is this one line policy definition.
Working with policies
In a first stage we will start from the file itself. Although in a later phase we will be able to define a UI interface to work with the policies. The input of a policy UI is always this file. It can be filtered to show the relevant policies in accordance with the subject on the screen. Let’s consider a UI for definition of policies related to components.
Given this ruleset:
|
|
When the user has the component mobilePhone
open, then the filter for the policies is:
- All policies of type
PARAMETER
where name starts withmobilePhone
. - (optional) filter by date range:
- Active today: all that have no
ON
section or today’s date is betweenON
andTO
of the date section
- Active today: all that have no
Versioning
Minimal policy
For a client to start using the system, the minimum requirement is that a base is defined. The example bellow denotes the absolute minimum for the system to operate.
In this example the client follows the latest
version of the platfohrm
base.
|
|
Splitting policy sets
Policy sets can become large, additionally we might want to define different defaults
depending on a clients sector or wishes. We can achieve this by creating multiple files
and combining them. Let’s apply the same principles for the most important levels and set this up.
Defining a base
Let’s say we want to provide a different base for construction oriented organizations. We will first create our base, one that we will use for all non-construction oriented organizations.
|
|
Now let’s define an entirely different base for construction oriented organizations.
|
|
Here we changed the entire ruleset to tailor for construction oriented organizations. We had to define unchanged policies as well. The problem with this is manageability. If we have to create a base for all sectors, we would have
a lot of maintenance propagating our changes through all these different bases
.
A better way to achieve the same result but in a more manageable manner would be to extend our own default base. Doing so we would only need to define the changes for the construction instead of duplicating all policies. The result would be:
|
|
Using this approach we would get all changes from the base. We just needed to define the changes.
Note that we chose to follow the latest
version of our platfohrm-base
. The effect is that new versions would automatically impact our version for the construction sector.
If we want to avoid that, all we need to do is change platfohrm-base:latest
to platfohrm-base:1.0
. That would give us even more control.
A client can now choose what base to follow. The organization can define their base in their own policy definition:
|
|
In this example, the organization decided to follow the platfohrm-base-construction
and follow all changes automatically when new versions of the base are released.
Cherry-picking
Cherry-picking is the process where we can really fine-tune the needs of the policies. As an example, a car policy might be a difficult one. We as an organization want to offer more choices to the organizations using our software. Let’s say we want to define 2 car policies.
Generous car policy:
|
|
Here we defined the generous car policy
, we have set the maximum catalog price for a car to be 36 000
.
Budget car policy:
|
|
Here we have defined the budget car policy
. We lowered the maximum catalog price to 28 000
.
We can now define our base in similar fashion. Since this base will be widely used, we will add the budget car policy
to the base.
|
|
Here we used our previous example of our base. We have now added the budget car policy
to it. With cherry-picking we can go even further. Let’s create 2 more policies. One for
meal vouchers
and one for mobile phone
.
Meal vouchers:
|
|
We have set constraints on the meal vouchers. The policy above states that the value of meal vouchers needs to be between a min
and a max
: 4.50
and 10.00
respectively.
Mobile phone:
|
|
Here we specify that the benefit in kind
for a mobile phone
always equals 3.00
, and that the benefit in kind for a
mobile subscriptionalso always equals
3.00```.
Combining all of the above, we can now specify our base policy in a very clean and maintainable way:
|
|
Here we have defined a base for organizations and experts to build upon. We cherry-picked policies and combined them to an all-inclusive policy base. An organization or an expert can
now build upon this policy freely and add value to the policy as is needed. As a final example let’s say an expert might want to change the base policy and upgrade the car policy to the
generous car policy
. All he would have to do is define this in a policy file. The expert can define their own policies easily. AS an example let’s say the expert defines a policy
for accounting
oriented organizations.
|
|
Here the expert created his own base. He started from the platfohrm-base
but changed the car policy to the generous car policy
. He also fixed the version of the car policy to
1.0
because he wanted more control over potential changes to provide even better support towards his clients. When he creates new clients in the system. The expert can now set this
policy as a base for the client:
|
|
The client will now follow the policy of expert A
. Additional policies can be defined if needed, the client can start to tailor the policies to his needs. This completes the circle.
Here the expert policy is set up as a base
meaning that it inherits all defaults of the platfohrm-base
. If this was not the case, the system would not work. But the expert is
in control when creating the new client. He could have simple added the platfohrm-base
to the policy definition of his client and achieve the same result.
|
|
An expert is in control of his clients. And he can set up clients by defining policies. These policies can be tailored to the clients needs. With this approach we can allow experts to set up clients through a wizard, or allow experts to change configuration for clients. All fine-tuning is done through policies.