From f7e28673f910850ce1bdffea8395f0ce416c4eab Mon Sep 17 00:00:00 2001
From: Lyuben Penkovski <lyuben.penkovski@vereign.com>
Date: Mon, 28 Mar 2022 08:20:23 +0300
Subject: [PATCH] Goa DSL for policy evaluation and 'main' wiring

---
 cmd/policy/main.go                      |  10 ++
 design/design.go                        |  13 +++
 design/types.go                         |  17 +++
 gen/http/cli/policy/cli.go              |  61 +++++++++++
 gen/http/openapi.json                   |   2 +-
 gen/http/openapi.yaml                   |  65 ++++++++++++
 gen/http/openapi3.json                  |   2 +-
 gen/http/openapi3.yaml                  |  81 ++++++++++++++-
 gen/http/policy/client/cli.go           |  55 ++++++++++
 gen/http/policy/client/client.go        |  75 ++++++++++++++
 gen/http/policy/client/encode_decode.go | 104 +++++++++++++++++++
 gen/http/policy/client/paths.go         |  17 +++
 gen/http/policy/client/types.go         |  55 ++++++++++
 gen/http/policy/server/encode_decode.go |  66 ++++++++++++
 gen/http/policy/server/paths.go         |  17 +++
 gen/http/policy/server/server.go        | 131 ++++++++++++++++++++++++
 gen/http/policy/server/types.go         |  57 +++++++++++
 gen/policy/client.go                    |  36 +++++++
 gen/policy/endpoints.go                 |  40 ++++++++
 gen/policy/service.go                   |  46 +++++++++
 internal/service/policy/service.go      |  18 ++++
 21 files changed, 965 insertions(+), 3 deletions(-)
 create mode 100644 design/types.go
 create mode 100644 gen/http/policy/client/cli.go
 create mode 100644 gen/http/policy/client/client.go
 create mode 100644 gen/http/policy/client/encode_decode.go
 create mode 100644 gen/http/policy/client/paths.go
 create mode 100644 gen/http/policy/client/types.go
 create mode 100644 gen/http/policy/server/encode_decode.go
 create mode 100644 gen/http/policy/server/paths.go
 create mode 100644 gen/http/policy/server/server.go
 create mode 100644 gen/http/policy/server/types.go
 create mode 100644 gen/policy/client.go
 create mode 100644 gen/policy/endpoints.go
 create mode 100644 gen/policy/service.go
 create mode 100644 internal/service/policy/service.go

diff --git a/cmd/policy/main.go b/cmd/policy/main.go
index 5a648869..05675f99 100644
--- a/cmd/policy/main.go
+++ b/cmd/policy/main.go
@@ -18,10 +18,13 @@ import (
 	goahealth "code.vereign.com/gaiax/tsa/policy/gen/health"
 	goahealthsrv "code.vereign.com/gaiax/tsa/policy/gen/http/health/server"
 	goaopenapisrv "code.vereign.com/gaiax/tsa/policy/gen/http/openapi/server"
+	goapolicysrv "code.vereign.com/gaiax/tsa/policy/gen/http/policy/server"
 	"code.vereign.com/gaiax/tsa/policy/gen/openapi"
+	goapolicy "code.vereign.com/gaiax/tsa/policy/gen/policy"
 	"code.vereign.com/gaiax/tsa/policy/internal/config"
 	"code.vereign.com/gaiax/tsa/policy/internal/service"
 	"code.vereign.com/gaiax/tsa/policy/internal/service/health"
+	"code.vereign.com/gaiax/tsa/policy/internal/service/policy"
 )
 
 var Version = "0.0.0+development"
@@ -42,18 +45,22 @@ func main() {
 
 	// create services
 	var (
+		policySvc goapolicy.Service
 		healthSvc goahealth.Service
 	)
 	{
+		policySvc = policy.New()
 		healthSvc = health.New()
 	}
 
 	// create endpoints
 	var (
+		policyEndpoints  *goapolicy.Endpoints
 		healthEndpoints  *goahealth.Endpoints
 		openapiEndpoints *openapi.Endpoints
 	)
 	{
+		policyEndpoints = goapolicy.NewEndpoints(policySvc)
 		healthEndpoints = goahealth.NewEndpoints(healthSvc)
 		openapiEndpoints = openapi.NewEndpoints(nil)
 	}
@@ -76,15 +83,18 @@ func main() {
 	// the service input and output data structures to HTTP requests and
 	// responses.
 	var (
+		policyServer  *goapolicysrv.Server
 		healthServer  *goahealthsrv.Server
 		openapiServer *goaopenapisrv.Server
 	)
 	{
+		policyServer = goapolicysrv.New(policyEndpoints, mux, dec, enc, nil, errFormatter)
 		healthServer = goahealthsrv.New(healthEndpoints, mux, dec, enc, nil, errFormatter)
 		openapiServer = goaopenapisrv.New(openapiEndpoints, mux, dec, enc, nil, errFormatter, nil, nil)
 	}
 
 	// Configure the mux.
+	goapolicysrv.Mount(mux, policyServer)
 	goahealthsrv.Mount(mux, healthServer)
 	goaopenapisrv.Mount(mux, openapiServer)
 
diff --git a/design/design.go b/design/design.go
index f73c6373..2dae4129 100644
--- a/design/design.go
+++ b/design/design.go
@@ -15,6 +15,19 @@ var _ = API("policy", func() {
 	})
 })
 
