Skip to content

Add no-openapi-client-extensions linter rule - #5109

Merged
Mark Cowlishaw (markcowl) merged 6 commits into
Azure:mainfrom
markcowl:markcowl/no-openapi-client-extensions
Aug 8, 2026
Merged

Add no-openapi-client-extensions linter rule#5109
Mark Cowlishaw (markcowl) merged 6 commits into
Azure:mainfrom
markcowl:markcowl/no-openapi-client-extensions

Conversation

@markcowl

Copy link
Copy Markdown
Member

Summary

Adds a new typespec-azure-core linter rule, no-openapi-client-extensions, that flags use of the @typespec/openapi @extension decorator to emit client-altering x-ms-* / x-nullable OpenAPI extensions.

These extensions change how clients, SDKs, and the ARM platform interpret an API (long-running, pageable, secret, ARM resource, client name, etc.). When hand-written with the raw @extension decorator they only appear in the OpenAPI output, so every other emitter works from the semantic TypeSpec model and never sees them — producing an incorrect representation of the API. Each has a first-class TypeSpec construct that should be used instead, which the docs enumerate.

Extensions flagged: x-ms-skip-url-encoding, x-ms-enum, x-ms-parameter-grouping, x-ms-parameter-location, x-ms-client-name, x-ms-discriminator-value, x-ms-client-flatten, x-ms-parameterized-host, x-ms-pageable, x-ms-long-running-operation, x-ms-long-running-operation-options, x-nullable, x-ms-internal, x-ms-azure-resource, x-ms-arm-id-details, x-ms-secret.

Motivated by the discussion in #3066 (bar use of client-altering extensions).

Changes

  • Rule implementation, tests, and docs in packages/typespec-azure-core.
  • Registered in linter.ts and in both the data-plane and resource-manager rulesets.
  • Docs include Impact, LintDiff Equivalent (correlates to the LintDiff rules that require/validate these extensions, e.g. R2007/R2005/R2064 for LRO, R2029/R2060/R4012 for pageable, R2018/R4005 for enum, R2012/R2013 for client-name, R2001 for client-flatten, R2019/R2062 for azure-resource, XMSSecretInResponse for secret), examples, and Suppression sections.
  • Changeset (feature) for @azure-tools/typespec-azure-core and @azure-tools/typespec-azure-rulesets.

Validation

  • pnpm build, targeted rule tests (12, all passing), and rulesets validate-rules-defined tests pass.
  • pnpm format, lint, and cspell clean.
  • int:azure-specs label to be applied to run the External Integration check against all Azure specs.

@markcowl Mark Cowlishaw (markcowl) added the int:azure-specs Run integration tests against azure-rest-api-specs label Jul 30, 2026
@microsoft-github-policy-service microsoft-github-policy-service Bot added lib:azure-core Issues for @azure-tools/typespec-azure-core library meta:website TypeSpec.io updates linter Issues related to linter rules labels Jul 30, 2026
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @azure-tools/typespec-azure-core
  • @azure-tools/typespec-azure-rulesets
Show changes

@azure-tools/typespec-azure-core - feature ✏️

Add no-openapi-client-extensions linter rule that flags use of the @typespec/openapi @extension decorator to emit client-altering x-ms-*/x-nullable OpenAPI extensions (e.g. x-ms-long-running-operation, x-ms-pageable, x-ms-enum, x-ms-client-name, x-ms-secret). These extensions only affect the OpenAPI output, so other emitters produce an incorrect representation of the API; use the equivalent TypeSpec construct instead.

@azure-tools/typespec-azure-rulesets - feature ✏️

Add no-openapi-client-extensions linter rule that flags use of the @typespec/openapi @extension decorator to emit client-altering x-ms-*/x-nullable OpenAPI extensions (e.g. x-ms-long-running-operation, x-ms-pageable, x-ms-enum, x-ms-client-name, x-ms-secret). These extensions only affect the OpenAPI output, so other emitters produce an incorrect representation of the API; use the equivalent TypeSpec construct instead.

@azure-tools/typespec-azure-core - fix ✏️

The no-openapi rule no longer flags the @extension decorator. Client-altering x-ms-* extensions emitted through @extension are handled by the no-openapi-client-extensions rule instead.

@pkg-pr-new

pkg-pr-new Bot commented Jul 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@azure-tools/typespec-azure-core@5109
npm i https://pkg.pr.new/@azure-tools/typespec-azure-rulesets@5109

commit: 060ab6d

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

