diff --git a/docs/dsl/docs.go b/docs/dsl/docs.go index f173ab99..938a6ce4 100644 --- a/docs/dsl/docs.go +++ b/docs/dsl/docs.go @@ -4,23 +4,58 @@ import ( "goa.design/goa/v3/eval" goaexpr "goa.design/goa/v3/expr" "goa.design/plugins/v3/docs" - "goa.design/plugins/v3/docs/expr" + plugexpr "goa.design/plugins/v3/docs/expr" ) // init registers the docs plugin when importing the DSL. func init() { docs.Register() } // UseJSONTags configures the docs plugin to use JSON struct tags declared via -// Meta("struct:tag:json", ...) as field names in generated docs. This setting -// affects definitions, payloads, results, and error schemas and examples. -func UseJSONTags() { expr.Root.UseJSONTags = true } +// Meta("struct:tag:json", ...) as field names in generated docs. +// +// This setting affects type definitions, payloads, results, and error schemas +// and their examples. +// +// Usage: +// +// var _ = API("my api", func() { +// // Use field names from struct JSON tags throughout docs.json +// docs.UseJSONTags() +// }) +func UseJSONTags() { plugexpr.Root.UseJSONTags = true } // InlineRefs configures the docs plugin to inline referenced schemas in JSON -// Schema output where possible. Cycles are preserved by keeping $ref. -func InlineRefs() { expr.Root.InlineRefs = true } +// Schema output where possible. Cycles are preserved by keeping $ref where +// needed (e.g., recursive references). +// +// Usage: +// +// var _ = API("my api", func() { +// // Prefer inlined schemas rather than $ref when there are no cycles +// docs.InlineRefs() +// }) +func InlineRefs() { plugexpr.Root.InlineRefs = true } + +// IncludeTypes registers user types to force-emit in docs.json definitions. +// Accepts user types defined via Type or ResultType. +// +// Service and method schemas are always generated by the docs plugin when not +// disabled on the service/method. IncludeTypes does not change service/method +// emission. This is only useful for types that are generated via the "force" +// Goa Meta DSL; it ensures those user types (and their transitive dependencies) +// are included under the top-level "definitions" object. +// +// Usage: +// +// var _ = API("my api", func() { +// // Ensure these shared types appear in docs.json definitions so downstream +// // tooling can resolve schemas by name. +// docs.IncludeTypes(MySharedType, AnotherType) +// }) +func IncludeTypes(ts ...goaexpr.UserType) { plugexpr.Root.IncludeTypes(ts...) } -// DisableDocs disables docs.json generation for the current service only. -// It does not affect OpenAPI generation. Invoke inside a Service DSL. +// DisableDocs disables docs.json generation for the current service or method. +// It does not affect OpenAPI generation. Invoke inside a Service or Method DSL. // // Service("front", func() { // DisableDocs() diff --git a/docs/expr/root.go b/docs/expr/root.go index d7d07c00..e5ebc679 100644 --- a/docs/expr/root.go +++ b/docs/expr/root.go @@ -18,6 +18,9 @@ type ( // replacing them with copies of their referenced definitions where // possible. Cycles are preserved by leaving $ref in place when needed. InlineRefs bool + + // IncludedTypes are the user types to force-emit into definitions. + IncludedTypes []expr.UserType } ) @@ -39,3 +42,12 @@ func (*RootExpr) DependsOn() []eval.Root { return []eval.Root{expr.Root} } // This is used to skip frames that point to files in these packages when // computing the location of errors. func (*RootExpr) Packages() []string { return []string{"goa.design/plugins/v3/docs/dsl"} } + +// IncludeTypes registers the given user types for forced definition emission. +func (r *RootExpr) IncludeTypes(ts ...expr.UserType) { + for _, t := range ts { + if t != nil { + r.IncludedTypes = append(r.IncludedTypes, t) + } + } +} diff --git a/docs/generate.go b/docs/generate.go index c279c4d9..ed77fcd9 100644 --- a/docs/generate.go +++ b/docs/generate.go @@ -11,7 +11,7 @@ import ( "goa.design/goa/v3/codegen" "goa.design/goa/v3/eval" - "goa.design/goa/v3/expr" + goaexpr "goa.design/goa/v3/expr" "goa.design/goa/v3/http/codegen/openapi" plugexpr "goa.design/plugins/v3/docs/expr" ) @@ -41,7 +41,7 @@ func Generate(_ string, roots []eval.Root, files []*codegen.File) ([]*codegen.Fi var agg *data for _, root := range roots { - r, ok := root.(*expr.RootExpr) + r, ok := root.(*goaexpr.RootExpr) if !ok { continue } @@ -104,7 +104,7 @@ func Generate(_ string, roots []eval.Root, files []*codegen.File) ([]*codegen.Fi // docsDataForRoot builds the docs data for a single root while scoping // openapi.Definitions to that root only. The global definitions map is restored // before returning. -func docsDataForRoot(r *expr.RootExpr) *data { +func docsDataForRoot(r *goaexpr.RootExpr) *data { prev := openapi.Definitions openapi.Definitions = make(map[string]*openapi.Schema) defer func() { openapi.Definitions = prev }() @@ -117,7 +117,7 @@ func docsDataForRoot(r *expr.RootExpr) *data { return d } -func docsFile(r *expr.RootExpr) *codegen.File { +func docsFile(r *goaexpr.RootExpr) *codegen.File { // Per-run generation state state := newGenState() docs := &data{ @@ -132,6 +132,14 @@ func docsFile(r *expr.RootExpr) *codegen.File { defs[n] = dupSchema(d) } + // Force-emit definitions for explicitly included user types (and deps). + if its := plugexpr.Root.IncludedTypes; len(its) > 0 { + forced := forcedDefinitions(r.API, its, state) + for n, s := range forced { + defs[n] = s + } + } + // Apply JSON tag transforms if requested. if plugexpr.Root.UseJSONTags { defs = transformDefinitionsWithJSONTagsHybrid(r, defs) @@ -174,6 +182,72 @@ func docsFile(r *expr.RootExpr) *codegen.File { } } +// forcedDefinitions builds JSON Schemas for the given user types and their +// transitive dependencies and returns a name->schema map suitable for inclusion +// in the top-level definitions object. +func forcedDefinitions(api *goaexpr.APIExpr, uts []goaexpr.UserType, state *genState) map[string]*openapi.Schema { //nolint:cyclop + seen := make(map[string]*goaexpr.UserTypeExpr) + + var addUT func(goaexpr.UserType) + addUT = func(ut goaexpr.UserType) { + if ut == nil { + return + } + if ute, ok := ut.(*goaexpr.UserTypeExpr); ok { + name := ute.TypeName + if _, ok := seen[name]; ok { + return + } + seen[name] = ute + walkDeps(ute.AttributeExpr, addUT) + } + } + + for _, ut := range uts { + addUT(ut) + } + + out := make(map[string]*openapi.Schema, len(seen)) + for name, ute := range seen { + sch := schemaForAttribute(api, ute.AttributeExpr, state) + out[name] = dupSchema(sch) + } + return out +} + +// walkDeps recursively visits attribute data types and invokes add on any +// discovered user types (including result types). It follows bases and +// references to mirror behavior elsewhere in the plugin. +func walkDeps(att *goaexpr.AttributeExpr, add func(goaexpr.UserType)) { + if att == nil || att.Type == nil { + return + } + switch t := att.Type.(type) { + case goaexpr.UserType: + add(t) + walkDeps(t.Attribute(), add) + case *goaexpr.Array: + walkDeps(t.ElemType, add) + case *goaexpr.Map: + walkDeps(t.KeyType, add) + walkDeps(t.ElemType, add) + case *goaexpr.Object: + for _, nat := range *t { + walkDeps(nat.Attribute, add) + } + case *goaexpr.Union: + for _, v := range t.Values { + walkDeps(v.Attribute, add) + } + } + for _, b := range att.Bases { + walkDeps(&goaexpr.AttributeExpr{Type: b}, add) + } + for _, r := range att.References { + walkDeps(&goaexpr.AttributeExpr{Type: r}, add) + } +} + // dupSchema creates a safe deep copy of the given schema, ensuring maps are initialized. func dupSchema(s *openapi.Schema) *openapi.Schema { if s == nil { @@ -226,7 +300,7 @@ func dupSchema(s *openapi.Schema) *openapi.Schema { return &js } -func apiDocs(api *expr.APIExpr) *apiData { +func apiDocs(api *goaexpr.APIExpr) *apiData { data := &apiData{ Name: api.Name, Title: api.Title, @@ -260,7 +334,7 @@ func apiDocs(api *expr.APIExpr) *apiData { // mustGenerateService returns false if the service (or its HTTP service) is // marked with Meta("openapi:generate", "false") or legacy // Meta("swagger:generate", "false"). -func mustGenerateService(r *expr.RootExpr, svc *expr.ServiceExpr) bool { +func mustGenerateService(r *goaexpr.RootExpr, svc *goaexpr.ServiceExpr) bool { // Explicit docs DSL can disable docs.json without impacting OpenAPI if vals, ok := svc.Meta["docs:generate"]; ok && len(vals) > 0 && strings.EqualFold(vals[len(vals)-1], "false") { return false @@ -286,7 +360,7 @@ func mustGenerateService(r *expr.RootExpr, svc *expr.ServiceExpr) bool { // "false"). If HTTP endpoints exist for the method, then the method is only // considered generatable if at least one endpoint is also generatable (mirrors // Goa behavior where endpoint-level meta gates individual operations). -func mustGenerateMethod(r *expr.RootExpr, meth *expr.MethodExpr) bool { //nolint:cyclop +func mustGenerateMethod(r *goaexpr.RootExpr, meth *goaexpr.MethodExpr) bool { //nolint:cyclop if vals, ok := meth.Meta["docs:generate"]; ok && len(vals) > 0 && strings.EqualFold(vals[len(vals)-1], "false") { return false } @@ -322,7 +396,7 @@ func mustGenerateMethod(r *expr.RootExpr, meth *expr.MethodExpr) bool { //nolint return true } -func servicesDocs(r *expr.RootExpr, state *genState) map[string]*serviceData { +func servicesDocs(r *goaexpr.RootExpr, state *genState) map[string]*serviceData { svcs := make(map[string]*serviceData, len(r.Services)) for _, svc := range r.Services { @@ -351,7 +425,7 @@ func servicesDocs(r *expr.RootExpr, state *genState) map[string]*serviceData { return svcs } -func generateServer(s *expr.ServerExpr) *serverData { +func generateServer(s *goaexpr.ServerExpr) *serverData { data := &serverData{ Name: s.Name, Description: s.Description, @@ -371,7 +445,7 @@ func generateServer(s *expr.ServerExpr) *serverData { data.Hosts[h.Name].URIs[i] = string(u) } } - if o := expr.AsObject(h.Variables.Type); o != nil { + if o := goaexpr.AsObject(h.Variables.Type); o != nil { data.Hosts[h.Name].Variables = make([]*variableData, len(*o)) for i, na := range *o { var def string @@ -393,7 +467,7 @@ func generateServer(s *expr.ServerExpr) *serverData { return data } -func generateRequirement(req *expr.SecurityExpr) *requirementData { +func generateRequirement(req *goaexpr.SecurityExpr) *requirementData { r := &requirementData{Scopes: req.Scopes} if len(req.Schemes) > 0 { r.Schemes = make([]*schemeData, len(req.Schemes)) @@ -416,14 +490,14 @@ func generateRequirement(req *expr.SecurityExpr) *requirementData { return r } -func generateMethod(api *expr.APIExpr, meth *expr.MethodExpr, state *genState) *methodData { +func generateMethod(api *goaexpr.APIExpr, meth *goaexpr.MethodExpr, state *genState) *methodData { m := &methodData{ Name: meth.Name, Description: meth.Description, Payload: generatePayload(api, meth.Payload, state), StreamingPayload: generatePayload(api, meth.StreamingPayload, state), } - if meth.Stream == expr.BidirectionalStreamKind || meth.Stream == expr.ServerStreamKind { + if meth.Stream == goaexpr.BidirectionalStreamKind || meth.Stream == goaexpr.ServerStreamKind { m.StreamingResult = generatePayload(api, meth.Result, state) } else { m.Result = generatePayload(api, meth.Result, state) @@ -439,9 +513,9 @@ func generateMethod(api *expr.APIExpr, meth *expr.MethodExpr, state *genState) * return m } -func generatePayload(api *expr.APIExpr, att *expr.AttributeExpr, state *genState) *payloadData { +func generatePayload(api *goaexpr.APIExpr, att *goaexpr.AttributeExpr, state *genState) *payloadData { // Do not generate payload for Empty - if ut, ok := att.Type.(*expr.UserTypeExpr); ok && ut == expr.Empty { + if ut, ok := att.Type.(*goaexpr.UserTypeExpr); ok && ut == goaexpr.Empty { return nil } @@ -459,7 +533,7 @@ func generatePayload(api *expr.APIExpr, att *expr.AttributeExpr, state *genState } } -func generateError(api *expr.APIExpr, er *expr.ErrorExpr, state *genState) *errorData { +func generateError(api *goaexpr.APIExpr, er *goaexpr.ErrorExpr, state *genState) *errorData { _, temporary := er.Meta["goa:error:temporary"] _, timeout := er.Meta["goa:error:timeout"] _, fault := er.Meta["goa:error:fault"] @@ -489,7 +563,7 @@ func mustJSON(d interface{}) string { // inline $ref logic removed // transformDefinitionsWithJSONTagsHybrid tries Root.UserType lookup. -func transformDefinitionsWithJSONTagsHybrid(r *expr.RootExpr, defs map[string]*openapi.Schema) map[string]*openapi.Schema { +func transformDefinitionsWithJSONTagsHybrid(r *goaexpr.RootExpr, defs map[string]*openapi.Schema) map[string]*openapi.Schema { if len(defs) == 0 { return defs } @@ -507,7 +581,7 @@ func transformDefinitionsWithJSONTagsHybrid(r *expr.RootExpr, defs map[string]*o // applyJSONTagsToSchema mutates s to use JSON tag names from Meta on the given // attribute and its descendants. It preserves required field semantics and // updates examples when present. -func applyJSONTagsToSchema(att *expr.AttributeExpr, s *openapi.Schema) { +func applyJSONTagsToSchema(att *goaexpr.AttributeExpr, s *openapi.Schema) { if att == nil || s == nil { return } @@ -519,10 +593,10 @@ func applyJSONTagsToSchema(att *expr.AttributeExpr, s *openapi.Schema) { // Unwrap user/result types to their underlying attributes before processing. for { switch t := att.Type.(type) { - case *expr.ResultTypeExpr: + case *goaexpr.ResultTypeExpr: att = t.AttributeExpr continue - case expr.UserType: + case goaexpr.UserType: att = t.Attribute() continue } @@ -531,15 +605,15 @@ func applyJSONTagsToSchema(att *expr.AttributeExpr, s *openapi.Schema) { // Recurse into composite types first so nested structures are handled. switch t := att.Type.(type) { - case *expr.Array: + case *goaexpr.Array: if s.Items != nil { applyJSONTagsToSchema(t.ElemType, s.Items) } - case *expr.Map: + case *goaexpr.Map: if as, ok := s.AdditionalProperties.(*openapi.Schema); ok { applyJSONTagsToSchema(t.ElemType, as) } - case *expr.Union: + case *goaexpr.Union: for i, v := range t.Values { if i < len(s.AnyOf) { applyJSONTagsToSchema(v.Attribute, s.AnyOf[i]) @@ -549,11 +623,11 @@ func applyJSONTagsToSchema(att *expr.AttributeExpr, s *openapi.Schema) { // Handle object property renaming and example/required updates. // If multiple fields resolve to the same JSON tag, the first seen wins. - if obj := expr.AsObject(att.Type); obj != nil && s.Properties != nil { + if obj := goaexpr.AsObject(att.Type); obj != nil && s.Properties != nil { // Build new properties map using JSON tag names. Use walkAttribute so bases/references are included. newProps := make(map[string]*openapi.Schema, len(s.Properties)) nameMap := make(map[string]string, len(*obj)) - _ = walkAttribute(att, func(oldName string, child *expr.AttributeExpr) error { + _ = walkAttribute(att, func(oldName string, child *goaexpr.AttributeExpr) error { jsonName := jsonTagName(child) if jsonName == "" || jsonName == "-" { jsonName = oldName @@ -597,13 +671,13 @@ func applyJSONTagsToSchema(att *expr.AttributeExpr, s *openapi.Schema) { // walkAttribute iterates over the given attribute, its bases and references (if any), // calling the iterator for each field of object types. This mirrors goa's internal // expr.walkAttribute to ensure bases and references are considered when transforming. -func walkAttribute(att *expr.AttributeExpr, it func(name string, a *expr.AttributeExpr) error) error { //nolint:cyclop +func walkAttribute(att *goaexpr.AttributeExpr, it func(name string, a *goaexpr.AttributeExpr) error) error { //nolint:cyclop switch dt := att.Type.(type) { - case expr.UserType: + case goaexpr.UserType: if err := walkAttribute(dt.Attribute(), it); err != nil { return err } - case *expr.Object: + case *goaexpr.Object: for _, nat := range *dt { if err := it(nat.Name, nat.Attribute); err != nil { return err @@ -611,12 +685,12 @@ func walkAttribute(att *expr.AttributeExpr, it func(name string, a *expr.Attribu } } for _, b := range att.Bases { - if err := walkAttribute(&expr.AttributeExpr{Type: b}, it); err != nil { + if err := walkAttribute(&goaexpr.AttributeExpr{Type: b}, it); err != nil { return err } } for _, r := range att.References { - if err := walkAttribute(&expr.AttributeExpr{Type: r}, it); err != nil { + if err := walkAttribute(&goaexpr.AttributeExpr{Type: r}, it); err != nil { return err } } @@ -625,7 +699,7 @@ func walkAttribute(att *expr.AttributeExpr, it func(name string, a *expr.Attribu // jsonTagName extracts the JSON tag field name from the attribute Meta if set. // It supports values like "name,omitempty" and returns "name". -func jsonTagName(att *expr.AttributeExpr) string { +func jsonTagName(att *goaexpr.AttributeExpr) string { if att == nil || att.Meta == nil { return "" } @@ -642,16 +716,16 @@ func jsonTagName(att *expr.AttributeExpr) string { // transformExampleWithJSONTags rewrites example map keys to match JSON tags from // Meta. It recurses through objects and arrays. For user and result types it // recurses into the underlying attribute. -func transformExampleWithJSONTags(att *expr.AttributeExpr, ex any) any { +func transformExampleWithJSONTags(att *goaexpr.AttributeExpr, ex any) any { if att == nil || ex == nil { return ex } switch t := att.Type.(type) { - case *expr.ResultTypeExpr: + case *goaexpr.ResultTypeExpr: return transformExampleWithJSONTags(t.AttributeExpr, ex) - case expr.UserType: + case goaexpr.UserType: return transformExampleWithJSONTags(t.Attribute(), ex) - case *expr.Object: + case *goaexpr.Object: m, ok := ex.(map[string]any) if !ok { return ex @@ -668,7 +742,7 @@ func transformExampleWithJSONTags(att *expr.AttributeExpr, ex any) any { } } return res - case *expr.Array: + case *goaexpr.Array: if arr, ok := ex.([]any); ok { out := make([]any, len(arr)) for i := range arr { @@ -677,7 +751,7 @@ func transformExampleWithJSONTags(att *expr.AttributeExpr, ex any) any { return out } return ex - case *expr.Map: + case *goaexpr.Map: // Only transform element values. switch m := ex.(type) { case map[string]any: @@ -695,7 +769,7 @@ func transformExampleWithJSONTags(att *expr.AttributeExpr, ex any) any { default: return ex } - case *expr.Union: + case *goaexpr.Union: // Attempt best-effort transform by applying first variant. if len(t.Values) > 0 { return transformExampleWithJSONTags(t.Values[0].Attribute, ex) diff --git a/go.mod b/go.mod index 8d8e9b24..98686512 100644 --- a/go.mod +++ b/go.mod @@ -15,13 +15,13 @@ require ( ) require ( - github.com/aws/smithy-go v1.23.0 // indirect + github.com/aws/smithy-go v1.23.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dimfeld/httppath v0.0.0-20170720192232-ee938bf73598 // indirect github.com/go-chi/chi/v5 v5.2.3 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect + github.com/go-logfmt/logfmt v0.6.1 // indirect github.com/go-logr/logr v1.4.3 // indirect - github.com/gohugoio/hashstructure v0.5.0 // indirect + github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect github.com/kr/pretty v0.3.1 // indirect @@ -31,15 +31,15 @@ require ( go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/otel/trace v1.38.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.28.0 // indirect - golang.org/x/net v0.44.0 // indirect + golang.org/x/mod v0.29.0 // indirect + golang.org/x/net v0.46.0 // indirect golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.36.0 // indirect - golang.org/x/term v0.35.0 // indirect - golang.org/x/text v0.29.0 // indirect - golang.org/x/tools v0.37.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + golang.org/x/sys v0.37.0 // indirect + golang.org/x/term v0.36.0 // indirect + golang.org/x/text v0.30.0 // indirect + golang.org/x/tools v0.38.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f // indirect + google.golang.org/grpc v1.76.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/go.sum b/go.sum index a26eed27..0d48467c 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/aws/aws-lambda-go v1.50.0 h1:0GzY18vT4EsCvIyk3kn3ZH5Jg30NRlgYaai1w0aGPMU= github.com/aws/aws-lambda-go v1.50.0/go.mod h1:dpMpZgvWx5vuQJfBt0zqBha60q7Dd7RfgJv23DymV8A= -github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE= -github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/smithy-go v1.23.1 h1:sLvcH6dfAFwGkHLZ7dGiYF7aK6mg4CgKA/iDKjLDt9M= +github.com/aws/smithy-go v1.23.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -17,8 +17,8 @@ github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU= github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= -github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= -github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE= +github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -27,8 +27,8 @@ github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1 github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/gohugoio/hashstructure v0.5.0 h1:G2fjSBU36RdwEJBWJ+919ERvOVqAg9tfcYp47K9swqg= -github.com/gohugoio/hashstructure v0.5.0/go.mod h1:Ser0TniXuu/eauYmrwM4o64EBvySxNzITEOLlm4igec= +github.com/gohugoio/hashstructure v0.6.0 h1:7wMB/2CfXoThFYhdWRGv3u3rUM761Cq29CxUW+NltUg= +github.com/gohugoio/hashstructure v0.6.0/go.mod h1:lapVLk9XidheHG1IQ4ZSbyYrXcaILU1ZEP/+vno5rBQ= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -96,28 +96,28 @@ goa.design/goa/v3 v3.22.5 h1:8rSbco1Ind/jrSYsXN4fLzchxQrGgVESTQxSGYEGq8g= goa.design/goa/v3 v3.22.5/go.mod h1:PgV47RNYgRg+buOAs4xYG0eG38a1yWf/kgiQasejF8s= goa.design/model v1.13.0 h1:PeYp5lD7GhqGDRODNGXIdySl9em7VBhh91rCTwfhVmA= goa.design/model v1.13.0/go.mod h1:UypAKlz3BFCg4qa4DHNYpUq2ZLvaYjq6eonf5515uDU= -golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= -golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= -golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= -golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= -golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= -golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= -golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f h1:1FTH6cpXFsENbPR5Bu8NQddPSaUUE6NA2XdZdDSAJK4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251014184007-4626949a642f/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= +google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=