fix: add involves edge from task to agent:nomos at creation
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled

Plus sync vendor directory for Docker build compatibility.
This commit is contained in:
2026-08-11 22:03:12 +02:00
parent 7d6a3320d4
commit febc153b7f
3384 changed files with 945212 additions and 2 deletions

View File

@@ -0,0 +1,391 @@
package openapi3
import (
"context"
"encoding/json"
"fmt"
"maps"
"net/url"
"slices"
"github.com/go-openapi/jsonpointer"
)
// T is the root of an OpenAPI v3 document
// See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#openapi-object
// and https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#openapi-object
type T struct {
Extensions map[string]any `json:"-" yaml:"-"`
Origin *Origin `json:"-" yaml:"-"`
OpenAPI string `json:"openapi" yaml:"openapi"` // Required
Components *Components `json:"components,omitempty" yaml:"components,omitempty"`
Info *Info `json:"info" yaml:"info"` // Required
Paths *Paths `json:"paths" yaml:"paths"` // Required in 3.0, optional in 3.1
Security SecurityRequirements `json:"security,omitempty" yaml:"security,omitempty"`
Servers Servers `json:"servers,omitempty" yaml:"servers,omitempty"`
Tags Tags `json:"tags,omitempty" yaml:"tags,omitempty"`
ExternalDocs *ExternalDocs `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
Webhooks map[string]*PathItem `json:"webhooks,omitempty" yaml:"webhooks,omitempty"` // OpenAPI >=3.1
JSONSchemaDialect string `json:"jsonSchemaDialect,omitempty" yaml:"jsonSchemaDialect,omitempty"` // OpenAPI >=3.1
visited visitedComponent
url *url.URL
// Document-scoped format validators
// These validators are automatically used by all schemas in this document
stringFormats map[string]StringFormatValidator
numberFormats map[string]NumberFormatValidator
integerFormats map[string]IntegerFormatValidator
}
// IsOpenAPI30 returns whether doc is an OpenAPI document version 3.0.x.
// Returns true for 3, 3.0, 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.0.4, ...
// And false for 3.1.0, 3.2, ... and for invalid strings.
func (doc *T) IsOpenAPI30() bool {
return doc.OpenAPIMajorMinor() == "3.0"
}
// IsOpenAPI31OrLater returns whether doc is an OpenAPI document version >=3.1.
// Returns true for 3.1, 3.1.0, 3.1.1, 3.1.2, 3.2.0, ...
// And false for cases where IsOpenAPI30 returns true and for invalid strings.
func (doc *T) IsOpenAPI31OrLater() bool {
return slices.Contains([]string{"3.1", "3.2"}, doc.OpenAPIMajorMinor())
}
func errFieldFor31Plus(field string, origin *Origin) error {
return newFieldFor31Plus(field, origin)
}
func errValueOfFieldFor31Plus(value any, field string) error {
return fmt.Errorf("value %q of field %s is for OpenAPI >=3.1", value, field)
}
// OpenAPIMajorMinor returns 3.y of the OpenAPI "3.y" or "3.y.z" version of the document.
// Returns the empty string for invalid OpenAPI version strings.
func (doc *T) OpenAPIMajorMinor() string {
if doc == nil {
return ""
}
switch doc.OpenAPI {
case "3", "3.0", "3.0.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4":
return "3.0"
case "3.1", "3.1.0", "3.1.1", "3.1.2":
return "3.1"
case "3.2", "3.2.0":
return "3.2"
default:
return ""
}
}
var _ jsonpointer.JSONPointable = (*T)(nil)
// JSONLookup implements https://pkg.go.dev/github.com/go-openapi/jsonpointer#JSONPointable
func (doc *T) JSONLookup(token string) (any, error) {
switch token {
case "openapi":
return doc.OpenAPI, nil
case "components":
return doc.Components, nil
case "info":
return doc.Info, nil
case "paths":
return doc.Paths, nil
case "security":
return doc.Security, nil
case "servers":
return doc.Servers, nil
case "tags":
return doc.Tags, nil
case "externalDocs":
return doc.ExternalDocs, nil
case "webhooks":
return doc.Webhooks, nil
case "jsonSchemaDialect":
return doc.JSONSchemaDialect, nil
}
v, _, err := jsonpointer.GetForToken(doc.Extensions, token)
return v, err
}
// MarshalJSON returns the JSON encoding of T.
func (doc *T) MarshalJSON() ([]byte, error) {
x, err := doc.MarshalYAML()
if err != nil {
return nil, err
}
return json.Marshal(x)
}
// MarshalYAML returns the YAML encoding of T.
func (doc *T) MarshalYAML() (any, error) {
if doc == nil {
return nil, nil
}
m := make(map[string]any, 10+len(doc.Extensions))
maps.Copy(m, doc.Extensions)
m["openapi"] = doc.OpenAPI
if x := doc.Components; x != nil {
m["components"] = x
}
m["info"] = doc.Info
m["paths"] = doc.Paths
if x := doc.Security; len(x) != 0 {
m["security"] = x
}
if x := doc.Servers; len(x) != 0 {
m["servers"] = x
}
if x := doc.Tags; len(x) != 0 {
m["tags"] = x
}
if x := doc.ExternalDocs; x != nil {
m["externalDocs"] = x
}
if x := doc.Webhooks; len(x) != 0 {
m["webhooks"] = x
}
if x := doc.JSONSchemaDialect; x != "" {
m["jsonSchemaDialect"] = x
}
return m, nil
}
// UnmarshalJSON sets T to a copy of data.
func (doc *T) UnmarshalJSON(data []byte) error {
type TBis T
var x TBis
if err := json.Unmarshal(data, &x); err != nil {
return unmarshalError(err)
}
_ = json.Unmarshal(data, &x.Extensions)
delete(x.Extensions, "openapi")
delete(x.Extensions, "components")
delete(x.Extensions, "info")
delete(x.Extensions, "paths")
delete(x.Extensions, "security")
delete(x.Extensions, "servers")
delete(x.Extensions, "tags")
delete(x.Extensions, "externalDocs")
delete(x.Extensions, "webhooks")
delete(x.Extensions, "jsonSchemaDialect")
if len(x.Extensions) == 0 {
x.Extensions = nil
}
delete(x.Webhooks, originKey)
*doc = T(x)
return nil
}
func (doc *T) AddOperation(path string, method string, operation *Operation) {
if doc.Paths == nil {
doc.Paths = NewPaths()
}
pathItem := doc.Paths.Value(path)
if pathItem == nil {
pathItem = &PathItem{}
doc.Paths.Set(path, pathItem)
}
pathItem.SetOperation(method, operation)
}
func (doc *T) AddServer(server *Server) {
doc.Servers = append(doc.Servers, server)
}
func (doc *T) AddServers(servers ...*Server) {
doc.Servers = append(doc.Servers, servers...)
}
// SetStringFormatValidators sets document-scoped string format validators.
// These validators are automatically used by all schemas in this document.
func (doc *T) SetStringFormatValidators(validators map[string]StringFormatValidator) {
doc.stringFormats = validators
}
// SetStringFormatValidator sets a single document-scoped string format validator.
func (doc *T) SetStringFormatValidator(name string, validator StringFormatValidator) {
if doc.stringFormats == nil {
doc.stringFormats = make(map[string]StringFormatValidator)
}
doc.stringFormats[name] = validator
}
// SetNumberFormatValidators sets document-scoped number format validators.
// These validators are automatically used by all schemas in this document.
func (doc *T) SetNumberFormatValidators(validators map[string]NumberFormatValidator) {
doc.numberFormats = validators
}
// SetNumberFormatValidator sets a single document-scoped number format validator.
func (doc *T) SetNumberFormatValidator(name string, validator NumberFormatValidator) {
if doc.numberFormats == nil {
doc.numberFormats = make(map[string]NumberFormatValidator)
}
doc.numberFormats[name] = validator
}
// SetIntegerFormatValidators sets document-scoped integer format validators.
// These validators are automatically used by all schemas in this document.
func (doc *T) SetIntegerFormatValidators(validators map[string]IntegerFormatValidator) {
doc.integerFormats = validators
}
// SetIntegerFormatValidator sets a single document-scoped integer format validator.
func (doc *T) SetIntegerFormatValidator(name string, validator IntegerFormatValidator) {
if doc.integerFormats == nil {
doc.integerFormats = make(map[string]IntegerFormatValidator)
}
doc.integerFormats[name] = validator
}
// GetSchemaValidationOptions returns SchemaValidationOptions that include
// this document's format validators. Use this when validating schemas from this document.
func (doc *T) GetSchemaValidationOptions() []SchemaValidationOption {
var opts []SchemaValidationOption
if doc.stringFormats != nil {
opts = append(opts, WithStringFormatValidators(doc.stringFormats))
}
if doc.numberFormats != nil {
opts = append(opts, WithNumberFormatValidators(doc.numberFormats))
}
if doc.integerFormats != nil {
opts = append(opts, WithIntegerFormatValidators(doc.integerFormats))
}
return opts
}
// Validate returns an error if T does not comply with the OpenAPI spec.
// Validations Options can be provided to modify the validation behavior.
//
// By default, doc.OpenAPI's field dictates whether "JSON Schema Draft 2020-12" validation
// is enabled.
func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error {
if doc.IsOpenAPI31OrLater() {
opts = append(opts, IsOpenAPI31OrLater())
}
ctx = WithValidationOptions(ctx, opts...)
me := newErrCollector(ctx)
if doc.OpenAPI == "" {
if err := me.emit(newOpenAPIVersionRequired(doc.Origin)); err != nil {
return err
}
}
if doc.Webhooks != nil && !doc.IsOpenAPI31OrLater() {
if err := me.emit(newWebhooksFieldFor31Plus(doc.Origin)); err != nil {
return err
}
}
if doc.JSONSchemaDialect != "" && !doc.IsOpenAPI31OrLater() {
if err := me.emit(newJSONSchemaDialectFieldFor31Plus(doc.Origin)); err != nil {
return err
}
}
wrapSection := func(section string) func(error) error {
return func(e error) error { return &SectionValidationError{Section: section, Cause: e} }
}
var wrap func(error) error
wrap = wrapSection("components")
if v := doc.Components; v != nil {
if err := me.emitWrapped(wrap, v.Validate(ctx)); err != nil {
return err
}
}
wrap = wrapSection("info")
if v := doc.Info; v != nil {
if err := me.emitWrapped(wrap, v.Validate(ctx)); err != nil {
return err
}
} else if err := me.emit(wrap(newInfoRequired(doc.Origin))); err != nil {
return err
}
wrap = wrapSection("paths")
if v := doc.Paths; v != nil {
if err := me.emitWrapped(wrap, v.Validate(ctx)); err != nil {
return err
}
} else if doc.IsOpenAPI30() {
if err := me.emit(wrap(newPathsRequired(doc.Origin))); err != nil {
return err
}
}
wrap = wrapSection("security")
if v := doc.Security; v != nil {
if err := me.emitWrapped(wrap, v.Validate(ctx)); err != nil {
return err
}
}
wrap = wrapSection("servers")
if v := doc.Servers; v != nil {
if err := me.emitWrapped(wrap, v.Validate(ctx)); err != nil {
return err
}
}
wrap = wrapSection("tags")
if v := doc.Tags; v != nil {
if err := me.emitWrapped(wrap, v.Validate(ctx)); err != nil {
return err
}
}
wrap = wrapSection("external docs")
if v := doc.ExternalDocs; v != nil {
if err := me.emitWrapped(wrap, v.Validate(ctx)); err != nil {
return err
}
}
wrap = wrapSection("webhooks")
for _, name := range componentNames(doc.Webhooks) {
pathItem := doc.Webhooks[name]
if pathItem == nil {
if err := me.emit(wrap(newWebhookNil(name))); err != nil {
return err
}
// Nothing to descend into for a nil webhook; the nil itself
// is the only finding under this name until the entry is
// populated, so continue to the next webhook.
continue
}
wrapWebhook := func(e error) error { return wrap(&WebhookValidationError{Name: name, Cause: e}) }
if err := me.emitWrapped(wrapWebhook, pathItem.Validate(ctx)); err != nil {
return err
}
}
wrap = wrapSection("jsonSchemaDialect")
if doc.JSONSchemaDialect != "" {
u, err := url.Parse(doc.JSONSchemaDialect)
if err != nil {
if err = me.emit(wrap(err)); err != nil {
return err
}
} else if u.Scheme == "" {
if err := me.emit(wrap(newJSONSchemaDialectAbsoluteURIRequired(doc.Origin))); err != nil {
return err
}
}
}
return me.finalize(validateExtensions(ctx, doc.Extensions, doc.Origin))
}
// ValidateSchemaJSON validates data against a schema using this document's format validators.
// This is a convenience method that automatically applies the document's format validators.
func (doc *T) ValidateSchemaJSON(schema *Schema, value any, opts ...SchemaValidationOption) error {
// Combine document's validators with any additional options
allOpts := append(doc.GetSchemaValidationOptions(), opts...)
return schema.VisitJSON(value, allOpts...)
}