@signatu/policyengine
v0.213.0
Published
signatu policy engine
Downloads
24
Readme
Policy Engine
The goal of the new engine is to build a robust, safe, extensible and maintainable Policy engine that can support multiple languages and output formats.
The new engine will be built using TypeScript to leverage compile-time type safety. The engine will be built to be run either on the server under node.js, or in the browser.
Design
A diagram is maintained at Draw.io
Concepts
A Policy
is a representation of the Privacy Policy the
user has created by answering Question
s. The answers will result in one or more PolicyClause
, of the following type:
- Pre-defined static clauses
- Pre-defined clauses from a mutually exclusive list, including possible "specify..." input.
- Pre-defined clauses from multiple selections from a list, including possible "specify..." input.
- Free-text input
A PolicySection
represents a section that considers a certain topic, e.g., "Transfer of Data". Both PolicySection
and PolicyClause
implements the PolicyElement interface. A Policy
is hence an ordered list of objects that implement PolicyElement
.
A PolicyGenerator
will generate a PolicyDocument
from a given Policy
. Typically there will be different PolicyGenerator
implementations for the different output formats, and possibly languages.
Multiple languages and outputs
All the predefined clauses has a text in controlled English language that serves as the "master" text. All other representations (e.g., plain language German, legal language French) are considered derivatives of this controlled text, and should mirror its meaning as closely as possible.
The user-specified input will as a rule not be provided in a controlled English, hence it may require translation to allow for output in other formats.
Design
Here we'll write up the general flow of alternative options. There are three complicating factors:
- Each question can result in different clauses depending on the option the user chooses
- Clauses can be output in different languages and formats (e.g., pictures)
- Clauses can include user-specified input texts, written in a non-controlled, natural language (e.g., German).
Basics
The PolicyElement
corresponds to a specific option for a Question
, referencing user-specified input through a UserInput
object. A PolicyElement
will have a set of PolicyContent
objects associated with each option, one for each language and potentially other types as well (e.g., pictures).
Scenarios
Create the questionnaire
The Questionnaire
is structured as an ordered list of Sections
, who all have an ordered list of Questions
. Each Question
option has a single PolicyElement
associated with it, specifically a PolicyClause
. The masterText
is the controlled English for the clause.
To add actual content to the PolicyElement
, one or more PolicyContent
is added to the PolicyElement
. For example, a TextContent
object having language: en
can be added to make an English plaintext version of the clause.
Answer a questionnaire”
Each Question
is presented to the user. When a particular option is chosen, it is connected to a particular PolicyElement
, and the PolicyElement
is added to the Policy
. If the PolicyElement requiresInput
, then collect input from the user, and add that to the Policy
as well. The UserInput
will reference the PolicyElement
it contains input for. This will be used by the PolicyGenerator
.
Generate a policy
A PolicyGenerator
will create output based on a Policy
and some parameters, such as the language
, type of output (text, pictures, etc) and so on.
The generation is pretty straightforward:
- For each
PolicyElement
:
- Get the correct associated
PolicyContent
object. When generating a text-based policy in English, for example, the right object would be aTextContent
havinglanguage: en
. - If the
PolicyContent
requires/has input, get the associatedUserInput
object and provide thegenerate()
method.
- Combine the output of each
PolicyElement
in sequence into the finalPolicyDocument
. - Repeat for different parameters (e.g., language).
User input
Some questions require the user to "specify" further - e.g., the type of processing, the retainment time for data, and so on. This input is merged into the PolicyContent
from PolicyElement
. Note that a PolicyElement
can have multiple PolicyContent
- different languages, different formats (icon, speech, video), so we need to be able to track multiple UserInput
for each PolicyElement
.
We want the PolicyElement
and PolicyContent
objects to be the same across different Policies, so the current thinking is to provide UserInput[]
to a PolicyContent.generate()
function.
We'll use Mustache
to render user input. All UserInput
objects have a given name
, and that name is substituted for {{name}}
in the PolicyContent
text.
Metadata
Some of the PolicyContent
are template strings - e.g., "{{controller.name}} processes data in the US". The meta data may be in different languages and formats, too. Meta-data is also handled with Mustache, where the Policy
metaData is passed. If the text contains e.g., {{controller.name}}
, then we expect meta data to have an object controller
with a property name
.
Generate a clause for an external service
E.g., Google Analytics. This is equivalent to the others - an ExternalService
object (which implements PolicyElement
) is added to the Policy
. The appropriate PolicyContent
objects are added to the ExternalService
- e.g., IconContent
.
Discussion
It would be beneficial of two PolicyDocuments
containing the same PolicyElement
can be said to be legally equivalent for that particular area, and that the legal consequences are similar. This may be difficult in practice, but if possible, it would ease reasoning over policies, finding similar policies and so on.
Open Questions
- Should
UserInput
just be a class implementingPolicyContent
? - Should the
generate()
method be moved out of thePolicyContent
interface? How do we control generation to different formats - e.g., plain text, HTML, JSON, XML, PNG, etc? - Do we need to separate
PolicySection
andPolicyClause
? Can't both of them just be aPolicyElement
?
Answered Questions
- How to associate the
UserInput
without creating a newPolicyElement
for eachPolicy
? => associate it with both thePolicy
and thePolicyElement
(one way only). Hence when generating a policy, we keep track of the input for all thePolicyElements
.