Adds a typespec-azure-core linter rule that flags use of the @typespec/openapi @extension decorator to emit client-altering x-ms-* / x-nullable OpenAPI extensions (e.g. x-ms-long-running-operation, x-ms-pageable, x-ms-enum, x-ms-client-name, x-ms-secret). These extensions only affect the OpenAPI output, so other emitters produce an incorrect representation of the API; the docs point to the equivalent TypeSpec construct for each. Registered in both the data-plane and resource-manager rulesets.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 53a7f4f6-90c0-4844-bb8c-e3e62837b21b
The no-openapi rule no longer reports a violation for the @typespec/openapi
@extension decorator. Client-altering x-ms-* extensions emitted through
@extension are now handled by the dedicated no-openapi-client-extensions rule,
so flagging every @extension use here is redundant and over-broad. Updates the
tests and rule docs accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 53a7f4f6-90c0-4844-bb8c-e3e62837b21b
@markcowl
Mark Cowlishaw (markcowl) force-pushed the markcowl/no-openapi-client-extensions branch from 155070d to 5631698 Compare August 7, 2026 00:43
Mark Cowlishaw (markcowl) added a commit to markcowl/azure-rest-api-specs that referenced this pull request Aug 7, 2026
The new @azure-tools/typespec-azure-core/no-openapi-client-extensions
linter rule (Azure/typespec-azure#5109) flags uses of the
@typespec/openapi @extension decorator that emit client-altering
x-ms-* / x-* extensions, because those only affect the OpenAPI output
and are ignored by client SDKs and other emitters.

This adds #suppress directives at the 150 existing decorator locations
(861 diagnostic instances across template instantiations) in 70 specs
so they continue to compile once the rule ships. Each directive is
placed on the decorated node and records that the usage predates the
rule and should migrate to the equivalent TypeSpec construct.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 53a7f4f6-90c0-4844-bb8c-e3e62837b21b
Mark Cowlishaw (markcowl) added a commit to markcowl/azure-rest-api-specs that referenced this pull request Aug 7, 2026
The new @azure-tools/typespec-azure-core/no-openapi-client-extensions
linter rule (Azure/typespec-azure#5109) flags uses of the
@typespec/openapi @extension decorator that emit client-altering
x-ms-* / x-* extensions, because those only affect the OpenAPI output
and are ignored by client SDKs and other emitters.

This adds #suppress directives at the 150 existing decorator locations
(861 diagnostic instances across template instantiations) in 70 specs
so they continue to compile once the rule ships. Each directive is
placed on the decorated node and records that the usage predates the
rule and should migrate to the equivalent TypeSpec construct.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 53a7f4f6-90c0-4844-bb8c-e3e62837b21b
@markcowl

Copy link
Copy Markdown
Member Author

PR for spec suppressions: Azure/azure-rest-api-specs#45323

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

📦 Package size report

✅ No notable package size changes compared to the base branch.

13 package(s) with no notable change
Package Packed (base → head) Δ Packed Unpacked (base → head) Δ Unpacked
@azure-tools/typespec-azure-core 129.22 KB → 129.41 KB +186 B (+0.1%) 701.72 KB → 702.62 KB +928 B (+0.1%)
@azure-tools/typespec-java 13.51 MB → 13.51 MB +21 B (+0.0%) 15.03 MB → 15.03 MB
@azure-tools/typespec-azure-rulesets 5.15 KB → 5.16 KB +10 B (+0.2%) 31.73 KB → 32.09 KB +364 B (+1.1%)
@azure-tools/azure-http-specs 146.21 KB → 146.21 KB 1.16 MB → 1.16 MB
@azure-tools/typespec-autorest 80.93 KB → 80.93 KB 395.06 KB → 395.06 KB
@azure-tools/typespec-autorest-canonical 7.42 KB → 7.42 KB 26.00 KB → 26.00 KB
@azure-tools/typespec-azure-portal-core 42.40 KB → 42.40 KB 192.87 KB → 192.87 KB
@azure-tools/typespec-azure-resource-manager 171.29 KB → 171.29 KB 1.04 MB → 1.04 MB
@azure-tools/typespec-client-generator-core 226.23 KB → 226.23 KB 1.22 MB → 1.22 MB
@azure-tools/typespec-go 244.79 KB → 244.79 KB 1.25 MB → 1.25 MB
@azure-tools/typespec-metadata 15.91 KB → 15.91 KB 62.26 KB → 62.26 KB
@azure-tools/typespec-python 46.22 KB → 46.22 KB 180.83 KB → 180.83 KB
@azure-tools/typespec-ts 524.66 KB → 524.66 KB 2.53 MB → 2.53 MB

Packed = gzipped .tgz published to npm. Unpacked = total extracted size. 🆕 added, 🗑️ removed. Packages from the core/ submodule are not included.
🔴 grew · 🟢 shrank — only changes of at least 512 B and 0.5% are marked.

@catalinaperalta catalinaperalta left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a small nit in the docs

…sions.md

Co-authored-by: catalinaperalta <9859037+catalinaperalta@users.noreply.github.com>
@markcowl
Mark Cowlishaw (markcowl) added this pull request to the merge queue Aug 8, 2026
Merged via the queue into Azure:main with commit af7cb04 Aug 8, 2026
41 of 44 checks passed
@markcowl
Mark Cowlishaw (markcowl) deleted the markcowl/no-openapi-client-extensions branch August 8, 2026 08:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

int:azure-specs Run integration tests against azure-rest-api-specs lib:azure-core Issues for @azure-tools/typespec-azure-core library linter Issues related to linter rules meta:website TypeSpec.io updates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants