fix(openapi3): don't emit auth scheme models under components.schemas#10677
Open
dschmidt wants to merge 3 commits into
Open
fix(openapi3): don't emit auth scheme models under components.schemas#10677dschmidt wants to merge 3 commits into
dschmidt wants to merge 3 commits into
Conversation
A custom auth scheme model declared inside the service namespace
(`model X { type: AuthType.http; scheme: "..."; }`) was emitted both
under `components.securitySchemes.X` (correct) and under
`components.schemas.X` (spurious). The second emit is the side effect
of `processUnreferencedSchemas`, which walks every model in the
service namespace and emits any whose visibility is "unreachable from
payloads". Custom auth models always match that criterion but are
already represented under `securitySchemes`.
The visible symptom was that any `@extension(...)` on the auth model
propagated to both emit locations. Extensions valid at
`components.securitySchemes.X` (e.g. `bearerFormat`) are unknown at
`components.schemas.X`, and downstream OpenAPI validators (such as
openapi-generator-cli) reject the document.
Filter the auth scheme models out of `processUnreferencedSchemas` so
they only land in `components.securitySchemes`.
dschmidt
added a commit
to dschmidt/libre-graph-api
that referenced
this pull request
May 13, 2026
…espace Workaround for microsoft/typespec#10677: when auth scheme models are declared inside the service namespace, the openapi3 emitter leaks them into `components.schemas` (in addition to the correct `components.securitySchemes`). Any `@extension` on the model propagates to both copies, and downstream validators (openapi-generator-cli) reject extensions like `bearerFormat: plain` at the `schemas` location. Move the three schemes (basicAuth, bearerAuth, openId) into a new `spec/auth.tsp` file that has no `namespace LibreGraph;` declaration, so they live in the global namespace and `processUnreferencedSchemas` in the openapi3 emitter doesn't visit them. With the models at global namespace the `@extension("bearerFormat", "plain")` line is back on `bearerAuth`, and the emitted YAML matches the original libre-graph-api v1 spec on that detail (`bearerFormat: plain` under `components.securitySchemes.bearerAuth`). Re-merge the auth models back into main.tsp once microsoft/typespec#10677 ships.
commit: |
Contributor
|
All changed packages have been documented.
Show changes
|
…erenced by an operation
timotheeguerin
approved these changes
May 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
A custom auth scheme model declared inside the service namespace is emitted into both
components.securitySchemes(correct) andcomponents.schemas(spurious):Emitted output today:
The spurious
components.schemas.<name>entry comes fromprocessUnreferencedSchemas, which walks every model in the service namespace and emits any model that is "unreachable" (i.e. not referenced from any payload). Custom auth scheme models always match that criterion but are already covered bycomponents.securitySchemes.Visible symptom (how I found this):
@extension(...)decorators applied to the auth model propagate to both emit locations. Extensions valid undercomponents.securitySchemes.<name>(for examplebearerFormat: plainon a bearer auth scheme) are unknown undercomponents.schemas.<name>, and downstream tools — openapi-generator-cli's spec validator in my case — reject the document:The bug only triggers when the auth model is declared inside the service namespace. Declared at global scope it doesn't reproduce, because
processUnreferencedSchemasonly walks the service namespace.Fix
Filter auth scheme model types out of
processUnreferencedSchemas.serviceAuth.schemesalready carries each scheme's originating model (HttpAuth.model) by the timeemitSchemasruns.Auth models continue to be emitted via the separate
securitySchemespath ininitializeEmitter.Test
Added a test case in
packages/openapi3/test/security.test.tsthat assertsres.components.schemas?.customBeareris undefined whileres.components.securitySchemes.customBeareris set correctly. All 60 existing security tests still pass.Backward compatibility
I think this should be safe: depending on auth scheme models to appear under
components.schemaswould be a misuse — they're not payload schemas. The change only affects the emit location, the model still parses and resolves identically inside@useAuth(...).