1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package bidder
import (
"cmp"
"context"
"fmt"
"strings"
"github.com/johnandersen777/socialweb-computer-kcp/api/v1alpha1"
"github.com/johnandersen777/socialweb-computer-kcp/internal/atproto/market"
"github.com/johnandersen777/socialweb-computer-kcp/internal/market/participant"
"github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/runs"
)
const (
PerspectiveBidder = "bidder"
PolicyRecordType = participant.PolicyRecordType
)
type policyEvaluator struct {
runs *runs.Client
scope string
records *market.RepoStore
}
func (e *policyEvaluator) workflow() string {
if e == nil {
return v1alpha1.BidderDefaultPolicy
}
return cmp.Or(strings.TrimSpace(e.scope), v1alpha1.BidderDefaultPolicy)
}
func (e *policyEvaluator) Scope(ctx context.Context, input participant.PolicyInput) participant.PolicyDecision {
input.Perspective = PerspectiveBidder
input.Mode = participant.PolicyModeScope
input.RFP = nil
return e.run(ctx, runs.Request{WorkflowRef: e.workflow()}, input)
}
func (e *policyEvaluator) EvaluatePolicies(ctx context.Context, refs []market.StrongRef, input participant.PolicyInput) participant.PolicyDecision {
if input.Perspective == "" {
input.Perspective = PerspectiveBidder
}
if input.Mode == "" {
input.Mode = participant.PolicyModeFull
}
if own := e.run(ctx, runs.Request{WorkflowRef: e.workflow()}, input); !own.Allow {
return own
}
if len(refs) == 0 {
return participant.PolicyDecision{Allow: true}
}
if e == nil || e.records == nil {
return participant.PolicyDecision{Reason: "the policy record store is not configured"}
}
for _, entry := range refs {
if _, err := market.ParseRecordRef(entry.URI, entry.CID); err != nil {
return participant.PolicyDecision{Reason: fmt.Sprintf("failed to resolve policy ref %s: %v", entry.URI, err)}
}
record, err := e.records.Resolve(ctx, market.RecordRef{URI: entry.URI, CID: entry.CID})
if err != nil {
return participant.PolicyDecision{Reason: fmt.Sprintf("failed to resolve policy ref %s: %v", entry.URI, err)}
}
workflow, err := participant.PolicyRecordWorkflow(record.Value)
if err != nil {
return participant.PolicyDecision{Reason: fmt.Sprintf("policy ref %s: %v", entry.URI, err)}
}
if decision := e.run(ctx, runs.Request{Workflow: workflow, Source: entry.URI}, input); !decision.Allow {
return decision
}
}
return participant.PolicyDecision{Allow: true}
}
func (e *policyEvaluator) run(ctx context.Context, req runs.Request, input participant.PolicyInput) participant.PolicyDecision {
if e == nil || e.runs == nil {
return participant.PolicyDecision{Reason: "the policy run client is not configured"}
}
req.Input = input.Runs()
return e.runs.Run(ctx, req)
}