diff --git a/api/apiv1/design/database.go b/api/apiv1/design/database.go index b47b40ce..1b9842f1 100644 --- a/api/apiv1/design/database.go +++ b/api/apiv1/design/database.go @@ -228,11 +228,10 @@ var ServiceSpec = g.Type("ServiceSpec", func() { g.Description("Username of the database_users entry this service connects as. " + "The user must exist in database_users and have appropriate roles for the service's needs.") g.Example("app") - g.Default("") - g.Meta("struct:tag:json", "connect_as,omitempty") + g.Meta("struct:tag:json", "connect_as") }) - g.Required("service_id", "service_type", "version", "host_ids") + g.Required("service_id", "service_type", "version", "host_ids", "connect_as") }) var BackupRepositorySpec = g.Type("BackupRepositorySpec", func() { diff --git a/api/apiv1/gen/control_plane/service.go b/api/apiv1/gen/control_plane/service.go index 8fe269d8..5827ec14 100644 --- a/api/apiv1/gen/control_plane/service.go +++ b/api/apiv1/gen/control_plane/service.go @@ -1018,7 +1018,7 @@ type ServiceSpec struct { DatabaseConnection *DatabaseConnection `json:"database_connection,omitempty"` // Username of the database_users entry this service connects as. The user must // exist in database_users and have appropriate roles for the service's needs. - ConnectAs string `json:"connect_as,omitempty"` + ConnectAs string `json:"connect_as"` } // StartInstancePayload is the payload type of the control-plane service diff --git a/api/apiv1/gen/http/control_plane/client/encode_decode.go b/api/apiv1/gen/http/control_plane/client/encode_decode.go index 5d01e05f..b61db4b6 100644 --- a/api/apiv1/gen/http/control_plane/client/encode_decode.go +++ b/api/apiv1/gen/http/control_plane/client/encode_decode.go @@ -4738,12 +4738,6 @@ func marshalControlplaneServiceSpecToServiceSpecRequestBody(v *controlplane.Serv if v.DatabaseConnection != nil { res.DatabaseConnection = marshalControlplaneDatabaseConnectionToDatabaseConnectionRequestBody(v.DatabaseConnection) } - { - var zero string - if res.ConnectAs == zero { - res.ConnectAs = "" - } - } return res } @@ -5216,12 +5210,6 @@ func marshalServiceSpecRequestBodyToControlplaneServiceSpec(v *ServiceSpecReques if v.DatabaseConnection != nil { res.DatabaseConnection = marshalDatabaseConnectionRequestBodyToControlplaneDatabaseConnection(v.DatabaseConnection) } - { - var zero string - if res.ConnectAs == zero { - res.ConnectAs = "" - } - } return res } @@ -5790,9 +5778,7 @@ func unmarshalServiceSpecResponseBodyToControlplaneServiceSpec(v *ServiceSpecRes Port: v.Port, Cpus: v.Cpus, Memory: v.Memory, - } - if v.ConnectAs != nil { - res.ConnectAs = *v.ConnectAs + ConnectAs: *v.ConnectAs, } res.HostIds = make([]controlplane.Identifier, len(v.HostIds)) for i, val := range v.HostIds { @@ -5812,9 +5798,6 @@ func unmarshalServiceSpecResponseBodyToControlplaneServiceSpec(v *ServiceSpecRes if v.DatabaseConnection != nil { res.DatabaseConnection = unmarshalDatabaseConnectionResponseBodyToControlplaneDatabaseConnection(v.DatabaseConnection) } - if v.ConnectAs == nil { - res.ConnectAs = "" - } return res } @@ -6289,12 +6272,6 @@ func marshalControlplaneServiceSpecToServiceSpecRequestBodyRequestBody(v *contro if v.DatabaseConnection != nil { res.DatabaseConnection = marshalControlplaneDatabaseConnectionToDatabaseConnectionRequestBodyRequestBody(v.DatabaseConnection) } - { - var zero string - if res.ConnectAs == zero { - res.ConnectAs = "" - } - } return res } @@ -6769,12 +6746,6 @@ func marshalServiceSpecRequestBodyRequestBodyToControlplaneServiceSpec(v *Servic if v.DatabaseConnection != nil { res.DatabaseConnection = marshalDatabaseConnectionRequestBodyRequestBodyToControlplaneDatabaseConnection(v.DatabaseConnection) } - { - var zero string - if res.ConnectAs == zero { - res.ConnectAs = "" - } - } return res } diff --git a/api/apiv1/gen/http/control_plane/client/types.go b/api/apiv1/gen/http/control_plane/client/types.go index f58008b5..d3cae4bf 100644 --- a/api/apiv1/gen/http/control_plane/client/types.go +++ b/api/apiv1/gen/http/control_plane/client/types.go @@ -2112,7 +2112,7 @@ type ServiceSpecRequestBody struct { DatabaseConnection *DatabaseConnectionRequestBody `json:"database_connection,omitempty"` // Username of the database_users entry this service connects as. The user must // exist in database_users and have appropriate roles for the service's needs. - ConnectAs string `json:"connect_as,omitempty"` + ConnectAs string `json:"connect_as"` } // DatabaseConnectionRequestBody is used to define fields on request body types. @@ -2537,7 +2537,7 @@ type ServiceSpecResponseBody struct { DatabaseConnection *DatabaseConnectionResponseBody `json:"database_connection,omitempty"` // Username of the database_users entry this service connects as. The user must // exist in database_users and have appropriate roles for the service's needs. - ConnectAs *string `json:"connect_as,omitempty"` + ConnectAs *string `json:"connect_as"` } // DatabaseConnectionResponseBody is used to define fields on response body @@ -2890,7 +2890,7 @@ type ServiceSpecRequestBodyRequestBody struct { DatabaseConnection *DatabaseConnectionRequestBodyRequestBody `json:"database_connection,omitempty"` // Username of the database_users entry this service connects as. The user must // exist in database_users and have appropriate roles for the service's needs. - ConnectAs string `json:"connect_as,omitempty"` + ConnectAs string `json:"connect_as"` } // DatabaseConnectionRequestBodyRequestBody is used to define fields on request diff --git a/api/apiv1/gen/http/control_plane/server/encode_decode.go b/api/apiv1/gen/http/control_plane/server/encode_decode.go index 2263121a..e6b64e5b 100644 --- a/api/apiv1/gen/http/control_plane/server/encode_decode.go +++ b/api/apiv1/gen/http/control_plane/server/encode_decode.go @@ -4081,9 +4081,7 @@ func unmarshalServiceSpecRequestBodyToControlplaneServiceSpec(v *ServiceSpecRequ Port: v.Port, Cpus: v.Cpus, Memory: v.Memory, - } - if v.ConnectAs != nil { - res.ConnectAs = *v.ConnectAs + ConnectAs: *v.ConnectAs, } res.HostIds = make([]controlplane.Identifier, len(v.HostIds)) for i, val := range v.HostIds { @@ -4103,9 +4101,6 @@ func unmarshalServiceSpecRequestBodyToControlplaneServiceSpec(v *ServiceSpecRequ if v.DatabaseConnection != nil { res.DatabaseConnection = unmarshalDatabaseConnectionRequestBodyToControlplaneDatabaseConnection(v.DatabaseConnection) } - if v.ConnectAs == nil { - res.ConnectAs = "" - } return res } @@ -4712,12 +4707,6 @@ func marshalControlplaneServiceSpecToServiceSpecResponseBody(v *controlplane.Ser if v.DatabaseConnection != nil { res.DatabaseConnection = marshalControlplaneDatabaseConnectionToDatabaseConnectionResponseBody(v.DatabaseConnection) } - { - var zero string - if res.ConnectAs == zero { - res.ConnectAs = "" - } - } return res } @@ -5154,9 +5143,7 @@ func unmarshalServiceSpecRequestBodyRequestBodyToControlplaneServiceSpec(v *Serv Port: v.Port, Cpus: v.Cpus, Memory: v.Memory, - } - if v.ConnectAs != nil { - res.ConnectAs = *v.ConnectAs + ConnectAs: *v.ConnectAs, } res.HostIds = make([]controlplane.Identifier, len(v.HostIds)) for i, val := range v.HostIds { @@ -5176,9 +5163,6 @@ func unmarshalServiceSpecRequestBodyRequestBodyToControlplaneServiceSpec(v *Serv if v.DatabaseConnection != nil { res.DatabaseConnection = unmarshalDatabaseConnectionRequestBodyRequestBodyToControlplaneDatabaseConnection(v.DatabaseConnection) } - if v.ConnectAs == nil { - res.ConnectAs = "" - } return res } diff --git a/api/apiv1/gen/http/control_plane/server/types.go b/api/apiv1/gen/http/control_plane/server/types.go index c82fd5aa..e8f2d301 100644 --- a/api/apiv1/gen/http/control_plane/server/types.go +++ b/api/apiv1/gen/http/control_plane/server/types.go @@ -2196,7 +2196,7 @@ type ServiceSpecResponseBody struct { DatabaseConnection *DatabaseConnectionResponseBody `json:"database_connection,omitempty"` // Username of the database_users entry this service connects as. The user must // exist in database_users and have appropriate roles for the service's needs. - ConnectAs string `json:"connect_as,omitempty"` + ConnectAs string `json:"connect_as"` } // DatabaseConnectionResponseBody is used to define fields on response body @@ -2548,7 +2548,7 @@ type ServiceSpecRequestBody struct { DatabaseConnection *DatabaseConnectionRequestBody `json:"database_connection,omitempty"` // Username of the database_users entry this service connects as. The user must // exist in database_users and have appropriate roles for the service's needs. - ConnectAs *string `json:"connect_as,omitempty"` + ConnectAs *string `json:"connect_as"` } // DatabaseConnectionRequestBody is used to define fields on request body types. @@ -2900,7 +2900,7 @@ type ServiceSpecRequestBodyRequestBody struct { DatabaseConnection *DatabaseConnectionRequestBodyRequestBody `json:"database_connection,omitempty"` // Username of the database_users entry this service connects as. The user must // exist in database_users and have appropriate roles for the service's needs. - ConnectAs *string `json:"connect_as,omitempty"` + ConnectAs *string `json:"connect_as"` } // DatabaseConnectionRequestBodyRequestBody is used to define fields on request @@ -5825,6 +5825,9 @@ func ValidateServiceSpecRequestBody(body *ServiceSpecRequestBody) (err error) { if body.HostIds == nil { err = goa.MergeErrors(err, goa.MissingFieldError("host_ids", "body")) } + if body.ConnectAs == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("connect_as", "body")) + } if body.ServiceID != nil { if utf8.RuneCountInString(*body.ServiceID) < 1 { err = goa.MergeErrors(err, goa.InvalidLengthError("body.service_id", *body.ServiceID, utf8.RuneCountInString(*body.ServiceID), 1, true)) @@ -6603,6 +6606,9 @@ func ValidateServiceSpecRequestBodyRequestBody(body *ServiceSpecRequestBodyReque if body.HostIds == nil { err = goa.MergeErrors(err, goa.MissingFieldError("host_ids", "body")) } + if body.ConnectAs == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("connect_as", "body")) + } if body.ServiceID != nil { if utf8.RuneCountInString(*body.ServiceID) < 1 { err = goa.MergeErrors(err, goa.InvalidLengthError("body.service_id", *body.ServiceID, utf8.RuneCountInString(*body.ServiceID), 1, true)) diff --git a/api/apiv1/gen/http/openapi.json b/api/apiv1/gen/http/openapi.json index 59fe9ba8..88a303da 100644 --- a/api/apiv1/gen/http/openapi.json +++ b/api/apiv1/gen/http/openapi.json @@ -8900,7 +8900,6 @@ "connect_as": { "type": "string", "description": "Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs.", - "default": "", "example": "app" }, "cpus": { @@ -9051,7 +9050,8 @@ "service_id", "service_type", "version", - "host_ids" + "host_ids", + "connect_as" ] }, "StartInstanceResponse": { diff --git a/api/apiv1/gen/http/openapi.yaml b/api/apiv1/gen/http/openapi.yaml index 775da45d..d57c0663 100644 --- a/api/apiv1/gen/http/openapi.yaml +++ b/api/apiv1/gen/http/openapi.yaml @@ -6386,7 +6386,6 @@ definitions: connect_as: type: string description: Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs. - default: "" example: app cpus: type: string @@ -6496,6 +6495,7 @@ definitions: - service_type - version - host_ids + - connect_as StartInstanceResponse: title: StartInstanceResponse type: object diff --git a/api/apiv1/gen/http/openapi3.json b/api/apiv1/gen/http/openapi3.json index 8cefb38b..2b3240fb 100644 --- a/api/apiv1/gen/http/openapi3.json +++ b/api/apiv1/gen/http/openapi3.json @@ -25572,7 +25572,6 @@ "connect_as": { "type": "string", "description": "Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs.", - "default": "", "example": "app" }, "cpus": { @@ -25723,7 +25722,8 @@ "service_id", "service_type", "version", - "host_ids" + "host_ids", + "connect_as" ] }, "ServiceSpec2": { @@ -25742,7 +25742,6 @@ "connect_as": { "type": "string", "description": "Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs.", - "default": "", "example": "app" }, "cpus": { @@ -25892,7 +25891,8 @@ "service_id", "service_type", "version", - "host_ids" + "host_ids", + "connect_as" ] }, "ServiceSpec3": { @@ -25911,7 +25911,6 @@ "connect_as": { "type": "string", "description": "Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs.", - "default": "", "example": "app" }, "cpus": { @@ -26062,7 +26061,8 @@ "service_id", "service_type", "version", - "host_ids" + "host_ids", + "connect_as" ] }, "ServiceSpec4": { @@ -26081,7 +26081,6 @@ "connect_as": { "type": "string", "description": "Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs.", - "default": "", "example": "app" }, "cpus": { @@ -26233,7 +26232,8 @@ "service_id", "service_type", "version", - "host_ids" + "host_ids", + "connect_as" ] }, "ServiceSpec5": { @@ -26252,7 +26252,6 @@ "connect_as": { "type": "string", "description": "Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs.", - "default": "", "example": "app" }, "cpus": { @@ -26405,7 +26404,8 @@ "service_id", "service_type", "version", - "host_ids" + "host_ids", + "connect_as" ] }, "ServiceSpec6": { @@ -26424,7 +26424,6 @@ "connect_as": { "type": "string", "description": "Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs.", - "default": "", "example": "app" }, "cpus": { @@ -26577,7 +26576,8 @@ "service_id", "service_type", "version", - "host_ids" + "host_ids", + "connect_as" ] }, "ServiceSpec7": { @@ -26596,7 +26596,6 @@ "connect_as": { "type": "string", "description": "Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs.", - "default": "", "example": "app" }, "cpus": { @@ -26745,7 +26744,8 @@ "service_id", "service_type", "version", - "host_ids" + "host_ids", + "connect_as" ] }, "StartInstanceResponse": { diff --git a/api/apiv1/gen/http/openapi3.yaml b/api/apiv1/gen/http/openapi3.yaml index 8e799f54..22901fe5 100644 --- a/api/apiv1/gen/http/openapi3.yaml +++ b/api/apiv1/gen/http/openapi3.yaml @@ -18046,7 +18046,6 @@ components: connect_as: type: string description: Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs. - default: "" example: app cpus: type: string @@ -18156,6 +18155,7 @@ components: - service_type - version - host_ids + - connect_as ServiceSpec2: type: object properties: @@ -18170,7 +18170,6 @@ components: connect_as: type: string description: Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs. - default: "" example: app cpus: type: string @@ -18279,6 +18278,7 @@ components: - service_type - version - host_ids + - connect_as ServiceSpec3: type: object properties: @@ -18293,7 +18293,6 @@ components: connect_as: type: string description: Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs. - default: "" example: app cpus: type: string @@ -18403,6 +18402,7 @@ components: - service_type - version - host_ids + - connect_as ServiceSpec4: type: object properties: @@ -18417,7 +18417,6 @@ components: connect_as: type: string description: Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs. - default: "" example: app cpus: type: string @@ -18528,6 +18527,7 @@ components: - service_type - version - host_ids + - connect_as ServiceSpec5: type: object properties: @@ -18542,7 +18542,6 @@ components: connect_as: type: string description: Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs. - default: "" example: app cpus: type: string @@ -18654,6 +18653,7 @@ components: - service_type - version - host_ids + - connect_as ServiceSpec6: type: object properties: @@ -18668,7 +18668,6 @@ components: connect_as: type: string description: Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs. - default: "" example: app cpus: type: string @@ -18780,6 +18779,7 @@ components: - service_type - version - host_ids + - connect_as ServiceSpec7: type: object properties: @@ -18794,7 +18794,6 @@ components: connect_as: type: string description: Username of the database_users entry this service connects as. The user must exist in database_users and have appropriate roles for the service's needs. - default: "" example: app cpus: type: string @@ -18902,6 +18901,7 @@ components: - service_type - version - host_ids + - connect_as StartInstanceResponse: type: object properties: diff --git a/server/internal/api/apiv1/validate.go b/server/internal/api/apiv1/validate.go index 9323f039..5bbed260 100644 --- a/server/internal/api/apiv1/validate.go +++ b/server/internal/api/apiv1/validate.go @@ -361,10 +361,7 @@ func validateServiceSpec(svc *api.ServiceSpec, path []string, isUpdate bool, dbU } // Validate connect_as references a valid database_users entry. - // Required for MCP, PostgREST, and RAG — all three use connect_as credentials. - if svc.ServiceType == "mcp" || svc.ServiceType == "postgrest" || svc.ServiceType == "rag" { - errs = append(errs, validateConnectAs(svc, dbUsers, path)...) - } + errs = append(errs, validateConnectAs(svc, dbUsers, path)...) // MCP-specific cross-validation: allow_writes vs target_session_attrs if svc.ServiceType == "mcp" && svc.DatabaseConnection != nil && svc.DatabaseConnection.TargetSessionAttrs != nil {