Commit 5f6f800
Add Cross-Tenant Restore (CTR) feature - API version 2026-03-31-preview (#41694)
* Copy 2026-01-01-preview output as 2026-03-01-preview
* Bump API version to 2026-03-01-preview
- Add v2026_03_01_preview version enum to main.tsp
- Add readme.md tag block for package-preview-2026-03-01-preview
- Update api-version in all example files from 2026-01-01-preview to 2026-03-01-preview
- Regenerate swagger with updated version string
* Add Cross-Tenant Restore (CTR) operations for 2026-03-01-preview
* Rename backupCrossTenantVaultMapping to backupCrossTenantVaultMappings
* Fix double-s in backupCrossTenantVaultMappingss typos
- Fix route backupCrossTenantVaultMappingsStatus -> backupCrossTenantVaultMappingStatus
- Fix type fields in examples: backupCrossTenantVaultMappingss -> backupCrossTenantVaultMappings
* Change API version from 2026-03-01-preview to 2026-03-31-preview
* Remove extendedProperties from CrossTenantVaultMapping and use armResourceIdentifier for sourceVaultId
* Add sourceTenantId to CrossTenantVaultMapping
* Format armResourceIdentifier per tsp format
* Use ResourceProvisioningState instead of inline union for provisioningState in CTR models
Replace inline 'Succeeded | Failed | Canceled' union with the built-in
Azure.ResourceManager.ResourceProvisioningState type in CrossTenantVaultMapping
and VaultCredentialCertificateProperties models. This removes 6 suppress
directives that were only needed to work around lint rules for the inline
union pattern.
* Revert to inline provisioningState union to fix ProvisioningStateMustBeReadOnly lint
ResourceProvisioningState generates a \ with sibling readOnly in the
swagger, but per JSON Schema spec sibling properties next to \ are
ignored. The ProvisioningStateMustBeReadOnly lint rule follows this strictly
and reports violations. Revert to the inline union pattern with suppress
directives which keeps readOnly directly on the property.
* Use armResourceIdentifier for resourceGuardOperationRequests in CTR models
* addressing comments
* Removing get and updating directive for suppressions
* fix: align examples and suppressions with compiled TypeSpec output
* fix typespec validation
* Fixed PR comments
* Fixing conflicts
* fix
* Rebase TSP source on upstream/main; restore 2026-01-31-preview baseline; layer 2026-03-31-preview on top
Phase 1 of CTR PR rework. The merge `4fac8dff80 Fixing conflicts` had dropped:
- The full `preview/2026-01-31-preview/` folder (109 files: bms.json + 108 examples)
- The `stable/2026-01-01/` folder (106 files) referenced by readme.md
- `examples/2026-01-01/` and `examples/2026-01-31-preview/` sibling folders (215 files
used by the typespec-autorest emitter to generate `x-ms-examples` references)
- The `v2026_01_01` and `v2026_01_31_preview` entries from the Versions enum
- The `package-2026-01-01` and `package-preview-2026-01-31-preview` readme tag blocks
- ~875 lines of upstream content from models.tsp (SourceSideScanInfo, ThreatInfo,
VMWorkloadPolicyType, AzureVmWorkloadSAPHanaScaleoutProtectableItem, full
UpdateRecoveryPointRequest schema, etc.) added in upstream PR #42398
Resync strategy: take upstream/main's TSP source verbatim for everything except
`CrossTenantVaultMappingResource.tsp`, then layer the CTR-specific additions on top.
Changes:
- main.tsp: rebased to upstream + added `import "./CrossTenantVaultMappingResource.tsp";`
and `v2026_03_31_preview` to Versions enum
- models.tsp: rebased to upstream + appended 224-line CTR slice
(CrossTenantRestoreRequest, CrossTenantVaultMapping, VaultCredential models, etc.) +
added `using Azure.Core;` so `armResourceIdentifier` resolves in CTR section
- readme.md: rebased to upstream + `package-preview-2026-03-31-preview` tag block +
6 CTR-specific suppressions (AllTrackedResourcesMustHaveDelete,
2x NestedResourcesMustHaveListOperation, 3x ResourceNameRestriction)
- back-compatible.tsp, RecoveryPointResource.tsp: rebased to upstream
- Imported folders: preview/2026-01-31-preview/, stable/2026-01-01/,
examples/2026-01-01/, examples/2026-01-31-preview/
- Regenerated bms.json files via `tsp compile`: stable/2025-02-01, stable/2025-08-01,
stable/2026-01-01, preview/2026-01-31-preview, preview/2026-03-31-preview
Verification:
- `tsp compile` passes
- All 5 emitted bms.json files match upstream/main byte-for-byte (except
preview/2026-03-31-preview/bms.json which intentionally adds CTR + restores
SQL Instance Snapshot Backup content)
- x-ms-examples counts match upstream: 81 for 2026-01-31-preview, 80 for
2026-01-01/2025-08-01/2025-02-01
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add CTR GetRecoveryPoint API (CrossTenantVaultRecoveryPoint_Get)
Mirrors BMS develop commit 92528aaa40 (PR 15500723) which added the
singular GET-by-recoveryPointId API for Cross-Tenant Restore. This was
the only swagger gap identified during the BMS-deltas audit.
- CrossTenantVaultMappingResource.tsp: add getRecoveryPointFromCrossTenantVault
operation following the same pattern as getProtectedItemFromCrossTenantVault.
Route: .../recoveryPoints/{recoveryPointId}, returns RecoveryPointResource.
- examples/2026-03-31-preview/CrossTenantVaultMappingOperations/
GetRecoveryPointFromCrossTenantVault.json: minimal IaaSVm example.
- preview/2026-03-31-preview/bms.json: regenerated; contains the new
operation at operationId CrossTenantVaultRecoveryPoint_Get.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* WIP Phase 4b spike: convert status check to ArmResourceActionSync
Spike to validate markcowls approach on one op before full rewrite. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 4b: convert CrossTenantVaultMappings interface to standard ARM templates
Drop @operationId/@extension/no-openapi suppressions on createOrUpdate and remove. Use ArmResourceActionAsync for remove. Sync example operationId fields to match emitted operationIds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* CTR: split CrossTenantOperations into 13 per-prefix interfaces; drop @operationId/@extension/no-openapi/arm-resource-operation suppressions
* CTR: wire 3 stale example operationIds after CrossTenantOperations split
* CTR: split CrossTenantVaultCredentialOperations into 3 per-prefix interfaces; drop @operationId/no-openapi/arm-resource-operation suppressions
* CTR: revert unintentional createdTime format change in CreateCrossTenantVaultMapping example
* CTR: fix source example createdTime to match committed preview output
Prior revert commit (90ecc39) only patched the emitted preview-side
example file for createdTime format; the source example was untouched
and therefore re-introduced the long-precision format on every recompile.
Fix the source so the next compile produces the canonical short form.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* CTR Phase 4c step 1: convert triggerValidateOperation to ArmResourceActionAsync template
Replaces hand-rolled @route + @armResourceOperations(#{ allowStaticRoutes: true })
on ValidateOperationFromCrossTenantVault.trigger with a standard
ArmResourceActionAsync<CrossTenantVaultMappingResource, ValidateOperationRequestResource,
ValidateOperationsResponse> template + @action(\�ackupTriggerValidateOperation\).
This is the first of two Group A conversions for Phase 4c. Eliminates one
allowStaticRoutes occurrence; emitted bms.json delta is template-emitter
artifacts only (api-version moved to first position, vaultName description
normalized, body param renamed to 'body', adds final-state-schema).
Part of work to address markcowl ARMChangesRequested review on PR #41694.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* CTR Phase 4c step 2: convert backupValidateOperation to ArmResourceActionSync template
Replaces hand-rolled @route + @armResourceOperations(#{ allowStaticRoutes: true })
on OperationFromCrossTenantVault.validate with a standard
ArmResourceActionSync<CrossTenantVaultMappingResource, ValidateOperationRequestResource,
ValidateOperationsResponse> template + @action(\�ackupValidateOperation\).
Second of two Group A conversions for Phase 4c. Eliminates one allowStaticRoutes
occurrence; emitted bms.json delta is template-emitter artifacts only.
Part of work to address markcowl ARMChangesRequested review on PR #41694.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* CTR Phase 4e: drop 3 ResourceNameRestriction suppressions for backupCrossTenantVaultMappings paths
Verified empirically with:
autorest readme.md --tag=package-preview-2026-03-31-preview \
--use=@microsoft.azure/openapi-validator@2.2.4 --azure-arm-validator
After removing all 3 suppressions, the run produced 0 ResourceNameRestriction
warnings (output identical to baseline modulo the 3 removed DeprecatedConfig
warnings for the directives themselves). The TSP-emitted swagger gives the
last name parameter (crossTenantVaultMappingName) a pattern of '.*' via
ResourceNameParameter<NamePattern='.*'>, which the rule accepts; the
suppressions' historical concern (parent vaultName inheriting empty pattern)
turned out not to actually trigger the rule for these paths.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* CTR Phase 4e: drop 2 NestedResourcesMustHaveListOperation suppressions
Empirical autorest --azure-validator (R4015) run with these directives removed produces zero NestedResourcesMustHaveListOperation errors:
- CrossTenantVaultMappingResource: the rule's getCollectionApiInfo successfully matches the list path /backupCrossTenantVaultMappings (operationId CrossTenantVaultMappings_List) to the resource. The historical justification that the rule could not match was incorrect.
- VaultCredentialCertificateResponse: not classified as a nested ARM resource by getAllNestedResources (no operations on subscription paths), so the rule never considers it. The suppression was a no-op.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* CTR Phase 4e: drop AllTrackedResourcesMustHaveDelete suppression
Empirically verified the rule does not fire on ProtectedItemResource:
allResourcesHaveDelete() picks the first apiPath per tracked resource and
checks for a DELETE there. ProtectedItemResource has DELETE on its
canonical /protectedItems/{name} path, so the rule passes regardless of
the cross-tenant read-only pass-through paths. Suppression was a no-op.
Tested via Node 18 + autorest --azure-validator (native modern ruleset).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert "CTR Phase 4e: drop AllTrackedResourcesMustHaveDelete suppression"
This reverts commit 413d67b.
* Revert "CTR Phase 4e: drop 2 NestedResourcesMustHaveListOperation suppressions"
This reverts commit 16b080a.
* Revert "CTR Phase 4e: drop 3 ResourceNameRestriction suppressions for backupCrossTenantVaultMappings paths"
This reverts commit b3fc7e5.
* CTR: fix 3 ModelValidation example errors
TriggerValidateOperation.json, ValidateOperation.json: rename inner
'parameters' key to 'body' to match the spec body parameter name
(ARM action templates emit body parameter as 'body').
RemoveCrossTenantVaultMapping.json: change response 204 to 200.
Spec defines 200 (final completion) and 202 (in progress); 204 is
not a valid response code for this LRO.
Updates source examples (examples/2026-03-31-preview/...) and the
compiled mirrors (preview/2026-03-31-preview/examples/...).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix 7 LintDiff errors on CTR PR
Phase 6 - empirical fixes:
1. ResourceNameRestriction (3): VirtualResource.tsp NamePattern '' -> '.*'
so vaultName param emits 'pattern: .*' across all api-versions.
2. PostResponseCodes (1): CrossTenantVaultMappingResource.remove now uses
ArmResourceActionNoResponseContentAsync (202-only) instead of
ArmResourceActionAsync with void body (which emitted 200+202).
Example file updated to drop empty 200 response.
3. ProvisioningStateMustBeReadOnly (3): Both CrossTenantVaultMapping.provisioningState
and VaultCredentialCertificateProperties.provisioningState now use an inline
anonymous string-literal union instead of a named/library type, so emission
is direct enum (no \) and 'readOnly: true' survives Spectral resolution.
Suppresses 3 TSP-side warnings (no-unnamed-union, arm-resource-provisioning-state
false-positive, no-closed-literal-union) with documented justifications.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* tsp format: wrap long provisioningState unions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert NamePattern; suppress RNR for 3 new CTR paths only
VirtualResource.tsp NamePattern '.*' was propagating to ALL api-versions
(stable 2025-02-01, 2025-08-01, 2026-01-01 and preview 2026-01-31-preview),
tripping openapi-diff rule 1036 ConstraintChanged on every vault path
because main has no pattern.
Reverted NamePattern to '' (the original state) so stable versions are byte-
for-byte identical to main again.
Updated 3 existing readme.md ResourceNameRestriction suppressions to point
at the actual 3 violating paths (backupCrossTenantVaultMappingStatus,
backupTriggerValidateOperation, backupValidateOperation). The previous
where-clauses targeted /backupCrossTenantVaultMappings paths which the rule
never flagged.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Switch CTR remove POST to ArmResourceActionNoContentAsync; consolidate RNR suppression to file-scope
Phase 5 lint-fix: drive LintDiff 'must fix' new-errors to zero on PR #41694.
Per CI run 25071630321 job-summary, 4 net-new errors at HEAD:
- 3x ResourceNameRestriction (vaultName) at bms.json L505/554/1676
- 1x PostResponseCodes at bms.json L1677 (removeCrossTenantVaultMapping POST)
Fix 1 - ResourceNameRestriction:
The 3 narrow path-scoped suppressions only silenced 3 of ~74 paths where
RNR fires. Top-50 trim explains why different commits surface different
3-path subsets. Replaced with one file-scoped suppression matching the
azure-rest-api-specs idiom (per automation, azurearcdata, etc.).
Fix 2 - PostResponseCodes:
ArmResourceActionNoResponseContentAsync (modern, non-deprecated) emits
202-only with location-header polling. Spectral PostResponseCodes rule
lags TypeSpec evolution and still expects legacy 202+204. Switched to
deprecated ArmResourceActionNoContentAsync template which emits the
expected 202+204+default shape. Added #suppress directives for both the
'deprecated' marker and the TSP-side arm-post-operation-response-codes
warning. Updated example to include 204 response. No breaking-change
risk - path is new in 2026-03-31-preview.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 7a: rename CrossTenantVaultMappingResource to CrossTenantVaultMapping; split properties type
Mark's review feedback: rename the resource model so the explicit KeyName decorator is no longer needed (default derivation produces 'crossTenantVaultMappingName' from the model name). Resolves the name collision by also renaming the previous properties type:
- model CrossTenantVaultMapping (properties) -> CrossTenantVaultMappingProperties
- model CrossTenantVaultMappingResource (resource) -> CrossTenantVaultMapping
- KeyName = `crossTenantVaultMappingName` line removed (auto-derived).
Resource is @added(v2026_03_31_preview) - preview-only with no published prior, so this is a schema-name-only rename in unreleased swagger. No URL / verb / operationId / wire-JSON / api-version changes. BMS DTOs are independently named in BMS source and unaffected.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 7b: Apply real pattern to crossTenantVaultMappingName; clarify RNR suppression rationale
Mark's review feedback: replace `NamePattern = `.*`` on the CrossTenantVaultMapping resource model with the actual ARM rule:
^[A-Za-z][A-Za-z0-9]{1,99}$ (2-100 chars, alphanumeric, no leading digit)
This flows through to the 4 model-derived crossTenantVaultMappingName path parameters in bms.json. The file-scoped ResourceNameRestriction suppression remains in readme.md because (a) vaultName is shared with stable api-versions and adding a pattern there would breaking-change-propagate, and (b) inline `@pattern(`.*`)` declarations on the static-routes pass-through interfaces will be removed in the planned LegacyOperations refactor (Phase 7c). Suppression reason text rewritten to make this scope explicit.
Also fixes a stale `CrossTenantVaultMappingResource` reference in the readme.md NestedResourcesMustHaveListOperation suppression (renamed in Phase 7a).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 7c.1: spike LegacyOperations on BackupProtectedItemsFromCrossTenantVault
Replace allowStaticRoutes-based interface with LegacyOperations alias.
- Pack vault+mapping path params into ParentParameters arg 1
- Use ProtectedItemResource as ResourceTypeParameter for child segment
- Preserve operationId 'BackupProtectedItemsFromCrossTenantVault_List' via
ResourceName template arg
- Add inline @pattern on crossTenantVaultMappingName to keep 7b validation
Validated: 101/101 operationId triples preserved, zero functional diff.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 7c.2: probe 5-level LegacyOperations on CrossTenantVaultRecoveryPoints
Confirms LegacyOperations pattern works for arbitrary depth (5 levels:
vault -> mapping -> fabric -> container -> protectedItem -> recoveryPoints).
Validated: 101/101 operationId triples preserved, zero functional diff.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 7c: bulk migrate cross-tenant interfaces from allowStaticRoutes to LegacyOperations
Addresses markcowl review feedback on PR #41694: replaces 14 allowStaticRoutes interfaces
in CrossTenantVaultMappingResource.tsp with thin consuming interfaces backed by
shared LegacyOperations Ops aliases.
Introduces 4 reusable parent-parameter models (CrossTenantVaultMappingParentParameters,
CrossTenantContainerParentParameters, CrossTenantProtectedItemParentParameters,
CrossTenantVaultCredentialParentParameters) so each Ops alias declares only the leaf
segment + key. Eliminates ~50 inline @path/@pattern duplications across the file.
No functional changes:
- 101 -> 101 operationIds, zero VERB+path+operationId diff vs HEAD~1
- crossTenantVaultMappingName real pattern (Phase 7b) preserved on every emitted route
- Response types preserved exactly (LRO 202, ArmAcceptedLroResponse, ArmNoContentResponse)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 7c followup: rename example body key parameters->body to match LegacyOperations ActionAsync template (fixes ModelValidation REQUIRED_PARAMETER_EXAMPLE_NOT_FOUND)
* Phase 7c followup 2: rename body key in TSP source example files (the previous fix only edited the emitted output, but TSP source is the input that gets copied during compile)
* Phase 7d: prune redundant suppressions after LegacyOperations refactor
- Remove 2x lro-location-header per-line suppressions in CrossTenantVaultMappingResource.tsp (lines 513, 704). Compile clean with --warn-as-error after removal.
- Remove AllTrackedResourcesMustHaveDelete from readme.md (templated Read<> ops via LegacyOperations no longer trip the rule on cross-tenant pass-through paths).
- Update ResourceNameRestriction reason to reflect post-7c reality (drop the ''.*'' inline-pattern source (2); refactor is now done. Suppression now only covers vaultName-inherited-from-VaultResource backcompat constraint).
* Phase 7d fixup: restore AllTrackedResourcesMustHaveDelete suppression
LintDiff blocked the removal: ProtectedItemResource''s standard path has DELETE, but the cross-tenant pass-through mirror exposes the same resource read-only. The lint rule sees the resource model (not paths) and cannot scope by route, so the suppression is required. Updated reason to clarify the cross-tenant context. Other Phase 7d removals (2 lro-location-header per-line in TSP, ResourceNameRestriction reason rewrite) remain in place — LintDiff confirmed they introduced no new violations.
* Phase 7e: add GET-by-name on CrossTenantVaultMapping to fix .NET SDK gen
Locally reproduced .NET SDK Validation crash: ArmProviderSchema.Deserialize threw KeyNotFoundException because the CTR mapping canonical path was referenced as parentResourceId by 5 cross-tenant child resources but was itself absent from the @armProviderSchema resource list. Inspection of tspCodeModel.json showed the mgmt emitter only registers a resource when it has a Read operation; CTR mapping had only createOrUpdate + list + remove (no GET-by-name).
Adding 'get is ArmResourceRead<CrossTenantVaultMapping>' registers the mapping as a top-level resource (27 entries in armProviderSchema, 0 missing parents). ARM convention also expects GET on a named resource. Pending service-side GET handler from BMS.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 7f: fix CrossTenantVaultMappings_Get example operationId typo
The TSP-level example file had operationId 'CrossTenantVaultMapping_Get' (singular)
which did not match the swagger-emitted operationId 'CrossTenantVaultMappings_Get'
(plural). This caused the autorest example pickup to skip linking it, which in turn
caused ModelValidation to fail with XMS_EXAMPLE_NOTFOUND_ERROR on the new GET-by-name
operation added in Phase 7e.
Fixed by:
- Correcting operationId in TSP-level example
- Adding provisioningState to align with model
- Re-emitting bms.json so x-ms-examples is wired and the example file is copied
into preview/2026-03-31-preview/examples/CrossTenantVaultMappingOperations/.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 7g: alias refactor for markcowl 2026-05-05 review (asks A+B+D)
- Convert 4 parameter models -> alias (Ask A): CrossTenantVaultMapping/Container/
ProtectedItem/VaultCredential ParentParameters
- Convert 11 LegacyOperations<...> interfaces -> alias (Ask B): all *Ops in CTR
- Extract StandardResourceGroupParams alias, used 11x (Ask D)
Wire contract unchanged: 0 path/operationId/response-code changes.
Generated SDK surface shrinks: param models no longer emit as named SDK types.
* Phase 7h: extract OData query parameter aliases (markcowl ask C/4)
Hand-rolled ListFilterParameter and ListSkipTokenParameter aliases replace
inline @query blocks at the 3 cross-tenant list operations
(BackupProtectedItems, RecoveryPoints, BackupJobs). Pure deduplication;
generated bms.json is byte-identical (583286 bytes, zero-line diff vs
pre-refactor snapshot).
Why hand-rolled rather than the standard ARM models:
- Azure.ResourceManager.SkipTokenParameter uses `` (lowercase t)
and is required; our wire uses `` (capital T) and optional.
Adopting the standard model would be a breaking wire change.
- Keeping a private alias preserves byte-identical wire while still giving
the reusable shape Mark asked for.
Scope is intentionally CrossTenantVaultMappingResource.tsp only. Other
RSV files in the same folder also have hand-rolled OData blocks but are
outside the scope of this PR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 8: regenerate bms.json after upstream v2026_02_01 merge
After merging upstream/main which added Versions.v2026_02_01, the @removed(Versions.v2026_02_01) markers on Threat*, SourceSideScan*, ProtectionLevel, UpdateRecoveryPointRequest, PatchRecoveryPoint*, VMWorkloadPolicyType, DatabaseInRP, InstanceProtectionReadiness, and the patch operation on RecoveryPointResource now actually take effect. These types/ops were @added in v2026_01_31_preview and removed in v2026_02_01, so they should not appear in 2026-03-31-preview (which is chronologically after 2026-02-01). The committed bms.json was stale because v2026_02_01 did not exist at the time it was generated.
* Phase 8.1: drop vmWorkloadPolicyType from SapHanaDBInstance examples
vmWorkloadPolicyType was @removed(Versions.v2026_02_01) in models.tsp, so it
no longer exists in the 2026-03-31-preview schema. Two example files
still referenced it as a property on the AzureVmWorkloadSAPHanaDBInstance
protection policy, causing ModelValidation OBJECT_ADDITIONAL_PROPERTIES
errors. Removed the property from both TSP-source examples (examples/) and
regenerated the autorest-emitted copies (preview/.../examples/) via tsp
compile. Verified locally with oav-runner examples (passes).
* Phase 9: fix .NET emitter NRE by giving CTR 202 responses a body
The .NET mgmt emitter (@azure-typespec/http-client-csharp-mgmt)'s
BuildExistsOperationPipelineProcessing assumes every status response in a
GET binds to a body, and NRE's when the 202 has none. This brought down
the .NET SDK Validation gate on PR #41694 for the three cross-tenant
operation-result GETs.
Per live1206's verified fix (PR #41694 issuecomment-4449163933), give
each 202 a body matching the 200 payload. Two of the three sites also
swap the LegacyOperations.Read<T> resource type from the response model
to the parent CrossTenantVaultMapping so the emitter's resource-type
resolution stays consistent.
Wire behavior is unchanged: BMS service controllers still emit empty
202 Accepted, and ARM LRO clients never consume the 202 body (they
poll until 200). The spec is intentionally over-describing the 202 to
unblock the .NET generator.
Sites changed (all in CrossTenantVaultMappingResource.tsp):
- ProtectedItemOperationResultsFromCrossTenantVault (L342)
- ValidateOperationResultFromCrossTenantVault (L479)
- CrossTenantVaultCredentialOperationResults (L656)
Each site carries an inline #suppress for no-response-body (and, on
site 3, arm-resource-operation-response) with justification text
referencing the PR comment.
Regenerated bms.json shows exactly 3 hunks; operationId count
(101) and 202 block count (35) are unchanged.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 9.1: literal live1206 fix for .NET emitter NRE + ModelValidation
Reverts ArmAcceptedLroResponse to literal AcceptedResponse to match
live1206's exact diff in PR #41694 issuecomment-4449163933:
Response = ArmResponse<X> | { ...AcceptedResponse; @Body body: X; }
Also adds the missing 202 body to the 3 CTR operation-result example
files so Swagger ModelValidation stops emitting
RESPONSE_BODY_NOT_IN_EXAMPLE.
Local repro: .NET emitter still NREs at line ~330 of
ResourceOperationMethodProvider.BuildExistsOperationPipelineProcessing
on this shape across emitter versions 20260512.4, 20260513.2, and
20260514.4 (latest). Pushing to surface CI's verdict against the
exact prescribed shape, in case live1206's local test used a different
baseline.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 9.2: restore Location + Retry-After headers on CTR 202 responses
After Phase 9.1 (live1206's literal fix replacing ArmAcceptedLroResponse
with AcceptedResponse + @Body) made .NET ModelValidation green, LintDiff
went red with 3 new `LroLocationHeader` errors because the inline
`...AcceptedResponse; @Body body: T` shape carries no headers, so the
emitted 202 responses dropped the Location header.
Fix: add `@header("Location") location?: string;` and
`@header("Retry-After") retryAfter?: int32;` to each of the 3 inline 202
response models in CrossTenantVaultMappingResource.tsp (ProtectedItem,
ValidateOperation, VaultCredential operation-result GETs). This:
* eliminates the 3 LroLocationHeader errors (the actual LintDiff blocker)
* preserves the AcceptedResponse + @Body shape that fixed the .NET emitter
* restores byte-equivalent header blocks in bms.json, eliminating the
~99 line-shift-correlation warnings LintDiff reported as 'new'
* keeps wire behavior unchanged (BMS service may or may not emit these
headers - they are optional in spec)
Refs: PR #41694 issuecomment-4449163933.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Retrigger CI: validate JS SDK after upstream warp fix
* Add 2026-03-31-preview API version for RecoveryServices
Pure version bump from 2026-02-01 — no schema or behavior changes. Aligns
the RSV control-plane preview with the RecoveryServicesBackup CTR work in
preview 2026-03-31-preview.
Changes:
- Add v2026_03_31_preview entry to the Versions enum in main.tsp
- Copy examples from 2026-02-01 to preview/2026-03-31-preview/examples
- Bump embedded api-version strings in the copied examples
- Generate preview/2026-03-31-preview/openapi.json via tsp compile
- Add package-preview-2026-03-31-preview tag block to readme.md
(default tag unchanged — stable 2026-02-01)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add 2026-03-31-preview API version for SiteRecovery
Pure version bump from 2026-02-01 — no schema or behavior changes. Aligns
ASR with the recoveryservicesbackup CTR work in preview 2026-03-31-preview.
Note: this introduces the first preview/ subtree under
recoveryservicessiterecovery/.../SiteRecovery/. Prior versions are all
stable-only.
Changes:
- Add v2026_03_31_preview entry to the Versions enum in main.tsp
- Copy examples from 2026-02-01 to preview/2026-03-31-preview/examples
- Bump embedded api-version strings in the copied examples
- Generate preview/2026-03-31-preview/service.json via tsp compile
- Add package-preview-2026-03-31-preview tag block to readme.md
(default tag unchanged — stable 2026-02-01)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Phase 11: Address markcowl review nit on @query parameter property names
Per markcowl review on PR #41694 (discussion threads r3236748641 +
r3236749402), rename TSP property identifiers in the
ListFilterParameter / ListSkipTokenParameter aliases so SDK clients
get usable parameter names (ilter, skipToken) instead of the
raw $filter / $skipToken identifiers, which are not legal in some
target languages (e.g., C#) and get emitter-mangled.
The @query("$filter") decorator argument continues to control the
on-the-wire name, so the URL contract is unchanged. Recompiled bms.json
adds x-ms-client-name: filter / x-ms-client-name: skipToken to the
three affected list operations; no parameter
ame/in change, no
breaking change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Re-trigger CI (diagnostic for Swagger ApiDocPreview)
No content changes. Empty commit to determine whether the apidrop Docs build failure on e1e9c9f is deterministic vs flaky.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* CTR: refactor provisioningState to named union; drop suppressions
Wrap ResourceProvisioningState in a named CrossTenantProvisioningState union (with @Azure.Core.lroStatus and extensible string member) per the azurefleet pattern, replacing the prior inline-literal union that required three suppressions (no-unnamed-union, arm-resource-provisioning-state, no-closed-literal-union) on each property.
Applied to CrossTenantVaultMappingProperties.provisioningState and VaultCredentialCertificateProperties.provisioningState. tsp compile --warn-as-error clean; emitted swagger has readOnly:true preserved next to the new schema's $ref (Spectral does not strip siblings off this named-schema reference shape).
Addresses PR #41694 mentat9 review threads L8796 and L8982.
* CTR: tighten string types to uuid/url for AAD identity fields (mentat9 review)
* Revert "CTR: tighten string types to uuid/url for AAD identity fields (mentat9 review)"
This reverts commit 9c579d0.
* Revert "CTR: refactor provisioningState to named union; drop suppressions"
This reverts commit 2f9ab1b.
* Regenerate SiteRecovery preview/2026-03-31-preview/service.json for microsoft -> Microsoft casing
After merging upstream/main (ed16268 renamed microsoft to Microsoft in SiteRecovery TSP source and stable service.jsons), regenerate our preview service.json so it picks up the correct casing in the replicationEligibilityResults paths. Resolves TypeSpec Validation + Breaking Change(Cross-Version) failures that started 5/18 when upstream merged the fix but our preview was still on the old lowercase casing.
No wire change: this only restores casing consistency with stable. CTR feature surface untouched.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* CTR: refactor provisioningState to named union; drop suppressions
Wrap ResourceProvisioningState in a named CrossTenantProvisioningState union (with @Azure.Core.lroStatus and extensible string member) per the azurefleet pattern, replacing the prior inline-literal union that required three suppressions (no-unnamed-union, arm-resource-provisioning-state, no-closed-literal-union) on each property.
Applied to CrossTenantVaultMappingProperties.provisioningState and VaultCredentialCertificateProperties.provisioningState. tsp compile --warn-as-error clean; emitted swagger has readOnly:true preserved next to the new schema's $ref (Spectral does not strip siblings off this named-schema reference shape).
Addresses PR #41694 mentat9 review threads L8796 and L8982.
* CTR: suppress ProvisioningStateMustBeReadOnly on net-new bms.json refs
OpenAPI 2.0 JSON Reference resolution drops siblings of $ref, so the
emitter-written readOnly:true next to the CrossTenantProvisioningState
named-union ref is invisible to the LintDiff rule. azurefleet emits the
identical shape and passes only via baseline grandfathering. Adding a
single suppressions.yaml entry scoped to the 2026-03-31-preview bms.json
file covers all 5 hits (L590/L651/L657 on CrossTenantVaultMapping and
L1920/L1926 on VaultCredentialCertificateResponse).
* Revert "CTR: suppress ProvisioningStateMustBeReadOnly on net-new bms.json refs"
This reverts commit cf964f4.
* CTR: suppress ProvisioningStateMustBeReadOnly via readme.md suppressions block
Add Spectral LintDiff suppression for ProvisioningStateMustBeReadOnly on
bms.json. The previous attempt via suppressions.yaml (commit cf964f4,
reverted in b250e0e) was silently ignored - that file is only wired
for TypeSpecRequirement-tool entries, not arbitrary Spectral rules.
The autorest readme.md suppressions: block is the correct channel for
Spectral rule suppression - confirmed by 15 RPs that suppress this exact
rule (playwrighttesting, newrelic, eventhub, cdn, eventgrid, ...). RSB's
readme.md already uses this mechanism for ProvisioningStateSpecifiedForLROPut
(added during earlier CTR work); this commit adds a sibling entry.
Root cause: the Phase 12.1 named-union refactor (a4491b0) made the
emitter output \ + sibling readOnly:true for provisioningState. Per
OpenAPI 2.0 / JSON Reference semantics, anything next to \ is stripped
at resolution, so Spectral cannot observe the readOnly. Identical shape
exists in azurefleet.json (FleetProperties.provisioningState) without
suppression - LintDiff is diff-only and that resource is baseline-
grandfathered. Net-new resources introduced by this PR
(CrossTenantVaultMapping, VaultCredentialCertificateResponse) trip the
rule from scratch (5 errors at bms.json L590/L651/L657/L1920/L1926).
* Revert "CTR: suppress ProvisioningStateMustBeReadOnly via readme.md suppressions block"
This reverts commit 4260210.
* CTR: re-add ProvisioningStateMustBeReadOnly suppression with strengthened reason
Restores the suppression block reverted in 049e7b4. Path 2 (suppression-free
fix) was investigated exhaustively before falling back:
* Confirmed the rule source (provisioning-state-must-be-read-only.ts) only
accepts literal readOnly===true on the resolved property -- no x-ms-mutability
/ @extension escape hatch; decorators alone don't inject readOnly into the
union definition.
* Identified the emitter-level fix: `use-read-only-status-schema: true` in
tspconfig.yaml. Verified locally that it produces 0 rule fires. However it
re-emits all stable bms.json files (adds readOnly inside 4 pre-existing
LRO-status unions per file). Out of scope for a preview-only PR; will be
adopted when a stable api-version is next regenerated.
* Per-version emitter overrides, @added-gated emission, @extension(readOnly),
x-ms-mutability, and nested-tspconfig sub-projects all evaluated and
rejected (see context/SwaggerCTR/files/no-suppression-experiment-plan.md).
Precedent: 15+ RPs suppress this exact rule (playwrighttesting, newrelic,
eventhub, cdn, eventgrid, ...). RSB readme.md already uses this mechanism for
ProvisioningStateSpecifiedForLROPut.
Reason text in readme.md updated with the rule-source citation and the
emitter-option finding so reviewers don't need to re-derive the analysis.
* CTR: tighten string types to uuid/url for AAD identity fields (mentat9 review)
* CTR: suppress GuidUsage on net-new uuid-typed CTR properties
GUIDs are used for sourceTenantId, aadTenantId, servicePrincipalClientId,
and servicePrincipalObjectId under Cross Tenant Restore properties.
Suppression added upon feedback from ARM reviewer (mentat9, PR #41694).
Also trims the ProvisioningStateMustBeReadOnly reason of a sentence
that referenced the global emitter-option follow-up.
* CTR: convert authType to extensible union per mentat9 review
Replaces `authType?: string` with an extensible `AuthType` union
(modelAsString=true) so future auth modes can be added by IDM without
breaking older SDKs. Wire format unchanged: still a string with the
single known value `AzureActiveDirectory`.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Cross-tenant operationResults GETs: model the actual wire shape (200+body, 202 headers, 204)
The three cross-tenant operationResults GETs were previously modelled with
a 202 that carried a body (a workaround for a .NET emitter NRE in the
Phase 9 workstream). That misrepresents the wire: BMS emits an empty 202
with Location/Retry-After while polling, and a 200+body (or 204) on
completion.
This change makes the spec describe the real shape:
- 200 OK with the final body when the operation has completed
- 202 Accepted with Location + Retry-After headers (no body) while polling
- 204 No Content when there is no body to return
Same fix mirrors the structure of the non-CTR equivalents
(ProtectedItemOperationResults, ValidateOperationResults) and matches the
bare-route scratch branch (users/zubair/ctr-lro-bare-route).
Suppressions cleanup: dropped the three no-response-body suppressions
(no longer triggered now that 202 has no body); kept the
arm-resource-operation-response suppression on CrossTenantVaultCredentialOperationResults.
Examples + generated bms.json updated to match.
* ctr opResults: drop 204 from spec + examples (RPC-Get-V1-01)
Lintdiff RPC-Get-V1-01 (GetResponseCodes) whitelists only {200, default, optional 202} for GET. 204 was triggering 3 errors on the CTR operationResults GETs.
Validate and VaultCredential service paths never emit 204 (verified in BL); ProtectedItem can emit 204 forwarded from source vault but losing the spec annotation matches what the grandfathered non-CTR ProtectedItemOperationResults_Get effectively models for new APIs. Wire remains HTTP-valid; clients treat 204 as terminal completion.
* rsb: carry 2026-01-31-preview-only features into 2026-03-31-preview
Per Azure preview-continuity policy (a preview = last preview union last stable, plus its own changes), re-add the 30 features that were @added(v2026_01_31_preview)+@removed(v2026_02_01) — i.e. dropped by the 2026-02-01 stable — into 2026-03-31-preview via @added(v2026_03_31_preview), while keeping them out of both stables via @removed(v2026_05_01).
Restores 78 schema elements: 16 models/unions/enums (threat/source-side-scan, SQL/SAP workload, recovery-point patch), 1 op (RecoveryPoints_Update), and 13 fields/enum-values on surviving models (e.g. ProtectedItem.sourceSideScanInfo, RecoveryPoint.threatInfo/threatStatus, ContainerType.HanaScaleoutContainer).
Verified: preview/2026-03-31-preview now fully contains 2026-01-31-preview (A\\C=0) and 2026-02-01 (B\\C=0); additions over last preview are CTR-only; 2026-02-01, 2026-05-01 and 2026-01-31-preview bms.json all byte-unchanged. tsp 1.13.0 compile clean.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: iwrinshow <36922102+iwrinshow@users.noreply.github.com>
Co-authored-by: Piyush Kumar <pikumar@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Zubair Abid <zubair@microsoft.com>
Co-authored-by: Zubair Abid <zubairabid@microsoft.com>
Co-authored-by: Mike Harder <mharder@microsoft.com>1 parent a469e9f commit 5f6f800
658 files changed
Lines changed: 92359 additions & 0 deletions
File tree
- specification
- recoveryservicesbackup/resource-manager/Microsoft.RecoveryServices/RecoveryServicesBackup
- examples/2026-03-31-preview
- AzureIaasVm
- V2Policy
- AzureStorage
- AzureWorkload
- BackupDataMove
- Common
- CrossTenantVaultMappingOperations
- Dpm
- PrivateEndpointConnection
- ResourceGuardProxyCRUD
- TieringCost
- preview/2026-03-31-preview
- examples
- AzureIaasVm
- V2Policy
- AzureStorage
- AzureWorkload
- BackupDataMove
- Common
- CrossTenantVaultMappingOperations
- Dpm
- PrivateEndpointConnection
- ResourceGuardProxyCRUD
- TieringCost
- recoveryservicessiterecovery/resource-manager/Microsoft.RecoveryServices/SiteRecovery
- examples/2026-03-31-preview
- preview/2026-03-31-preview
- examples
- recoveryservices/resource-manager/Microsoft.RecoveryServices/RecoveryServices
- examples/2026-03-31-preview
- preview/2026-03-31-preview
- examples
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 47 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
Lines changed: 21 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
Lines changed: 23 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
Lines changed: 14 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
Lines changed: 20 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
Lines changed: 24 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
Lines changed: 22 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
Lines changed: 37 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
Lines changed: 38 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
Lines changed: 94 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
0 commit comments