~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
96 lines · 3.5 KB Raw History
package policy

import (
	"context"
	"log/slog"
	"net/http"
	"strings"
	"time"

	commonv1 "github.com/johnandersen777/socialweb-computer-kcp/api/common/v1alpha1"
	policyv1alpha1 "github.com/johnandersen777/socialweb-computer-kcp/api/policy/v1alpha1"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/bus"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/contract/sandbox"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/controllers/policyengine"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/controllers/policytrigger"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/controllers/policyworkflow"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/controllers/policyworkflowrun"
	ctlruntime "github.com/johnandersen777/socialweb-computer-kcp/internal/controllers/runtime"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/atproto"
	pecontroller "github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/controller"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/executor"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/registry"
	"github.com/johnandersen777/socialweb-computer-kcp/internal/policyengine/trust"
)

type Options struct {
	Bus *bus.Bus

	Actions policytrigger.ActionsFunc

	PLCURL string

	HTTP *http.Client

	DefaultRunTTL time.Duration

	Sandbox sandbox.Runner

	OpenSandbox func(ctx context.Context, spec *policyv1alpha1.PolicySandboxConfig) (sandbox.Runner, error)

	Disabled bool

	Log *slog.Logger
}

func Register(m *ctlruntime.Manager, opts Options) error {
	if opts.Disabled {
		return nil
	}
	log := opts.Log
	if log == nil {
		log = slog.New(slog.DiscardHandler)
	}
	logf := func(level, message string, meta map[string]any) {
		attributes := make([]any, 0, len(meta)*2)
		for key, value := range meta {
			attributes = append(attributes, key, value)
		}
		switch level {
		case "error":
			log.Error(message, attributes...)
		case "warn":
			log.Warn(message, attributes...)
		case "debug":
			log.Debug(message, attributes...)
		default:
			log.Info(message, attributes...)
		}
	}
	client := atproto.NewClient()
	if opts.HTTP != nil {
		client.HTTP = opts.HTTP
	}
	if plcURL := strings.TrimSpace(opts.PLCURL); plcURL != "" {
		client.PLCURL = plcURL
	}
	host := trust.NewResolver(trust.ResolverOptions{Client: client, Log: logf})
	policies := registry.GhaLiteOnly(executor.NewGhaLite(executor.GhaLiteOptions{Sandbox: opts.Sandbox}))
	records := pecontroller.NewRecordResolver(func(ctx context.Context, ref commonv1.StrongRef) (map[string]any, error) {
		return host.Resolve(ctx, atproto.StrongRef{URI: ref.URI, CID: ref.CID})
	}, policies)
	engines := pecontroller.NewEngineManager(pecontroller.NewDefaultEngineFactory(pecontroller.Config{Sandbox: opts.Sandbox, OpenSandbox: opts.OpenSandbox, Host: host, Log: logf}))
	if _, err := policyengine.Register(m, policyengine.Options{Bus: opts.Bus, Engines: engines, Log: log}); err != nil {
		return err
	}
	if _, err := policyworkflow.Register(m, policyworkflow.Options{Workflows: &pecontroller.WorkflowReconciler{
		Actions: executor.DefaultActionResolver(), Records: records}}); err != nil {
		return err
	}
	if _, err := policyworkflowrun.Register(m, policyworkflowrun.Options{Engines: engines, DefaultRunTTL: opts.DefaultRunTTL, Log: log,
		Runs: &pecontroller.RunReconciler{Records: records, Host: host}}); err != nil {
		return err
	}
	_, err := policytrigger.Register(m, policytrigger.Options{Actions: opts.Actions, Log: log})
	return err
}