Skip to content

Commit

Permalink
docs: typed policy engine DR
Browse files Browse the repository at this point in the history
  • Loading branch information
ndr-brt committed Oct 4, 2024
1 parent b46a4c1 commit 434c392
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Typed Policy Engine

## Decision

We will implement a new implementation of the Policy Engine, with strongly typed scopes and contexts.

## Rationale

At the moment implementing a new policy function for an adopter requires a "blind guess" about the content of the `PolicyContext`
object, because it's designed as an unstructured map.
Bounding the context structure to the scope will help documentation and usability of the Policy Engine.

## Approach

First we need to make two assumptions:
- it won't be possible to register a policy function or a policy validator under `ALL_SCOPES` (`*`):
- it makes no sense to have a function/validator bound to all the scopes, scopes have well defined bound, they could
share context content (e.g. `Instant now` field could be one of them), but this should happen at the `PolicyContext`
hierarchy level.
- scope hierarchy won't be a thing anymore (e.g. `scope` and `scope.child`)
- for the same reason as before, plus, it is a feature never really used, because an actual scope hierarchy was never
defined.

We will define a `record` that will represent the scope:
```java
public record PolicyScope<C extends PolicyContext>(String name) { }
```
The record is bound to a `PolicyContext` context implementation, and it has a `name` property.

The biggest part of refactor evolves around extracting a `ScopedPolicyEngine` from `PolicyEngine`, that will work only on a specific
scope, the interface will be pretty similar to the `PolicyEngine` one, but it won't need to have the `scope` passed, because
that will be an internal attribute.

e.g.
```java
public interface ScopedPolicyEngine<C extends PolicyContext> {

Result<Void> evaluate(Policy policy, C context);

Policy filter(Policy policy);

<R extends Rule> void registerFunction(Class<R> type, String key, AtomicConstraintRuleFunction<R, C> function);

<R extends Rule> void registerFunction(Class<R> type, DynamicAtomicConstraintRuleFunction<R, C> function);

<R extends Rule> void registerFunction(Class<R> type, RulePolicyFunction<R, C> function);

void registerPreValidator(PolicyValidatorFunction validator);

void registerPostValidator(PolicyValidatorFunction validator);

PolicyEvaluationPlan createEvaluationPlan(Policy policy);

}
```

this `ScopedPolicyEngine` can then be obtained from the `PolicyEngine`:
```java
public interface PolicyEngine {
...

<C extends PolicyContext, S extends PolicyScope<C>> ScopedPolicyEngine<C> forScope(S scope);

...
```

All the `PolicyEngine` methods with `String scope` will be deprecated, and the implementation will call `forScope` internally
to avoid breaking changes.

Other interfaces/classes will need to be duplicated with a "scoped" version of them, like:
- `AtomicConstraintFunction`
- `DynamicAtomicConstraintFunction`
- `RuleFunction`
- ... (potential others, to be discovered during the refactor)

The `PolicyEvaluationPlanner` and the related "steps" will need to be adapted to the new interfaces, no need to do with
the "duplicate/deprecate" pattern because it is an internal component.
1 change: 1 addition & 0 deletions docs/developer/decision-records/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@
- [2024-09-24 STS Accounts API](./2024-09-24-sts-accounts-api)
- [2024-09-25 Multiple Protocol Versions](./2024-09-25-multiple-protocol-versions)
- [2024-10-02 Clustered data-plane](./2024-10-02-clustered-data-plane/)
- [2024-10-06 Typed Policy Engine](./2024-10-05-typed-policy-engine)

0 comments on commit 434c392

Please sign in to comment.