feat(openapi): add allow option to OpenAPIReferenceHandlerPlugin - #1911
Conversation
Allows serving the docs UI and OpenAPI spec conditionally, e.g. only to authenticated users. When allow resolves to false, the request falls through as unmatched, as if the plugin were not installed. Resolves middleapi#1907
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
More templates
@orpc/ai-sdk
@orpc/arktype
@orpc/bun
@orpc/client
@orpc/cloudflare
@orpc/contract
@orpc/experimental-effect
@orpc/evlog
@orpc/hibernation
@orpc/json-schema
@orpc/experimental-msw
@orpc/nest
@orpc/next
@orpc/node
@orpc/openapi
@orpc/opentelemetry
@orpc/pinia-colada
@orpc/pino
@orpc/publisher
@orpc/ratelimit
@orpc/server
@orpc/shared
@orpc/swr
@orpc/tanstack-query
@orpc/trpc
@orpc/valibot
@orpc/zod
commit: |
There was a problem hiding this comment.
✅ No new issues found. The
allowoption is correctly scoped, well-typed, and the coverages genuinely exercise the new behavior.
Reviewed changes
allowoption onOpenAPIReferenceHandlerPlugin: Newallow: Value<Promisable<boolean>, [...]>option (defaulttrue), stored viaoptions.allow ?? true. Ininit, it's awaited only after a GET request falls through as unmatched AND its URL matchesspecPath/docsPath, and before the spec is generated — so a denied request returns the original unmatched result and never touchesspec, matching the "as if the plugin were not installed" contract.- Tests: Two new cases. The deny case loops
/and/spec.json, asserts the unmatched result is returned unchanged andspecis not called, and that the predicate receives the routing options (includingrequest.url). The allow-true case assertsallowis not invoked for unrelated paths and the spec serves with 200. - Docs: New
## Restricting Accesssection with aallowexample, heading level consistent with## Learn More.
No regressions found. The default is unchanged (allow omitted = served), the new tests fail if the gate regresses, and value()'s boolean/function handling makes the true default a no-op.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
✅ No new issues found. The refactor keeps the implemented behavior intact and tightens the deny contract.
Reviewed changes
- Dropped the stored
truedefault:this.allow = options.allow ?? true→this.allow = options.allow, and the@default trueJSDoc line was removed. Omittingallownow storesundefined. - Stricter gate:
if (!await value(this.allow, opts))→if (await value(this.allow, opts) === false). This is exactly what makes dropping the default safe:value(undefined, opts)yieldsundefined, andundefined === falseisfalse, so omittedallowstill serves. It also prevents a predicate that happens to resolve to a falsy-but-not-falsevalue (e.g. a missingreturnin an async fn) from silently denying the docs — consistent with the documented contract "when it resolves tofalse". - Tests and docs were not touched by this commit; the existing deny/allow-true/unrelated-path cases continue to cover the gate. I re-ran the plugin test file (10/10 pass) and
tsc -bfor@orpc/openapi(clean).
No regressions found. await value(...) === false parses as (await value(...)) === false, confirming the strict comparison applies to the resolved value.
DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

Adds an
allowoption toOpenAPIReferenceHandlerPluginso the docs UI and OpenAPI spec can be served conditionally, for example only to authenticated users. When it resolves tofalse, the request falls through as unmatched, as if the plugin were not installed, so unauthorized clients cannot tell the docs and spec paths exist.Resolves #1907
Design
allow: Value<Promisable<boolean>, [StandardHandlerRoutingInterceptorOptions<T>]>, defaulting totrue. It receives the same options asspec,docsTitle, anddocsHead, so decisions can use the handler context or request headers.Testing