// Package component implements the Dever external Worker process protocol. // The compiler owns schema and typed Port codecs; callers bind its identity here. package component import ( "bytes" "context" "encoding/binary" "encoding/json" "errors" "io" "math" "regexp" "sort" "strconv" "strings" "time" "unicode/utf8" ) const ( Version = "dever-component-1" maxBytes = 16 * 1024 * 1024 maxDepth = 64 maxElements = 65536 cancelGrace = time.Second ) var ( decimalPattern = regexp.MustCompile(`^[+-]?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[eE][+-]?[0-9]+)?$`) uuidPattern = regexp.MustCompile(`(?i)^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$`) timePattern = regexp.MustCompile(`^[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]{3})?$`) datetimePattern = regexp.MustCompile(`^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]{1,3})?(?:Z|[+-][0-9]{2}:[0-9]{2})$`) ) type Contract struct { Port, Schema, Adapter string Operations, Capabilities, Errors []string } type TypeSchema struct { Type string `json:"type"` Name string `json:"name,omitempty"` Value *TypeSchema `json:"value,omitempty"` Fields map[string]TypeSchema `json:"fields,omitempty"` } type Manifest struct { Port string `json:"port"` Schema string `json:"schema"` Adapter string `json:"adapter"` Operations []string `json:"operations"` Capabilities []string `json:"capabilities"` Setting *TypeSchema `json:"setting"` Inputs map[string]TypeSchema `json:"inputs"` Outputs map[string]TypeSchema `json:"outputs"` Errors map[string]TypeSchema `json:"errors"` } type BusinessError struct { Identity string Payload any } func (e BusinessError) Error() string { return e.Identity } type handler[S any] func(context.Context, any, S) (any, error) type Worker[S any] struct { contract Contract decodeSetting func(any) (S, error) handlers map[string]handler[S] inputTypes map[string]TypeSchema outputTypes map[string]TypeSchema errorTypes map[string]TypeSchema } func NewFromManifest(manifest Manifest) (*Worker[any], error) { if len(manifest.Inputs) != len(manifest.Operations) || len(manifest.Outputs) != len(manifest.Operations) { return nil, errors.New("incomplete typed Worker contract") } for _, operation := range manifest.Operations { if _, ok := manifest.Inputs[operation]; !ok { return nil, errors.New("missing operation input contract") } if _, ok := manifest.Outputs[operation]; !ok { return nil, errors.New("missing operation output contract") } } identities := make([]string, 0, len(manifest.Errors)) for identity := range manifest.Errors { identities = append(identities, identity) } sort.Strings(identities) worker, err := New(Contract{ Port: manifest.Port, Schema: manifest.Schema, Adapter: manifest.Adapter, Operations: manifest.Operations, Capabilities: manifest.Capabilities, Errors: identities, }, func(value any) (any, error) { if manifest.Setting == nil { if value != nil { return nil, errors.New("unexpected setting") } return nil, nil } return decodeTyped(value, *manifest.Setting) }) if err != nil { return nil, err } worker.inputTypes, worker.outputTypes, worker.errorTypes = manifest.Inputs, manifest.Outputs, manifest.Errors return worker, nil } // ServeManifest binds the checked contract to compile-time selected handlers. func ServeManifest(manifestBytes []byte, handlers map[string]func(context.Context, any, any) (any, error), input io.Reader, output io.Writer) error { var manifest Manifest if err := json.Unmarshal(manifestBytes, &manifest); err != nil { return err } worker, err := NewFromManifest(manifest) if err != nil { return err } if err := worker.RegisterHandlers(handlers); err != nil { return err } return worker.Serve(input, output) } func (w *Worker[S]) RegisterHandler(operation string, run func(context.Context, any, S) (any, error)) error { schema, ok := w.inputTypes[operation] if !ok || run == nil { return errors.New("operation is not in a typed Worker contract") } if w.handlers[operation] != nil { return errors.New("duplicate component operation") } w.handlers[operation] = func(ctx context.Context, raw any, setting S) (any, error) { payload, err := decodeTyped(raw, schema) if err != nil { return nil, errors.New("invalid component payload") } result, err := run(ctx, payload, setting) if err != nil { var business BusinessError if errors.As(err, &business) { typeSchema, declared := w.errorTypes[business.Identity] if !declared { return nil, errors.New("undeclared business error identity") } business.Payload, err = decodeTyped(business.Payload, typeSchema) if err != nil { return nil, errors.New("invalid business error payload") } return nil, business } return nil, err } return decodeTyped(result, w.outputTypes[operation]) } return nil } func (w *Worker[S]) RegisterHandlers(handlers map[string]func(context.Context, any, S) (any, error)) error { if len(handlers) != len(w.contract.Operations) { return errors.New("component operations are not fully registered") } for _, operation := range w.contract.Operations { if err := w.RegisterHandler(operation, handlers[operation]); err != nil { return err } } return nil } func decodeTyped(value any, schema TypeSchema) (any, error) { switch schema.Type { case "nullable": if value == nil { return nil, nil } if schema.Value == nil { return nil, errors.New("invalid nullable contract") } return decodeTyped(value, *schema.Value) case "list": values, ok := value.([]any) if !ok || schema.Value == nil { return nil, errors.New("expected list") } result := make([]any, len(values)) for index, item := range values { decoded, err := decodeTyped(item, *schema.Value) if err != nil { return nil, err } result[index] = decoded } return result, nil case "record": object, ok := value.(map[string]any) if !ok { return nil, errors.New("expected record") } for name := range object { if _, ok := schema.Fields[name]; !ok { return nil, errors.New("unknown record field") } } result := make(map[string]any, len(schema.Fields)) for name, field := range schema.Fields { entry, exists := object[name] if !exists && field.Type != "nullable" { return nil, errors.New("missing record field") } decoded, err := decodeTyped(entry, field) if err != nil { return nil, err } result[name] = decoded } return result, nil case "int64", "duration", "model_id": switch number := value.(type) { case json.Number: if _, err := number.Int64(); err == nil { return number, nil } case int64: return number, nil case int: return int64(number), nil } case "float64": switch number := value.(type) { case json.Number: parsed, err := number.Float64() if err == nil && !math.IsInf(parsed, 0) && !math.IsNaN(parsed) { return number, nil } case float64: if !math.IsInf(number, 0) && !math.IsNaN(number) { return number, nil } } case "bool": if boolean, ok := value.(bool); ok { return boolean, nil } case "json": return value, nil case "text", "id", "secret", "decimal", "uuid", "datetime", "date", "time": if text, ok := value.(string); ok { switch schema.Type { case "decimal": if !decimalPattern.MatchString(text) { return nil, errors.New("invalid decimal") } case "uuid": if !uuidPattern.MatchString(text) { return nil, errors.New("invalid UUID") } case "date": if _, err := time.Parse("2006-01-02", text); err != nil { return nil, err } case "time": if !timePattern.MatchString(text) { return nil, errors.New("invalid Time") } layout := "15:04:05" if len(text) == 12 { layout = "15:04:05.000" } if _, err := time.Parse(layout, text); err != nil { return nil, err } case "datetime": if !datetimePattern.MatchString(text) { return nil, errors.New("invalid DateTime") } parsed, err := time.Parse(time.RFC3339Nano, text) if err != nil || parsed.Nanosecond()%1_000_000 != 0 { return nil, errors.New("invalid DateTime") } } return text, nil } } return nil, errors.New("invalid typed Worker value") } func New[S any](contract Contract, decodeSetting func(any) (S, error)) (*Worker[S], error) { if contract.Port == "" || contract.Schema == "" || contract.Adapter == "" || len(contract.Operations) == 0 || decodeSetting == nil || !unique(contract.Operations) || !unique(contract.Capabilities) || !unique(contract.Errors) { return nil, errors.New("incomplete component contract") } if contract.Capabilities == nil { contract.Capabilities = []string{} } if contract.Errors == nil { contract.Errors = []string{} } contract.Operations = append([]string(nil), contract.Operations...) contract.Capabilities = append([]string{}, contract.Capabilities...) contract.Errors = append([]string{}, contract.Errors...) return &Worker[S]{contract: contract, decodeSetting: decodeSetting, handlers: make(map[string]handler[S])}, nil } func unique(values []string) bool { seen := make(map[string]bool, len(values)) for _, value := range values { if value == "" || seen[value] { return false } seen[value] = true } return true } // RegisterTyped binds a compiler-declared operation to its application codec. func RegisterTyped[S, P any](worker *Worker[S], operation string, decode func(any) (P, error), run func(context.Context, P, S) (any, error)) error { if !contains(worker.contract.Operations, operation) || worker.handlers[operation] != nil || decode == nil || run == nil { return errors.New("unknown or duplicate component operation") } worker.handlers[operation] = func(ctx context.Context, raw any, setting S) (any, error) { payload, err := decode(raw) if err != nil { return nil, errors.New("invalid component payload") } return run(ctx, payload, setting) } return nil } func contains(values []string, target string) bool { for _, value := range values { if value == target { return true } } return false } type event struct { message map[string]any err error } type result struct { id int64 payload any err error } func (w *Worker[S]) Serve(input io.Reader, output io.Writer) error { if len(w.handlers) != len(w.contract.Operations) { return errors.New("component operations are not fully registered") } messages := make(chan event, 1) done := make(chan struct{}) defer close(done) go func() { for { message, err := readFrame(input) select { case messages <- event{message, err}: case <-done: return } if err != nil { return } } }() first := <-messages if first.err != nil { return first.err } setting, err := w.handshake(first.message, output) if err != nil { return err } results := make(chan result, 1) var cancel context.CancelFunc var active int64 var activeDone chan struct{} defer func() { if active != 0 { _ = stopHandler(cancel, activeDone) } }() nextID := int64(1) lastCancelled := false for { select { case received := <-messages: if received.err != nil { return received.err } message := received.message kind, ok := message["kind"].(string) if !ok { return errors.New("invalid component kind") } switch kind { case "health": if !exact(message, "kind", "id") || requestID(message["id"]) != 0 { return errors.New("invalid component health") } if err := writeFrame(output, message); err != nil { return err } case "call": if !exact(message, "kind", "id", "operation", "payload") { return errors.New("invalid component call") } id := requestID(message["id"]) operation, ok := message["operation"].(string) run := w.handlers[operation] if id != nextID || active != 0 || !ok || run == nil { return errors.New("invalid component call") } nextID++ ctx, stop := context.WithCancel(context.Background()) cancel, active = stop, id activeDone = make(chan struct{}) payload := message["payload"] go func(finished chan struct{}) { defer close(finished) value, err := run(ctx, payload, setting) select { case results <- result{id, value, err}: case <-ctx.Done(): case <-done: } }(activeDone) case "cancel": if !exact(message, "kind", "id") { return errors.New("invalid component cancel") } id := requestID(message["id"]) if id <= 0 { return errors.New("invalid component cancel") } if id == active { if err := stopHandler(cancel, activeDone); err != nil { active = 0 activeDone = nil return err } active = 0 activeDone = nil lastCancelled = true if err := writeFrame(output, map[string]any{"kind": "error", "id": id, "error": "dever.cancelled", "payload": nil}); err != nil { return err } } else if id != nextID-1 || lastCancelled { return errors.New("unknown component cancel id") } case "shutdown": if !exact(message, "kind") { return errors.New("invalid component shutdown") } if active != 0 { if err := stopHandler(cancel, activeDone); err != nil { active = 0 activeDone = nil return err } active = 0 activeDone = nil } return writeFrame(output, map[string]any{"kind": "shutdown"}) default: return errors.New("unknown component message") } case completed := <-results: if completed.id != active { continue } cancel() active = 0 activeDone = nil lastCancelled = false if completed.err == nil { if err := writeFrame(output, map[string]any{"kind": "result", "id": completed.id, "payload": completed.payload}); err != nil { return err } continue } var business BusinessError if !errors.As(completed.err, &business) || !contains(w.contract.Errors, business.Identity) { return errors.New("component handler failed") } if err := writeFrame(output, map[string]any{"kind": "error", "id": completed.id, "error": business.Identity, "payload": business.Payload}); err != nil { return err } } } } func stopHandler(cancel context.CancelFunc, finished <-chan struct{}) error { cancel() timer := time.NewTimer(cancelGrace) defer timer.Stop() select { case <-finished: return nil case <-timer.C: return errors.New("component handler did not stop after cancellation") } } func (w *Worker[S]) handshake(hello map[string]any, output io.Writer) (S, error) { var zero S if !exact(hello, "kind", "version", "port", "schema", "adapter", "capabilities", "operations", "setting") || hello["kind"] != "hello" || hello["version"] != Version || hello["port"] != w.contract.Port || hello["schema"] != w.contract.Schema || hello["adapter"] != w.contract.Adapter || !sameNames(hello["capabilities"], w.contract.Capabilities) || !sameNames(hello["operations"], w.contract.Operations) { return zero, errors.New("component handshake does not match registered contract") } setting, err := w.decodeSetting(hello["setting"]) if err != nil { return zero, errors.New("invalid component setting") } if err := writeFrame(output, map[string]any{"kind": "ready", "version": Version, "port": w.contract.Port, "schema": w.contract.Schema, "adapter": w.contract.Adapter, "capabilities": w.contract.Capabilities, "operations": w.contract.Operations}); err != nil { return zero, err } return setting, nil } func sameNames(raw any, expected []string) bool { values, ok := raw.([]any) if !ok || len(values) != len(expected) { return false } for i, value := range values { if value != expected[i] { return false } } return true } func exact(message map[string]any, names ...string) bool { if len(message) != len(names) { return false } for _, name := range names { if _, ok := message[name]; !ok { return false } } return true } func requestID(value any) int64 { number, ok := value.(json.Number) if !ok { return -1 } id, err := number.Int64() if err != nil || id < 0 { return -1 } return id } func readFrame(input io.Reader) (map[string]any, error) { var header [4]byte if _, err := io.ReadFull(input, header[:]); err != nil { return nil, errors.New("incomplete component frame") } size := binary.BigEndian.Uint32(header[:]) if size == 0 || size > maxBytes { return nil, errors.New("component frame exceeds byte limit") } body := make([]byte, size) if _, err := io.ReadFull(input, body); err != nil { return nil, errors.New("incomplete component frame") } return parseJSON(body) } func writeFrame(output io.Writer, message map[string]any) error { body, err := json.Marshal(message) if err != nil { return errors.New("invalid handler response") } if len(body) == 0 || len(body) > maxBytes { return errors.New("component frame exceeds byte limit") } if _, err := parseJSON(body); err != nil { return err } var header [4]byte binary.BigEndian.PutUint32(header[:], uint32(len(body))) if err := writeAll(output, header[:]); err != nil { return err } return writeAll(output, body) } func writeAll(output io.Writer, data []byte) error { for len(data) > 0 { count, err := output.Write(data) if err != nil { return err } if count == 0 { return io.ErrShortWrite } data = data[count:] } return nil } func parseJSON(body []byte) (map[string]any, error) { if !utf8.Valid(body) { return nil, errors.New("component frame is not UTF-8") } decoder := json.NewDecoder(bytes.NewReader(body)) decoder.UseNumber() remaining := maxElements value, err := parseValue(decoder, 0, &remaining) if err != nil { return nil, err } if _, err := decoder.Token(); err != io.EOF { return nil, errors.New("invalid component JSON") } object, ok := value.(map[string]any) if !ok { return nil, errors.New("component message must be an object") } return object, nil } func parseValue(decoder *json.Decoder, depth int, remaining *int) (any, error) { if depth > maxDepth || *remaining <= 0 { return nil, errors.New("wire JSON exceeds limit") } *remaining-- token, err := decoder.Token() if err != nil { return nil, errors.New("invalid component JSON") } delim, ok := token.(json.Delim) if !ok { if number, isNumber := token.(json.Number); isNumber && strings.ContainsAny(string(number), ".eE") { value, err := strconv.ParseFloat(string(number), 64) if err != nil || math.IsInf(value, 0) || math.IsNaN(value) { return nil, errors.New("non-finite wire Float") } } return token, nil } if depth == maxDepth { return nil, errors.New("wire JSON exceeds depth limit") } switch delim { case '{': object := make(map[string]any) for decoder.More() { key, err := decoder.Token() if err != nil { return nil, errors.New("invalid component JSON") } name, ok := key.(string) if !ok { return nil, errors.New("invalid component JSON") } if _, exists := object[name]; exists { return nil, errors.New("duplicate JSON field") } value, err := parseValue(decoder, depth+1, remaining) if err != nil { return nil, err } object[name] = value } if end, err := decoder.Token(); err != nil || end != json.Delim('}') { return nil, errors.New("invalid component JSON") } return object, nil case '[': array := make([]any, 0) for decoder.More() { value, err := parseValue(decoder, depth+1, remaining) if err != nil { return nil, err } array = append(array, value) } if end, err := decoder.Token(); err != nil || end != json.Delim(']') { return nil, errors.New("invalid component JSON") } return array, nil default: return nil, errors.New("invalid component JSON") } }