+var _ = Service("policy", func() {
+	Description("Policy Service provides evaluation of policies through Open Policy Agent.")
+
+	Method("Evaluate", func() {
+		Payload(EvaluateRequest)
+		Result(EvaluateResult)
+		HTTP(func() {
+			POST("/policy/{group}/{policyName}/{version}/evaluation")
+			Response(StatusOK)
+		})
+	})
+})
+
 var _ = Service("health", func() {
 	Description("Health service provides health check endpoints.")
 
diff --git a/design/types.go b/design/types.go
new file mode 100644
index 00000000..c72cf1a0
--- /dev/null
+++ b/design/types.go
@@ -0,0 +1,17 @@
+// nolint:revive
+package design
+
+import . "goa.design/goa/v3/dsl"
+
+var EvaluateRequest = Type("EvaluateRequest", func() {
+	Field(1, "group", String, "Policy group")
+	Field(2, "policyName", String, "Policy name")
+	Field(3, "version", String, "Policy version")
+	Field(4, "data", Any, "Data passed as input to the policy execution runtime")
+	Required("group", "policyName", "version", "data")
+})
+
+var EvaluateResult = Type("EvaluateResult", func() {
+	Field(1, "result", Any, "Arbitrary JSON response.")
+	Required("result")
+})
diff --git a/gen/http/cli/policy/cli.go b/gen/http/cli/policy/cli.go
index b27030d7..f7610a85 100644
--- a/gen/http/cli/policy/cli.go
+++ b/gen/http/cli/policy/cli.go
@@ -14,6 +14,7 @@ import (
 	"os"
 
 	healthc "code.vereign.com/gaiax/tsa/policy/gen/http/health/client"
+	policyc "code.vereign.com/gaiax/tsa/policy/gen/http/policy/client"
 	goahttp "goa.design/goa/v3/http"
 	goa "goa.design/goa/v3/pkg"
 )
@@ -24,12 +25,16 @@ import (
 //
 func UsageCommands() string {
 	return `health (liveness|readiness)
+policy evaluate
 `
 }
 
 // UsageExamples produces an example of a valid invocation of the CLI tool.
 func UsageExamples() string {
 	return os.Args[0] + ` health liveness` + "\n" +
+		os.Args[0] + ` policy evaluate --body '{
+      "data": "Quasi et et laudantium non."
+   }' --group "Et facilis sit corporis enim." --policy-name "Saepe aut cumque." --version "Ab accusamus voluptatem et est."` + "\n" +
 		""
 }
 
@@ -48,11 +53,22 @@ func ParseEndpoint(
 		healthLivenessFlags = flag.NewFlagSet("liveness", flag.ExitOnError)
 
 		healthReadinessFlags = flag.NewFlagSet("readiness", flag.ExitOnError)
+
+		policyFlags = flag.NewFlagSet("policy", flag.ContinueOnError)
+
+		policyEvaluateFlags          = flag.NewFlagSet("evaluate", flag.ExitOnError)
+		policyEvaluateBodyFlag       = policyEvaluateFlags.String("body", "REQUIRED", "")
+		policyEvaluateGroupFlag      = policyEvaluateFlags.String("group", "REQUIRED", "Policy group")
+		policyEvaluatePolicyNameFlag = policyEvaluateFlags.String("policy-name", "REQUIRED", "Policy name")
+		policyEvaluateVersionFlag    = policyEvaluateFlags.String("version", "REQUIRED", "Policy version")
 	)
 	healthFlags.Usage = healthUsage
 	healthLivenessFlags.Usage = healthLivenessUsage
 	healthReadinessFlags.Usage = healthReadinessUsage
 
+	policyFlags.Usage = policyUsage
+	policyEvaluateFlags.Usage = policyEvaluateUsage
+
 	if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
 		return nil, nil, err
 	}
@@ -70,6 +86,8 @@ func ParseEndpoint(
 		switch svcn {
 		case "health":
 			svcf = healthFlags
+		case "policy":
+			svcf = policyFlags
 		default:
 			return nil, nil, fmt.Errorf("unknown service %q", svcn)
 		}
@@ -95,6 +113,13 @@ func ParseEndpoint(
 
 			}
 
+		case "policy":
+			switch epn {
+			case "evaluate":
+				epf = policyEvaluateFlags
+
+			}
+
 		}
 	}
 	if epf == nil {
@@ -125,6 +150,13 @@ func ParseEndpoint(
 				endpoint = c.Readiness()
 				data = nil
 			}
+		case "policy":
+			c := policyc.NewClient(scheme, host, doer, enc, dec, restore)
+			switch epn {
+			case "evaluate":
+				endpoint = c.Evaluate()
+				data, err = policyc.BuildEvaluatePayload(*policyEvaluateBodyFlag, *policyEvaluateGroupFlag, *policyEvaluatePolicyNameFlag, *policyEvaluateVersionFlag)
+			}
 		}
 	}
 	if err != nil {
@@ -167,3 +199,32 @@ Example:
     %[1]s health readiness
 `, os.Args[0])
 }
+
+// policyUsage displays the usage of the policy command and its subcommands.
+func policyUsage() {
+	fmt.Fprintf(os.Stderr, `Policy Service provides evaluation of policies through Open Policy Agent.
+Usage:
+    %[1]s [globalflags] policy COMMAND [flags]
+
+COMMAND:
+    evaluate: Evaluate implements Evaluate.
+
+Additional help:
+    %[1]s policy COMMAND --help
+`, os.Args[0])
+}
+func policyEvaluateUsage() {
+	fmt.Fprintf(os.Stderr, `%[1]s [flags] policy evaluate -body JSON -group STRING -policy-name STRING -version STRING
+
+Evaluate implements Evaluate.
+    -body JSON: 
+    -group STRING: Policy group
+    -policy-name STRING: Policy name
+    -version STRING: Policy version
+
+Example:
+    %[1]s policy evaluate --body '{
+      "data": "Quasi et et laudantium non."
+   }' --group "Et facilis sit corporis enim." --policy-name "Saepe aut cumque." --version "Ab accusamus voluptatem et est."
+`, os.Args[0])
+}
diff --git a/gen/http/openapi.json b/gen/http/openapi.json
index f3017019..b7773f1f 100644
--- a/gen/http/openapi.json
+++ b/gen/http/openapi.json
@@ -1 +1 @@
-{"swagger":"2.0","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":""},"host":"localhost:8080","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}}}}
\ No newline at end of file
+{"swagger":"2.0","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":""},"host":"localhost:8080","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/policy/{group}/{policyName}/{version}/evaluation":{"post":{"tags":["policy"],"summary":"Evaluate policy","operationId":"policy#Evaluate","parameters":[{"name":"group","in":"path","description":"Policy group","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version","required":true,"type":"string"},{"name":"EvaluateRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/PolicyEvaluateRequestBody","required":["data"]}}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/PolicyEvaluateResponseBody","required":["result"]}}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}}},"definitions":{"PolicyEvaluateRequestBody":{"title":"PolicyEvaluateRequestBody","type":"object","properties":{"data":{"type":"string","description":"Data passed as input to the policy execution runtime","example":"Ipsum nihil quo.","format":"binary"}},"example":{"data":"Repellat velit omnis."},"required":["data"]},"PolicyEvaluateResponseBody":{"title":"PolicyEvaluateResponseBody","type":"object","properties":{"result":{"type":"string","description":"Arbitrary JSON response.","example":"Illum ad assumenda consectetur minima voluptatibus.","format":"binary"}},"example":{"result":"Id odio aperiam voluptatem molestias corrupti sunt."},"required":["result"]}}}
\ No newline at end of file
diff --git a/gen/http/openapi.yaml b/gen/http/openapi.yaml
index d78c3dfa..214812d2 100644
--- a/gen/http/openapi.yaml
+++ b/gen/http/openapi.yaml
@@ -24,6 +24,44 @@ paths:
           description: OK response.
       schemes:
       - http
+  /policy/{group}/{policyName}/{version}/evaluation:
+    post:
+      tags:
+      - policy
+      summary: Evaluate policy
+      operationId: policy#Evaluate
+      parameters:
+      - name: group
+        in: path
+        description: Policy group
+        required: true
+        type: string
+      - name: policyName
+        in: path
+        description: Policy name
+        required: true
+        type: string
+      - name: version
+        in: path
+        description: Policy version
+        required: true
+        type: string
+      - name: EvaluateRequestBody
+        in: body
+        required: true
+        schema:
+          $ref: '#/definitions/PolicyEvaluateRequestBody'
+          required:
+          - data
+      responses:
+        "200":
+          description: OK response.
+          schema:
+            $ref: '#/definitions/PolicyEvaluateResponseBody'
+            required:
+            - result
+      schemes:
+      - http
   /readiness:
     get:
       tags:
@@ -35,3 +73,30 @@ paths:
           description: OK response.
       schemes:
       - http
+definitions:
+  PolicyEvaluateRequestBody:
+    title: PolicyEvaluateRequestBody
+    type: object
+    properties:
+      data:
+        type: string
+        description: Data passed as input to the policy execution runtime
+        example: Ipsum nihil quo.
+        format: binary
+    example:
+      data: Repellat velit omnis.
+    required:
+    - data
+  PolicyEvaluateResponseBody:
+    title: PolicyEvaluateResponseBody
+    type: object
+    properties:
+      result:
+        type: string
+        description: Arbitrary JSON response.
+        example: Illum ad assumenda consectetur minima voluptatibus.
+        format: binary
+    example:
+      result: Id odio aperiam voluptatem molestias corrupti sunt.
+    required:
+    - result
diff --git a/gen/http/openapi3.json b/gen/http/openapi3.json
index 22d61abd..705e2078 100644
--- a/gen/http/openapi3.json
+++ b/gen/http/openapi3.json
@@ -1 +1 @@
-{"openapi":"3.0.3","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":"1.0"},"servers":[{"url":"http://localhost:8080","description":"Policy Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}}},"components":{},"tags":[{"name":"health","description":"Health service provides health check endpoints."}]}
\ No newline at end of file
+{"openapi":"3.0.3","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":"1.0"},"servers":[{"url":"http://localhost:8080","description":"Policy Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/policy/{group}/{policyName}/{version}/evaluation":{"post":{"tags":["policy"],"summary":"Evaluate policy","operationId":"policy#Evaluate","parameters":[{"name":"group","in":"path","description":"Policy group","required":true,"schema":{"type":"string","description":"Policy group","example":"Explicabo beatae quisquam officiis libero voluptatibus."},"example":"Repudiandae dolore quod."},{"name":"policyName","in":"path","description":"Policy name","required":true,"schema":{"type":"string","description":"Policy name","example":"Aut ut fuga quae eius minus."},"example":"Architecto quibusdam ab."},{"name":"version","in":"path","description":"Policy version","required":true,"schema":{"type":"string","description":"Policy version","example":"In illum est et hic."},"example":"Deleniti non nihil dolor aut sed."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluateRequestBody"},"example":{"data":"Quasi et et laudantium non."}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluateResult"},"example":{"result":"Et voluptates."}}}}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}}},"components":{"schemas":{"EvaluateRequestBody":{"type":"object","properties":{"data":{"type":"string","description":"Data passed as input to the policy execution runtime","example":"Vitae qui.","format":"binary"}},"example":{"data":"Provident fugiat at cupiditate."},"required":["data"]},"EvaluateResult":{"type":"object","properties":{"result":{"type":"string","description":"Arbitrary JSON response.","example":"Commodi vitae voluptatem.","format":"binary"}},"example":{"result":"Similique quisquam optio."},"required":["result"]}}},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"policy","description":"Policy Service provides evaluation of policies through Open Policy Agent."}]}
\ No newline at end of file
diff --git a/gen/http/openapi3.yaml b/gen/http/openapi3.yaml
index b2d64e2a..aa3e8dd7 100644
--- a/gen/http/openapi3.yaml
+++ b/gen/http/openapi3.yaml
@@ -16,6 +16,57 @@ paths:
       responses:
         "200":
           description: OK response.
+  /policy/{group}/{policyName}/{version}/evaluation:
+    post:
+      tags:
+      - policy
+      summary: Evaluate policy
+      operationId: policy#Evaluate
+      parameters:
+      - name: group
+        in: path
+        description: Policy group
+        required: true
+        schema:
+          type: string
+          description: Policy group
+          example: Explicabo beatae quisquam officiis libero voluptatibus.
+        example: Repudiandae dolore quod.
+      - name: policyName
+        in: path
+        description: Policy name
+        required: true
+        schema:
+          type: string
+          description: Policy name
+          example: Aut ut fuga quae eius minus.
+        example: Architecto quibusdam ab.
+      - name: version
+        in: path
+        description: Policy version
+        required: true
+        schema:
+          type: string
+          description: Policy version
+          example: In illum est et hic.
+        example: Deleniti non nihil dolor aut sed.
+      requestBody:
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/EvaluateRequestBody'
+            example:
+              data: Quasi et et laudantium non.
+      responses:
+        "200":
+          description: OK response.
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/EvaluateResult'
+              example:
+                result: Et voluptates.
   /readiness:
     get:
       tags:
@@ -25,7 +76,35 @@ paths:
       responses:
         "200":
           description: OK response.
-components: {}
+components:
+  schemas:
+    EvaluateRequestBody:
+      type: object
+      properties:
+        data:
+          type: string
+          description: Data passed as input to the policy execution runtime
+          example: Vitae qui.
+          format: binary
+      example:
+        data: Provident fugiat at cupiditate.
+      required:
+      - data
+    EvaluateResult:
+      type: object
+      properties:
+        result:
+          type: string
+          description: Arbitrary JSON response.
+          example: Commodi vitae voluptatem.
+          format: binary
+      example:
+        result: Similique quisquam optio.
+      required:
+      - result
 tags:
 - name: health
   description: Health service provides health check endpoints.
+- name: policy
+  description: Policy Service provides evaluation of policies through Open Policy
+    Agent.
diff --git a/gen/http/policy/client/cli.go b/gen/http/policy/client/cli.go
new file mode 100644
index 00000000..c483ac70
--- /dev/null
+++ b/gen/http/policy/client/cli.go
@@ -0,0 +1,55 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy HTTP client CLI support package
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package client
+
+import (
+	"encoding/json"
+	"fmt"
+
+	policy "code.vereign.com/gaiax/tsa/policy/gen/policy"
+	goa "goa.design/goa/v3/pkg"
+)
+
+// BuildEvaluatePayload builds the payload for the policy Evaluate endpoint
+// from CLI flags.
+func BuildEvaluatePayload(policyEvaluateBody string, policyEvaluateGroup string, policyEvaluatePolicyName string, policyEvaluateVersion string) (*policy.EvaluateRequest, error) {
+	var err error
+	var body EvaluateRequestBody
+	{
+		err = json.Unmarshal([]byte(policyEvaluateBody), &body)
+		if err != nil {
+			return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n      \"data\": \"Quasi et et laudantium non.\"\n   }'")
+		}
+		if body.Data == nil {
+			err = goa.MergeErrors(err, goa.MissingFieldError("data", "body"))
+		}
+		if err != nil {
+			return nil, err
+		}
+	}
+	var group string
+	{
+		group = policyEvaluateGroup
+	}
+	var policyName string
+	{
+		policyName = policyEvaluatePolicyName
+	}
+	var version string
+	{
+		version = policyEvaluateVersion
+	}
+	v := &policy.EvaluateRequest{
+		Data: body.Data,
+	}
+	v.Group = group
+	v.PolicyName = policyName
+	v.Version = version
+
+	return v, nil
+}
diff --git a/gen/http/policy/client/client.go b/gen/http/policy/client/client.go
new file mode 100644
index 00000000..837783bd
--- /dev/null
+++ b/gen/http/policy/client/client.go
@@ -0,0 +1,75 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy client HTTP transport
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package client
+
+import (
+	"context"
+	"net/http"
+
+	goahttp "goa.design/goa/v3/http"
+	goa "goa.design/goa/v3/pkg"
+)
+
+// Client lists the policy service endpoint HTTP clients.
+type Client struct {
+	// Evaluate Doer is the HTTP client used to make requests to the Evaluate
+	// endpoint.
+	EvaluateDoer goahttp.Doer
+
+	// RestoreResponseBody controls whether the response bodies are reset after
+	// decoding so they can be read again.
+	RestoreResponseBody bool
+
+	scheme  string
+	host    string
+	encoder func(*http.Request) goahttp.Encoder
+	decoder func(*http.Response) goahttp.Decoder
+}
+
+// NewClient instantiates HTTP clients for all the policy service servers.
+func NewClient(
+	scheme string,
+	host string,
+	doer goahttp.Doer,
+	enc func(*http.Request) goahttp.Encoder,
+	dec func(*http.Response) goahttp.Decoder,
+	restoreBody bool,
+) *Client {
+	return &Client{
+		EvaluateDoer:        doer,
+		RestoreResponseBody: restoreBody,
+		scheme:              scheme,
+		host:                host,
+		decoder:             dec,
+		encoder:             enc,
+	}
+}
+
+// Evaluate returns an endpoint that makes HTTP requests to the policy service
+// Evaluate server.
+func (c *Client) Evaluate() goa.Endpoint {
+	var (
+		encodeRequest  = EncodeEvaluateRequest(c.encoder)
+		decodeResponse = DecodeEvaluateResponse(c.decoder, c.RestoreResponseBody)
+	)
+	return func(ctx context.Context, v interface{}) (interface{}, error) {
+		req, err := c.BuildEvaluateRequest(ctx, v)
+		if err != nil {
+			return nil, err
+		}
+		err = encodeRequest(req, v)
+		if err != nil {
+			return nil, err
+		}
+		resp, err := c.EvaluateDoer.Do(req)
+		if err != nil {
+			return nil, goahttp.ErrRequestError("policy", "Evaluate", err)
+		}
+		return decodeResponse(resp)
+	}
+}
diff --git a/gen/http/policy/client/encode_decode.go b/gen/http/policy/client/encode_decode.go
new file mode 100644
index 00000000..49cdd5fc
--- /dev/null
+++ b/gen/http/policy/client/encode_decode.go
@@ -0,0 +1,104 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy HTTP client encoders and decoders
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package client
+
+import (
+	"bytes"
+	"context"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+
+	policy "code.vereign.com/gaiax/tsa/policy/gen/policy"
+	goahttp "goa.design/goa/v3/http"
+)
+
+// BuildEvaluateRequest instantiates a HTTP request object with method and path
+// set to call the "policy" service "Evaluate" endpoint
+func (c *Client) BuildEvaluateRequest(ctx context.Context, v interface{}) (*http.Request, error) {
+	var (
+		group      string
+		policyName string
+		version    string
+	)
+	{
+		p, ok := v.(*policy.EvaluateRequest)
+		if !ok {
+			return nil, goahttp.ErrInvalidType("policy", "Evaluate", "*policy.EvaluateRequest", v)
+		}
+		group = p.Group
+		policyName = p.PolicyName
+		version = p.Version
+	}
+	u := &url.URL{Scheme: c.scheme, Host: c.host, Path: EvaluatePolicyPath(group, policyName, version)}
+	req, err := http.NewRequest("POST", u.String(), nil)
+	if err != nil {
+		return nil, goahttp.ErrInvalidURL("policy", "Evaluate", u.String(), err)
+	}
+	if ctx != nil {
+		req = req.WithContext(ctx)
+	}
+
+	return req, nil
+}
+
+// EncodeEvaluateRequest returns an encoder for requests sent to the policy
+// Evaluate server.
+func EncodeEvaluateRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, interface{}) error {
+	return func(req *http.Request, v interface{}) error {
+		p, ok := v.(*policy.EvaluateRequest)
+		if !ok {
+			return goahttp.ErrInvalidType("policy", "Evaluate", "*policy.EvaluateRequest", v)
+		}
+		body := NewEvaluateRequestBody(p)
+		if err := encoder(req).Encode(&body); err != nil {
+			return goahttp.ErrEncodingError("policy", "Evaluate", err)
+		}
+		return nil
+	}
+}
+
+// DecodeEvaluateResponse returns a decoder for responses returned by the
+// policy Evaluate endpoint. restoreBody controls whether the response body
+// should be restored after having been read.
+func DecodeEvaluateResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (interface{}, error) {
+	return func(resp *http.Response) (interface{}, error) {
+		if restoreBody {
+			b, err := ioutil.ReadAll(resp.Body)
+			if err != nil {
+				return nil, err
+			}
+			resp.Body = ioutil.NopCloser(bytes.NewBuffer(b))
+			defer func() {
+				resp.Body = ioutil.NopCloser(bytes.NewBuffer(b))
+			}()
+		} else {
+			defer resp.Body.Close()
+		}
+		switch resp.StatusCode {
+		case http.StatusOK:
+			var (
+				body EvaluateResponseBody
+				err  error
+			)
+			err = decoder(resp).Decode(&body)
+			if err != nil {
+				return nil, goahttp.ErrDecodingError("policy", "Evaluate", err)
+			}
+			err = ValidateEvaluateResponseBody(&body)
+			if err != nil {
+				return nil, goahttp.ErrValidationError("policy", "Evaluate", err)
+			}
+			res := NewEvaluateResultOK(&body)
+			return res, nil
+		default:
+			body, _ := ioutil.ReadAll(resp.Body)
+			return nil, goahttp.ErrInvalidResponse("policy", "Evaluate", resp.StatusCode, string(body))
+		}
+	}
+}
diff --git a/gen/http/policy/client/paths.go b/gen/http/policy/client/paths.go
new file mode 100644
index 00000000..62f6160d
--- /dev/null
+++ b/gen/http/policy/client/paths.go
@@ -0,0 +1,17 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// HTTP request path constructors for the policy service.
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package client
+
+import (
+	"fmt"
+)
+
+// EvaluatePolicyPath returns the URL path to the policy service Evaluate HTTP endpoint.
+func EvaluatePolicyPath(group string, policyName string, version string) string {
+	return fmt.Sprintf("/policy/%v/%v/%v/evaluation", group, policyName, version)
+}
diff --git a/gen/http/policy/client/types.go b/gen/http/policy/client/types.go
new file mode 100644
index 00000000..36eb2a2e
--- /dev/null
+++ b/gen/http/policy/client/types.go
@@ -0,0 +1,55 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy HTTP client types
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package client
+
+import (
+	policy "code.vereign.com/gaiax/tsa/policy/gen/policy"
+	goa "goa.design/goa/v3/pkg"
+)
+
+// EvaluateRequestBody is the type of the "policy" service "Evaluate" endpoint
+// HTTP request body.
+type EvaluateRequestBody struct {
+	// Data passed as input to the policy execution runtime
+	Data interface{} `form:"data" json:"data" xml:"data"`
+}
+
+// EvaluateResponseBody is the type of the "policy" service "Evaluate" endpoint
+// HTTP response body.
+type EvaluateResponseBody struct {
+	// Arbitrary JSON response.
+	Result interface{} `form:"result,omitempty" json:"result,omitempty" xml:"result,omitempty"`
+}
+
+// NewEvaluateRequestBody builds the HTTP request body from the payload of the
+// "Evaluate" endpoint of the "policy" service.
+func NewEvaluateRequestBody(p *policy.EvaluateRequest) *EvaluateRequestBody {
+	body := &EvaluateRequestBody{
+		Data: p.Data,
+	}
+	return body
+}
+
+// NewEvaluateResultOK builds a "policy" service "Evaluate" endpoint result
+// from a HTTP "OK" response.
+func NewEvaluateResultOK(body *EvaluateResponseBody) *policy.EvaluateResult {
+	v := &policy.EvaluateResult{
+		Result: body.Result,
+	}
+
+	return v
+}
+
+// ValidateEvaluateResponseBody runs the validations defined on
+// EvaluateResponseBody
+func ValidateEvaluateResponseBody(body *EvaluateResponseBody) (err error) {
+	if body.Result == nil {
+		err = goa.MergeErrors(err, goa.MissingFieldError("result", "body"))
+	}
+	return
+}
diff --git a/gen/http/policy/server/encode_decode.go b/gen/http/policy/server/encode_decode.go
new file mode 100644
index 00000000..cf8a4c3b
--- /dev/null
+++ b/gen/http/policy/server/encode_decode.go
@@ -0,0 +1,66 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy HTTP server encoders and decoders
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package server
+
+import (
+	"context"
+	"io"
+	"net/http"
+
+	policy "code.vereign.com/gaiax/tsa/policy/gen/policy"
+	goahttp "goa.design/goa/v3/http"
+	goa "goa.design/goa/v3/pkg"
+)
+
+// EncodeEvaluateResponse returns an encoder for responses returned by the
+// policy Evaluate endpoint.
+func EncodeEvaluateResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, interface{}) error {
+	return func(ctx context.Context, w http.ResponseWriter, v interface{}) error {
+		res, _ := v.(*policy.EvaluateResult)
+		enc := encoder(ctx, w)
+		body := NewEvaluateResponseBody(res)
+		w.WriteHeader(http.StatusOK)
+		return enc.Encode(body)
+	}
+}
+
+// DecodeEvaluateRequest returns a decoder for requests sent to the policy
+// Evaluate endpoint.
+func DecodeEvaluateRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (interface{}, error) {
+	return func(r *http.Request) (interface{}, error) {
+		var (
+			body EvaluateRequestBody
+			err  error
+		)
+		err = decoder(r).Decode(&body)
+		if err != nil {
+			if err == io.EOF {
+				return nil, goa.MissingPayloadError()
+			}
+			return nil, goa.DecodePayloadError(err.Error())
+		}
+		err = ValidateEvaluateRequestBody(&body)
+		if err != nil {
+			return nil, err
+		}
+
+		var (
+			group      string
+			policyName string
+			version    string
+
+			params = mux.Vars(r)
+		)
+		group = params["group"]
+		policyName = params["policyName"]
+		version = params["version"]
+		payload := NewEvaluateRequest(&body, group, policyName, version)
+
+		return payload, nil
+	}
+}
diff --git a/gen/http/policy/server/paths.go b/gen/http/policy/server/paths.go
new file mode 100644
index 00000000..b5ca7ad8
--- /dev/null
+++ b/gen/http/policy/server/paths.go
@@ -0,0 +1,17 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// HTTP request path constructors for the policy service.
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package server
+
+import (
+	"fmt"
+)
+
+// EvaluatePolicyPath returns the URL path to the policy service Evaluate HTTP endpoint.
+func EvaluatePolicyPath(group string, policyName string, version string) string {
+	return fmt.Sprintf("/policy/%v/%v/%v/evaluation", group, policyName, version)
+}
diff --git a/gen/http/policy/server/server.go b/gen/http/policy/server/server.go
new file mode 100644
index 00000000..e324397d
--- /dev/null
+++ b/gen/http/policy/server/server.go
@@ -0,0 +1,131 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy HTTP server
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package server
+
+import (
+	"context"
+	"net/http"
+
+	policy "code.vereign.com/gaiax/tsa/policy/gen/policy"
+	goahttp "goa.design/goa/v3/http"
+	goa "goa.design/goa/v3/pkg"
+)
+
+// Server lists the policy service endpoint HTTP handlers.
+type Server struct {
+	Mounts   []*MountPoint
+	Evaluate http.Handler
+}
+
+// ErrorNamer is an interface implemented by generated error structs that
+// exposes the name of the error as defined in the design.
+type ErrorNamer interface {
+	ErrorName() string
+}
+
+// MountPoint holds information about the mounted endpoints.
+type MountPoint struct {
+	// Method is the name of the service method served by the mounted HTTP handler.
+	Method string
+	// Verb is the HTTP method used to match requests to the mounted handler.
+	Verb string
+	// Pattern is the HTTP request path pattern used to match requests to the
+	// mounted handler.
+	Pattern string
+}
+
+// New instantiates HTTP handlers for all the policy service endpoints using
+// the provided encoder and decoder. The handlers are mounted on the given mux
+// using the HTTP verb and path defined in the design. errhandler is called
+// whenever a response fails to be encoded. formatter is used to format errors
+// returned by the service methods prior to encoding. Both errhandler and
+// formatter are optional and can be nil.
+func New(
+	e *policy.Endpoints,
+	mux goahttp.Muxer,
+	decoder func(*http.Request) goahttp.Decoder,
+	encoder func(context.Context, http.ResponseWriter) goahttp.Encoder,
+	errhandler func(context.Context, http.ResponseWriter, error),
+	formatter func(err error) goahttp.Statuser,
+) *Server {
+	return &Server{
+		Mounts: []*MountPoint{
+			{"Evaluate", "POST", "/policy/{group}/{policyName}/{version}/evaluation"},
+		},
+		Evaluate: NewEvaluateHandler(e.Evaluate, mux, decoder, encoder, errhandler, formatter),
+	}
+}
+
+// Service returns the name of the service served.
+func (s *Server) Service() string { return "policy" }
+
+// Use wraps the server handlers with the given middleware.
+func (s *Server) Use(m func(http.Handler) http.Handler) {
+	s.Evaluate = m(s.Evaluate)
+}
+
+// Mount configures the mux to serve the policy endpoints.
+func Mount(mux goahttp.Muxer, h *Server) {
+	MountEvaluateHandler(mux, h.Evaluate)
+}
+
+// Mount configures the mux to serve the policy endpoints.
+func (s *Server) Mount(mux goahttp.Muxer) {
+	Mount(mux, s)
+}
+
+// MountEvaluateHandler configures the mux to serve the "policy" service
+// "Evaluate" endpoint.
+func MountEvaluateHandler(mux goahttp.Muxer, h http.Handler) {
+	f, ok := h.(http.HandlerFunc)
+	if !ok {
+		f = func(w http.ResponseWriter, r *http.Request) {
+			h.ServeHTTP(w, r)
+		}
+	}
+	mux.Handle("POST", "/policy/{group}/{policyName}/{version}/evaluation", f)
+}
+
+// NewEvaluateHandler creates a HTTP handler which loads the HTTP request and
+// calls the "policy" service "Evaluate" endpoint.
+func NewEvaluateHandler(
+	endpoint goa.Endpoint,
+	mux goahttp.Muxer,
+	decoder func(*http.Request) goahttp.Decoder,
+	encoder func(context.Context, http.ResponseWriter) goahttp.Encoder,
+	errhandler func(context.Context, http.ResponseWriter, error),
+	formatter func(err error) goahttp.Statuser,
+) http.Handler {
+	var (
+		decodeRequest  = DecodeEvaluateRequest(mux, decoder)
+		encodeResponse = EncodeEvaluateResponse(encoder)
+		encodeError    = goahttp.ErrorEncoder(encoder, formatter)
+	)
+	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept"))
+		ctx = context.WithValue(ctx, goa.MethodKey, "Evaluate")
+		ctx = context.WithValue(ctx, goa.ServiceKey, "policy")
+		payload, err := decodeRequest(r)
+		if err != nil {
+			if err := encodeError(ctx, w, err); err != nil {
+				errhandler(ctx, w, err)
+			}
+			return
+		}
+		res, err := endpoint(ctx, payload)
+		if err != nil {
+			if err := encodeError(ctx, w, err); err != nil {
+				errhandler(ctx, w, err)
+			}
+			return
+		}
+		if err := encodeResponse(ctx, w, res); err != nil {
+			errhandler(ctx, w, err)
+		}
+	})
+}
diff --git a/gen/http/policy/server/types.go b/gen/http/policy/server/types.go
new file mode 100644
index 00000000..be5b1945
--- /dev/null
+++ b/gen/http/policy/server/types.go
@@ -0,0 +1,57 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy HTTP server types
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package server
+
+import (
+	policy "code.vereign.com/gaiax/tsa/policy/gen/policy"
+	goa "goa.design/goa/v3/pkg"
+)
+
+// EvaluateRequestBody is the type of the "policy" service "Evaluate" endpoint
+// HTTP request body.
+type EvaluateRequestBody struct {
+	// Data passed as input to the policy execution runtime
+	Data interface{} `form:"data,omitempty" json:"data,omitempty" xml:"data,omitempty"`
+}
+
+// EvaluateResponseBody is the type of the "policy" service "Evaluate" endpoint
+// HTTP response body.
+type EvaluateResponseBody struct {
+	// Arbitrary JSON response.
+	Result interface{} `form:"result" json:"result" xml:"result"`
+}
+
+// NewEvaluateResponseBody builds the HTTP response body from the result of the
+// "Evaluate" endpoint of the "policy" service.
+func NewEvaluateResponseBody(res *policy.EvaluateResult) *EvaluateResponseBody {
+	body := &EvaluateResponseBody{
+		Result: res.Result,
+	}
+	return body
+}
+
+// NewEvaluateRequest builds a policy service Evaluate endpoint payload.
+func NewEvaluateRequest(body *EvaluateRequestBody, group string, policyName string, version string) *policy.EvaluateRequest {
+	v := &policy.EvaluateRequest{
+		Data: body.Data,
+	}
+	v.Group = group
+	v.PolicyName = policyName
+	v.Version = version
+
+	return v
+}
+
+// ValidateEvaluateRequestBody runs the validations defined on
+// EvaluateRequestBody
+func ValidateEvaluateRequestBody(body *EvaluateRequestBody) (err error) {
+	if body.Data == nil {
+		err = goa.MergeErrors(err, goa.MissingFieldError("data", "body"))
+	}
+	return
+}
diff --git a/gen/policy/client.go b/gen/policy/client.go
new file mode 100644
index 00000000..5fc9b70f
--- /dev/null
+++ b/gen/policy/client.go
@@ -0,0 +1,36 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy client
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package policy
+
+import (
+	"context"
+
+	goa "goa.design/goa/v3/pkg"
+)
+
+// Client is the "policy" service client.
+type Client struct {
+	EvaluateEndpoint goa.Endpoint
+}
+
+// NewClient initializes a "policy" service client given the endpoints.
+func NewClient(evaluate goa.Endpoint) *Client {
+	return &Client{
+		EvaluateEndpoint: evaluate,
+	}
+}
+
+// Evaluate calls the "Evaluate" endpoint of the "policy" service.
+func (c *Client) Evaluate(ctx context.Context, p *EvaluateRequest) (res *EvaluateResult, err error) {
+	var ires interface{}
+	ires, err = c.EvaluateEndpoint(ctx, p)
+	if err != nil {
+		return
+	}
+	return ires.(*EvaluateResult), nil
+}
diff --git a/gen/policy/endpoints.go b/gen/policy/endpoints.go
new file mode 100644
index 00000000..5b8b177f
--- /dev/null
+++ b/gen/policy/endpoints.go
@@ -0,0 +1,40 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy endpoints
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package policy
+
+import (
+	"context"
+
+	goa "goa.design/goa/v3/pkg"
+)
+
+// Endpoints wraps the "policy" service endpoints.
+type Endpoints struct {
+	Evaluate goa.Endpoint
+}
+
+// NewEndpoints wraps the methods of the "policy" service with endpoints.
+func NewEndpoints(s Service) *Endpoints {
+	return &Endpoints{
+		Evaluate: NewEvaluateEndpoint(s),
+	}
+}
+
+// Use applies the given middleware to all the "policy" service endpoints.
+func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) {
+	e.Evaluate = m(e.Evaluate)
+}
+
+// NewEvaluateEndpoint returns an endpoint function that calls the method
+// "Evaluate" of service "policy".
+func NewEvaluateEndpoint(s Service) goa.Endpoint {
+	return func(ctx context.Context, req interface{}) (interface{}, error) {
+		p := req.(*EvaluateRequest)
+		return s.Evaluate(ctx, p)
+	}
+}
diff --git a/gen/policy/service.go b/gen/policy/service.go
new file mode 100644
index 00000000..f2b7f991
--- /dev/null
+++ b/gen/policy/service.go
@@ -0,0 +1,46 @@
+// Code generated by goa v3.7.0, DO NOT EDIT.
+//
+// policy service
+//
+// Command:
+// $ goa gen code.vereign.com/gaiax/tsa/policy/design
+
+package policy
+
+import (
+	"context"
+)
+
+// Policy Service provides evaluation of policies through Open Policy Agent.
+type Service interface {
+	// Evaluate implements Evaluate.
+	Evaluate(context.Context, *EvaluateRequest) (res *EvaluateResult, err error)
+}
+
+// ServiceName is the name of the service as defined in the design. This is the
+// same value that is set in the endpoint request contexts under the ServiceKey
+// key.
+const ServiceName = "policy"
+
+// MethodNames lists the service method names as defined in the design. These
+// are the same values that are set in the endpoint request contexts under the
+// MethodKey key.
+var MethodNames = [1]string{"Evaluate"}
+
+// EvaluateRequest is the payload type of the policy service Evaluate method.
+type EvaluateRequest struct {
+	// Policy group
+	Group string
+	// Policy name
+	PolicyName string
+	// Policy version
+	Version string
+	// Data passed as input to the policy execution runtime
+	Data interface{}
+}
+
+// EvaluateResult is the result type of the policy service Evaluate method.
+type EvaluateResult struct {
+	// Arbitrary JSON response.
+	Result interface{}
+}
diff --git a/internal/service/policy/service.go b/internal/service/policy/service.go
new file mode 100644
index 00000000..ed8edcb5
--- /dev/null
+++ b/internal/service/policy/service.go
@@ -0,0 +1,18 @@
+package policy
+
+import (
+	"context"
+
+	"code.vereign.com/gaiax/tsa/golib/errors"
+	"code.vereign.com/gaiax/tsa/policy/gen/policy"
+)
+
+type Service struct{}
+
+func New() *Service {
+	return &Service{}
+}
+
+func (s *Service) Evaluate(context.Context, *policy.EvaluateRequest) (*policy.EvaluateResult, error) {
+	return nil, errors.New("not implemented")
+}
-- 
GitLab