# Reg. validation of endpoints against provided schema

**URL:** <https://softwaremill.community/t/reg-validation-of-endpoints-against-provided-schema/451>\
**Category:** tapir\
**Created:** [October 29, 2024, 8:00pm UTC](https://softwaremill.community/t/reg-validation-of-endpoints-against-provided-schema/451 "2024-10-29T20:00:57Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![hochgi](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/hochgi/32/32_2.png) [@hochgi](https://softwaremill.community/u/hochgi)\
**Post date:** [October 29, 2024, 8:00pm UTC](https://softwaremill.community/t/reg-validation-of-endpoints-against-provided-schema/451/1 "2024-10-29T20:00:57Z")

</div>

Regarding this issue:

> <https://github.com/softwaremill/tapir/issues/3645>
>
> Sometimes it might be desirable to verify if the endpoints match a given OpenAPI… schema. To implement this, we would need to parse the schema (see https://github.com/softwaremill/sttp-apispec/issues/2 - although this is already partially done), and then invoke comparison of the two schemas (generated from endpoints & parsed), ignoring fields which do not matter (e.g. descriptions, or examples)

I could really use such a “static validator”.  
Thing is, that I don’t think it’s feasible to fully validate “statically”.

By “static” I mean given 2 definitions, whether they’re in openAPI format, scala tAPIr code, or anything else, I don’t think we can always prove they’re “isomorphic”.

Same API can be described in multiple ways.  
For instance, an API that responds with a body that references a schema like:

```yaml
components:
  schemas:
    User:
      type: object
      properties:
        email:
          type: string
        name:
          type: string
      required:
        - email
        - name

```

can also be documented in a more relaxed way, e.g:

```yaml
components:
  schemas:
    User:
      type: object
      additionalProperties:
        type: string

```

The definition still holds, and correct for all possible outputs.  
In Scala, it would be equivalent to use a case class of String members: `case class User(email: String, name: String)` and replace it with a more permissive type `Map[String, String]` which would still be correct.

When you think about it, you could document every API with `Any` as return type, and it will be correct.

Other corner cases are different uses of `oneOf`, `anyOf`, `allOf`, `not`…  
is

```yaml
oneOf:
  - string
  - boolean

```

different than:

```yaml
not:
  oneOf:
    - integer
    - number
    - array
    - object

```

?

Point is, validating 2 schemas equivalency is hard.  
It’s easier to validate that a specific request/response does not violate a given contract.

When I researched this, I came across this:  
[https://bitbucket.org/atlassian/swagger-request-validator](https://bitbucket.org/atlassian/swagger-request-validator)  
(and also: [Bitbucket](https://bitbucket.org/atlassian/swagger-mock-validator) )

My goal was to use openapi contract generated from a non-scala service (python) to generate a scala client (zio).  
I ended up writing the contract manually, for exactly the same reasons mentioned above.  
The openapi contract generated from python was very general, used `allOf` to denote inheritance with fields, while I needed to be specific, and generate sealed traits with `oneOf` instead.

So now, the problem was: how do I validate that the manually written contract stays correct?

You can see why I take interest in this issue.  
Any ideas on how to make it usable when the schemas are actually different, but still describe the same requests/responses in a different way?

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [October 30, 2024, 11:32am UTC](https://softwaremill.community/t/reg-validation-of-endpoints-against-provided-schema/451/2 "2024-10-30T11:32:43Z")

</div>

You’re certainly rising valid concerns, however I think the scope of the feature would be narrower - and we’d have to properly document it. The use case that I’d like to cover is that a schema is generated for a server, published, and then we want to verify that we don’t break the existing contract. So we never had the ambition of providing a general-purpose OpenAPI equivalence verifier, which would be hard for the reasons provided (“subtyping”, coproducts etc.).

But given the narrower scope as described above (and in the issue), it’s enough to verify that the schemas are identical (not equivalent) in the “parts that matter” (e.g., descriptions do not matter).

I think your use-case is different, so probably out of the scope of this feature in particular.

---

<div class="post-metadata">

**Author:** ![hochgi](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/hochgi/32/32_2.png) [@hochgi](https://softwaremill.community/u/hochgi)\
**Post date:** [October 30, 2024, 12:45pm UTC](https://softwaremill.community/t/reg-validation-of-endpoints-against-provided-schema/451/3 "2024-10-30T12:45:25Z")

</div>

makes sense. I hoped maybe I’d be able to use it, but perhaps not.  
Do you think that an equivalency verifier for tAPIr endpoints is something that might be provided in the future?

Perhaps it would not be a “proof”, but rather a “check”, kind of like property checks tests…  
Speaking of property checks, it gives the idea of some sort of `Gen` that takes an `Endpoint`, and generate valid requests & responses, which then can be validated against a given OpenAPI spec.

I could really use such a tool to write verification tests for a client to any service exposing an OpenAPI spec.

WDYT?

---

<div class="post-metadata">

**Author:** ![adamw](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/adamw/32/28_2.png) [@adamw](https://softwaremill.community/u/adamw)\
**Post date:** [October 30, 2024, 1:07pm UTC](https://softwaremill.community/t/reg-validation-of-endpoints-against-provided-schema/451/4 "2024-10-30T13:07:40Z")

</div>

I think that we might start with an “identity” check, and then it could be expanded to be more “intelligent”, allowing for greater flexibility in verifying subtyping & coproduct rules. It’s a complex problem, as you wrote, so probably needs gradual work.

I guess having an `Endpoint` instance and generating requests & responses would be doable, but that’s another feature (though very interesting, also from a security standpoint! Maybe create an issue for it so it doesn’t get lost?). But I’d attempt at implementing it without going through the (lossy) OpenAPI format.

---

<div class="post-metadata">

**Author:** ![hochgi](https://dub1.discourse-cdn.com/flex005/user_avatar/softwaremill.community/hochgi/32/32_2.png) [@hochgi](https://softwaremill.community/u/hochgi)\
**Post date:** [October 30, 2024, 1:42pm UTC](https://softwaremill.community/t/reg-validation-of-endpoints-against-provided-schema/451/5 "2024-10-30T13:42:29Z")

</div>

done!

> <https://github.com/softwaremill/tapir/issues/4124>
>
> Following \[this conversation\](https://softwaremill.community/t/reg-validation-of…-endpoints-against-provided-schema/451):
> It would be very helpful to have a tool that can generate requests & responses from an \`Endpoint\` definition.
> 
> Motivation:
> There are many ways we can use such a tool.
> In the scenario I describe in the original conversation,
> I speak of using such ability with e.g. scalacheck's \`Gen\` to create valid requests/responses.
> Those can then be tested against a given OpenAPI schema with tools like: \[swagger-request-validator\](https://bitbucket.org/atlassian/swagger-request-validator).

I’m not sure how hard it would be to implement this, but I would definitely be happy to use such a tool!  
Thanks ❤
