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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package participant
import (
"encoding/json"
"errors"
"fmt"
"strings"
"time"
commonv1 "github.com/johnandersen777/socialweb-computer-kcp/api/common/v1alpha1"
"github.com/johnandersen777/socialweb-computer-kcp/internal/atproto/market"
"github.com/johnandersen777/socialweb-computer-kcp/internal/contract/policy"
"github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/runs"
)
const (
PolicyModeScope = runs.ModeScope
PolicyModeFull = runs.ModeFull
)
type PolicyDecision = runs.Decision
type PolicyRef struct {
URI string
CID string
}
func (r *PolicyRef) StrongRef() *commonv1.StrongRef {
if r == nil || r.URI == "" {
return nil
}
return &commonv1.StrongRef{URI: r.URI, CID: r.CID}
}
func (r PolicyRef) Record() market.RecordRef {
return market.RecordRef{URI: r.URI, CID: r.CID}
}
type PolicyInput struct {
Perspective string
Workflow string
WorkflowBody json.RawMessage
WorkflowSource string
SelfDid string
SubjectDid string
CounterpartyDid string
RootRequesterDid string
RFP *PolicyRef
Bid *PolicyRef
Accept *PolicyRef
Mode string
}
func (in PolicyInput) Runs() runs.Input {
return runs.Input{Perspective: in.Perspective, Mode: in.Mode, SelfDid: in.SelfDid, SubjectDid: in.SubjectDid,
CounterpartyDid: in.CounterpartyDid, RootRequesterDid: in.RootRequesterDid,
RFP: in.RFP.StrongRef(), Bid: in.Bid.StrongRef(), Accept: in.Accept.StrongRef()}
}
type PolicyConfig struct {
Resolve runs.ResolveFunc
Owner policy.Owner
Engine commonv1.ObjectRef
Role string
Prefix string
Args map[string]string
Timeout time.Duration
Parser runs.Parser
Association *commonv1.AssociationPolicy
}
func NewPolicyRuns(cfg PolicyConfig) *runs.Client {
if cfg.Resolve == nil {
return nil
}
return &runs.Client{Resolve: cfg.Resolve, Owner: cfg.Owner, Engine: cfg.Engine, Role: cfg.Role, Prefix: cfg.Prefix,
Args: cfg.Args, Timeout: cfg.Timeout, Parser: cfg.Parser, Association: cfg.Association.DeepCopy(), Now: time.Now}
}
func ParsePolicyArgs(raw string) (map[string]string, error) {
if strings.TrimSpace(raw) == "" {
return map[string]string{}, nil
}
var value any
if err := json.Unmarshal([]byte(raw), &value); err != nil {
return nil, fmt.Errorf("participant: policyArgs is not JSON: %w", err)
}
if value == nil {
return map[string]string{}, nil
}
obj, ok := value.(map[string]any)
if !ok {
return nil, errors.New("participant: policyArgs must be a JSON object")
}
out := make(map[string]string, len(obj))
for key, item := range obj {
switch typed := item.(type) {
case string:
out[key] = typed
case bool:
out[key] = fmt.Sprintf("%t", typed)
case float64:
out[key] = fmt.Sprintf("%v", typed)
default:
data, err := json.Marshal(typed)
if err != nil {
return nil, err
}
out[key] = string(data)
}
}
return out, nil
}