Repository navigation
[Swagger Linter Migration] ExtensionResourcePathPattern -> use-scope-for-extension-routing - #5684
Yuchao Yan (msyyc) wants to merge 14 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
All changed packages have been documented.
Show changes
|
📦 Package size report✅ No notable package size changes compared to the base branch. 14 package(s) with no notable change
Packed = gzipped |
commit: |
There was a problem hiding this comment.
🟡 Changes recommended
The rule documentation must use the repository-required canonical R4038 LintDiff link.
1 open finding
What changed in this PR
Adds an opt-in ARM linter rule enforcing scope-based RPaaS extension routing while preserving ordinary ARM behavior.
Changes:
- Implements and registers the rule, disabled by default.
- Adds comprehensive rule and enablement tests.
- Adds documentation, ruleset registration, and Chronus entries.
| File | Description |
|---|---|
packages/typespec-azure-resource-manager/src/rules/use-scope-for-extension-routing.ts |
Implements the rule. |
packages/typespec-azure-resource-manager/test/rules/use-scope-for-extension-routing.test.ts |
Tests behavior and opt-in enablement. |
packages/typespec-azure-resource-manager/src/rules/use-scope-for-extension-routing.md |
Documents usage and migration provenance. |
packages/typespec-azure-resource-manager/src/linter.ts |
Registers the disabled-by-default rule. |
packages/typespec-azure-resource-manager/README.md |
Lists the new rule. |
packages/typespec-azure-rulesets/src/rulesets/resource-manager.ts |
Explicitly disables it in the general ruleset. |
packages/typespec-azure-rulesets/test/validate-rules-defined.test.ts |
Verifies opt-in status. |
website/src/content/docs/docs/libraries/azure-resource-manager/reference/linter.md |
Updates generated reference documentation. |
website/src/content/docs/docs/howtos/ARM/arm-rules.md |
Adds the ARM rule matrix entry. |
.chronus/changes/arm-use-scope-for-extension-routing-2026-10-13.md |
Records the ARM package feature. |
.chronus/changes/arm-use-scope-for-extension-routing-ruleset-2026-10-13.md |
Records ruleset registration. |
🧠 Review effort: Balanced
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
You can try these changes here
|
|
Copilot-generated review feedback. Could we reconcile the inline templated-interface guard with the existing ARM The existing helper checks the operation's declaration node as well as whether its interface is an uninstantiated template; this PR checks the interface directly. Other migration rules import the helper, while #5526 duplicates it locally. This should not be a blind substitution: first establish which concrete/inherited/template operations this rule must check and whether the node-kind distinction matters, then reuse or improve the shared helper accordingly. Avoid adding a universal operation-skip wrapper that conflates template declarations, template instances, service membership, and project-location filtering. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Follow-up to this review feedback. Reused the existing package-private Implemented in 5e30d542b. Scoped formatting, type-aware lint, package build and the focused native tests passed. Review threads are intentionally left open. |
## Summary Make subsequent RPaaS migrations smoother without broadening RPaaS restrictions to ordinary ARM or weakening validation/recovery gates. This is a standalone, skill-only follow-up to the first `ExtensionResourcePathPattern` migration in #5682 and promotion in #5684. ## Process findings and changes | Observed evidence | Skill correction | | --- | --- | | Intake initially stopped because no automatic native RPaaS selector was established. The accepted continuation used existing explicit lint enablement, default-disabled, with ordinary ARM counterexamples. Upstream RPaaS registration had been flattened to catalog `common`/`Both`. | Establish upstream audience separately from catalog eligibility. Consider supported native selection, an independently justified broader guideline, or documented external opt-in before classifying. Record mixed-audience limitations; preserve genuine uncertainty stops. | | The full generic corpus selected 468 projects, compiled 462, and left six failures. Target `0/0` reflected a default-disabled rule and ordinary ARM selection, not RPaaS parity. | Carry actual validator/native activation profiles into migration notes, promotion, and both reviews. Require enabled focused evidence and appropriate activation integration controls; retain required representative/full regression runs and disclose audience, version, diagnostic-unit, and source-identity limits. | | Development review reproduced two warnings for one authored operation-template endpoint, including a template companion. Four focused regressions corrected the diagnostic unit. | Check rule-owned HTTP/template traversal and exact endpoint counts/targets before expensive corpus runs, while retaining the exclusion of framework-only tests. | | Promotion documentation regeneration exited successfully but did not load the authored rule Markdown until supported compiler `docs`/`fileRef` metadata was added. | Verify authored-file binding and generated rationale/examples, not merely a successful regeneration or index entry. | | A quiet successful lint command produced no `Tee-Object` receipt file. Guessed config paths and a stale readiness budget mirror also caused avoidable handoff failures. | Capture empty raw output independently, derive paths from the actual checkout, and acknowledge authoritative later scoped grants without inventing stale-mirror prerequisites. Preserve exit statuses, counters, fingerprints, and failed evidence. | The reusable audience contract lives in rule intake; development, queue handoffs, and promotion link to it rather than duplicating a new RPaaS detector. Promotion also checks library/default/recommended/`all` activation, including automatic `all` behavior, and preserves every existing rule's enablement. ## Evidence and boundaries - The reviewed source's [migration evidence](https://github.com/Azure/typespec-azure/blob/99d04f1c7311c5919993dfbb0b0a8d8168d9ce70/packages/typespec-lintdiff/test/fixtures/ExtensionResourcePathPattern/migration.md) documents the native opt-in contract, ordinary ARM scope distinction, template regression, corpus limitations, and intentional diagnostic-unit/version differences. - The original stop, accepted continuation, failed-command receipts, scoped grants, and handoffs remain in the coordinating session's durable process records. Those operational artifacts are not committed. - Existing capabilities/reviewer ownership, immutable-source review, finite recovery authorization, and `no-valid-comments` termination already cover the runtime/review portions of the run and remain unchanged. The earlier optional `.git` repository-identity clarification remains separate in #5685. - No rule/package files, completed migration commits, later promotion changes, catalog schema, new worker flags, production audience detectors, dependencies, release entries, or generated outputs are changed. This PR does not claim production RPaaS corpus parity or re-review subsequent rule-PR heads. ## Validation - Reviewed the complete six-file Markdown diff against fetched canonical `feature/lintdiff-migration-new` base `527a585925e61bd782e61cce9127e235e555ea91`, including linked native-test responsibility and recovery/ownership contracts. - Ran Prettier write/check on only the six explicit changed files using already-prepared repository tooling; all passed. - Verified 76 relative Markdown file references and all new audience-contract anchors. - `git diff --check` passed. - No dependency installation, submodule setup, package/corpus builds/tests, repository-wide formatting, or recursive review loop was needed for this documentation-only update. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Evidence During the ExtensionResourcePathPattern queue, a publication preflight rejected the verified canonical remote https://github.com/Azure/typespec-azure solely because it lacked a .git suffix (command103). GitHub repository identity and push permission were already established, the reviewed content was unchanged, and no publication operation had been attempted. Independent read-only reconciliation confirmed the existing binding and permitted the next authorized action. ## Change Clarify the shared publication preflight: the optional .git suffix does not change the resolved owner/repository. Preserve actual effective push URL/refspec recording, canonical GitHub metadata and permission checks, phase ownership, and all duplicate-safe recovery rules. This does not authorize retries or weaken any content, review, validation, or publication gate. ## Scope and validation One skill-documentation file only, on a dedicated branch based on the freshly fetched canonical feature/lintdiff-migration-new ref. Explicit-file Prettier and git diff --check passed. The initial fresh-worktree formatter could not load the absent core plugin; the existing prepared promotion formatter/config was used instead, with no dependency installation or submodule setup. No rule/package/corpus changes or generated artifacts. Primary PRs #5682 and #5684 are untouched. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Simplify distinct path diagnostics and remove runtime enablement repetition while retaining opt-in registration in the configuration suite. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the custom all override, cover inherited enablement and explicit disablement, and align routing guidance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Preserve extension-routing policy coverage alongside current main rule registrations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
State RPaaS applicability directly and remove project-level enable/disable recipes from authoring guidance. Preserve current rule registration pending a managed applicability decision. Retain main and migration rule registrations in merge resolutions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Review fixes and current-main integration (2026-10-20)
Published fixes: afe5f3c
and d50459d.
Merged Azure main
2cd8ba15594de155ae4c79719d7e796577ccdcd7normally and resolvedthe registration/reference conflicts, preserving main's new rules and this rule.
Removed the enable/disable tutorial, introductory disable recommendation and
project-wide suppression workaround, including matching ARM guide/release-note
recommendations. Applicability is now handled through supported rule selection:
ARM library
allenables all other registered rules but not this RPaaS-only policy;the central Azure resource-manager ruleset also leaves it disabled. Explicit RPaaS
selection remains functional. No deployment detector, new identifier, source-rule
repair, diagnostic or semantic-listener change was introduced. Existing feature
release notes and the manual matrix describe the final opt-in policy.
Fresh validation at this head: ARM dependency-closure build/production typecheck;
538 ARM tests in 74 files; 7 Azure ruleset tests; root
pnpm formatthenpnpm lint; ARM documentation regeneration; Chronus status and diff checks.The new applicability regression failed before the fix (unintended target warning
under ARM
all) and passes afterward, with explicit selection still producingexactly one target warning and every other registered rule remaining enabled.
Actual published examples were executed once using the document's standard ARM
imports/usings: one expected warning at the incorrect operation versus zero
diagnostics for the correct example. This is a one-time receipt, not continuous
Markdown coverage or standalone-program evidence. Documentation regeneration
retains existing unrelated missing-documentation warnings.
Final-head CI is tracked separately; these local results do not claim CI approval.
Original Swagger linter
The original
R4038rule is an RPaaS-routing policy, not a restriction on all ARM extension-resource endpoints:OpenApiTypes.rpaas(RPaaSViolation), rather than inferring the service's deployment audience from its paths.$.paths./providers/segment.The check does not need provider-namespace metadata, schema/reference inspection, or a per-verb predicate. The retained catalog's
Bothclassification reflects legacy common-rule extraction, not the native policy's intended audience. Supported ordinary ARM specific-parent extension endpoints are not defects merely because they contain two provider segments.Source TypeSpec lintdiff rule
This promotes
ExtensionResourcePathPattern/tsp-lintdiff-local-linter/extension-resource-path-pattern, with canonical validator slugextension-resource-path-pattern.Azure/typespec-azure,lintdiff-extension-resource-path-pattern.99d04f1c7311c5919993dfbb0b0a8d8168d9ce70.C:\dev\worktrees\lintdiff-extension-resource-path-pattern; clean, without uncommitted rule changes.The source is assumed done for this promotion after its clean development review. It was not modified during promotion. Independent local promotion review verified non-trivia-token equality for the operation listener, helper, diagnostic message, and severity.
Destination analysis
The agent-selected destination is
@azure-tools/typespec-azure-resource-manager, under the official nameuse-scope-for-extension-routing. The policy governs ARM extension templates used for RPaaS routing, including the contrast betweenExtension.Read<Extension.ExternalResource<...>, Resource>andExtension.Read<Extension.ScopeParameter, Resource>.Azure Core is a plausible alternative based solely on the compiler/HTTP imports, but this is not a shared REST or data-plane requirement. TCGC is not appropriate: the check concerns the authoring contract's path, not SDK naming or SDK-specific metadata. Production imports remain compiler and HTTP only, with no emitter, OpenAPI, TCGC, generated-reference inference, or unsafe mutation.
Promoted native behavior and enablement
The rule visits concrete semantic operations, resolves their paths through
getHttpOperation, and warns when the path contains more than one literal/providers/segment. It reports one warning on each offending operation, even for three segments; separate verbs on the same path can therefore produce separate warnings.The reviewed source's template guards are preserved: uninstantiated operation templates and operations in declaration-only generic interfaces are skipped, while concrete instantiated or inherited endpoints remain checked. It checks the supplied program, not a latest-version projection or reconstructed historical Swagger.
This RPaaS-specific rule is opt-in. The ARM library's custom
allruleset enables every other registered rule and leavesuse-scope-for-extension-routingdisabled. Managed RPaaS configurations can select it explicitly; the separate general Azureresource-managerruleset also leaves it disabled.The routing policy applies to RPaaS extension-routing contracts, not ordinary ARM endpoints. Applicability is handled by rule selection rather than by an unsupported deployment detector or project-disable recipe. Ordinary ARM contracts retain supported specific-parent routes without enabling this policy. This is a destination enablement adaptation; the immutable source listener, literal path predicate, severity and diagnostic target are unchanged.
Promotion adaptations are the official name/export/description, native compiler
fileRefdocumentation metadata and documentation URL, official registration, and native tests/docs. The semantic listener/helper, warning severity, diagnostic message, and operation targeting are unchanged. The new authored documentation includes actual ARM-template incorrect/correct examples, Impact, Suppression, and dedicated LintDiff provenance; official references were regenerated and the manual ARM matrix updated. Generated ignored website rule pages are not force-added.Fixture-to-native test mapping
No validator or lintdiff snapshots were copied into the official package.
it("targets a hardcoded-parent operation without provider-namespace metadata")it("accepts an arbitrary scope with one provider segment")it("warns for the standard specific-parent ARM extension template")it("accepts the standard arbitrary-scope ARM extension template")it("reports only the instantiated endpoint from a generic interface")it("still reports an instantiated operation template endpoint")it("reports three provider segments only once")it("reports separate operations sharing one HTTP path")it("matches literal lowercase provider segments, not lookalikes")it("reports each distinct hardcoded-parent path")it("keeps only RPaaS-specific routing outside the general ARM all ruleset")it.each([false, true])("selects RPaaS routing explicitly rather than through ARM all: %s")allalone and exactly one when the rule is explicitly selected.it("keeps RPaaS extension-routing guidance opt-in in the general Azure rulesets")An additional native case covers routes without provider segments. Lintdiff-specific comparison-config infrastructure is not ported: it configures the migration harness rather than implementing the official rule.
Migration evidence and limits
See the source migration.md for the native contract, focused fixtures, selected populations, real-service observations, compile failures, and uncertainty.
The retained source corpus attempted 468 projects: 462 succeeded and 6 failed, with 59,809 all-rule diagnostics. The target rule has 0 validator / 0 native findings in the ordinary-ARM, generic-all-disabled context. This is not RPaaS corpus parity. Historical unchanged-failed-set evidence is not a fresh pre-edit A/B comparison. The installed validator engine
2.2.6and metadata checkout6243cb01do not establish identical research-source identity for the historical1198225...links, whose commit was not available in the local shared checkout.Per-authored-operation diagnostics and supplied-program version coverage intentionally differ from Swagger's per-emitted-path/latest-selected-version population. The corpus is observational source evidence, not proof of universal functional equivalence or a fresh promotion experiment.
Validation
Historical generated-all experiment (superseded)
The following records an earlier design, not the final policy. The current opt-in correction and fresh validation are recorded at the top of this description.
alloverride without changing the rule listener, diagnostic, or severity.allenablement and explicit project disablement.all.pnpm formatandpnpm lintpassed; unrelated formatter-only changes were excluded.Historical promotion validation
The following records the earlier promotion run, not a fresh rerun or a claim about the current test layout:
featureand disabled-registration rulesetsinternalChronus entries were validated with LF line endings andchronus status.git diff --checkpassed.Repository-wide
validate:prand website build were predeclared unwarranted for this scoped promotion and were not run; CI owns the authoritative website build. No required check remains failed or incomplete.Promotion sync policy
The clean-reviewed development head remains the source of semantic truth. A source-semantic defect discovered in promotion review blocks this PR and returns evidence to the owning queue for an authorized bounded development repair. Promotion resumes from a new immutable source pin only after clean source review; it does not repair source semantics solely in the official copy.
Review follow-up (2026-10-16)
Removed the compiler-owned project-disable test only. Retained rule registration, actual generated-
allactivation, concrete endpoint coverage, the separate disabled central-ruleset policy, and opt-out docs. Current focused rule/registration suites: 13 passed. Repository format/lint and diff check passed. Earlier suite counts below describe historical revisions.Current-main compatibility (2026-10-16, 111999c)
Merged main
88d691bb5normally in111999c35. The ruleset-test resolution retains both the central-ruleset opt-in assertions and main's redundant-summary assertion; rule IDs and enablement are unchanged.After merging: dependency-closure build, 13 focused ARM tests and 7 ruleset tests, repository format/lint and uncached formatting checks passed. Dependency-closure build passed; a separate full test-project tsc was not run. Fresh required CI checks at this head are pending; the historical checks above do not establish current-head readiness.