# Azure Resource Manager Documentation Knowledge Base

## Envelope Property Names

The current (non-deprecated) envelope property spread models are:

- `...ResourceSkuProperty` (not `ResourceSku`)
- `...EntityTagProperty` (not `EntityTag`)
- `...ResourcePlanProperty` (not `ResourcePlan`)
- `...ResourceKindProperty` (not `ResourceKind`)
- `...ManagedByProperty` (not `ManagedBy`)
- `...ManagedServiceIdentityProperty` (not `ManagedServiceIdentity`)
- `...ManagedSystemAssignedIdentityProperty` (not `ManagedSystemAssignedIdentity`)
- `...ExtendedLocationProperty`

The deprecated aliases are defined in `lib/models.tsp` with `#deprecated` markers.

## Resource Name Pattern

Always use `...ResourceNameParameter<ModelName>` in resource model definitions instead of manual `@key/@segment/@visibility/@path name` patterns. The template auto-generates camelCased key names and pluralized segment names from the model name. Custom key/segment names can be overridden via `KeyName` and `SegmentName` template parameters.

## Resource Model Naming

Do **not** add a `Resource` suffix to user-defined ARM resource models when using one of the resource templates (`TrackedResource<>`, `ProxyResource<>`, `ExtensionResource<>`). Name the model after the entity itself (e.g., `Employee`, `Job`, `EmployeeAgreement`) — not `EmployeeResource`, `JobResource`, etc. This is an anti-pattern because:

- It makes the auto-derived key and segment names (from `ResourceNameParameter<Model>`) easy to derive correctly (e.g., `Employee` → `employeeName`/`employees`). With a `Resource` suffix, the defaults become `employeeResourceName`/`employeeResources`, which forces every example to override `KeyName`/`SegmentName` unnecessarily.
- It follows the standard naming pattern used across Azure resource provider specs.

Examples and docs should consistently use the unsuffixed form:

```typespec
model Employee is TrackedResource<EmployeeProperties> {
  ...ResourceNameParameter<Employee>;
}
```

## Rule Documentation Files

Rule doc files under `website/src/content/docs/docs/libraries/azure-resource-manager/rules/` are **not** auto-generated by `pnpm regen-docs`. They are manually maintained. The `reference/linter.md` file IS auto-generated and links to these rule doc files. The rule doc frontmatter `title` should match the **markdown file name** (not the registered rule name in `src/linter.ts`), because the doc URL is derived from the file name. The "Full name" code block inside the doc still shows the fully-qualified registered rule name (which may include an `arm-` prefix).

## Reference Documentation Generation

- `pnpm regen-docs` from `packages/typespec-azure-resource-manager/` generates files into `reference/` only (data-types.md, decorators.md, interfaces.md, index.mdx, linter.md).
- Rule docs under `rules/` are NOT generated by this command.
- The package must be built before running `pnpm regen-docs`.

## Sample Paths

Canonical ARM samples are under `packages/samples/specs/resource-manager/`:

- `resource-types/tracked/` — TrackedResource
- `resource-types/proxy/` — ProxyResource child
- `resource-types/tenant/` — @tenantResource
- `resource-types/extension/` — ExtensionResource multi-scope
- `resource-types/specific-extension/` — ExternalResource targets
- `resource-types/singleton/` — @singleton
- `resource-types/virtual-resource/` — @armVirtualResource
- `resource-types/location/` — ArmLocationResource parent
- `resource-types/private-endpoints/` — PrivateEndpointConnection
- `resource-types/private-links/` — PrivateLink
- `resource-types/nsp/` — Network Security Perimeter

Old paths like `dynatrace/`, `tenantResource/`, `arm-scenarios/singleton/`, `operationsTest/` no longer exist.

## TSP Doc Comment Patterns

- `@dev` comments are intentional and must never be removed or converted to regular doc comments.
- The `@defaultResourceKeySegmentName` decorator on `ResourceNameParameter` auto-generates key and segment names.
- Ghost `@template` or `@param` tags in doc comments (referencing non-existent parameters) should be removed.
- The `nsp-operations.tsp` file has Action/ActionAsync templates that are POST operations, not GET — doc comments must reflect this.
- List operations (`ArmListBySubscription`, `ArmResourceListByParent`, `ArmResourceListAtScope`) must say "the resource being listed" — NOT "being patched" (copy-paste error from patch templates).
- `CreateOrReplace*` operations should say "createOrReplace" in their @template Response description. The deprecated `CreateOrUpdate*` ops say "createOrUpdate" (correct for them). In `legacy-types/`, operations named `CreateOrReplace*` still use "createOrUpdate" because the `@armResourceCreateOrUpdate` decorator confirms the ARM-level semantics.
- In `lib/extension/operations.tsp`, template doc comments use `Extension.Subscription`, `Extension.ManagementGroup`, `Extension.ResourceGroup` (dot-separated, not `>`).

## Build Requirements

- Node.js >= 22 is required for `pnpm install` and `pnpm build`.
- Build the ARM package with: `pnpm -r --filter "@azure-tools/typespec-azure-resource-manager..." build`
- Format with: `pnpm format`
- If the default Node.js is too old, download Node 22 manually and prepend to PATH.

## Operation Templates (Not Deprecated)

`ArmResourcePatchAsync` and `ArmResourcePatchSync` exist and are not deprecated, though they are noted as "not recommended" in resource-operations.md. `ArmCustomPatchSync` and `ArmCustomPatchAsync` are the preferred alternatives.

`TrackedResourceOperations` interface is current. `ResourceOperations` is deprecated (use `TrackedResourceOperations` instead).

## ArmTagsPatch Suppress Requirement

`ArmTagsPatchSync`, `ArmTagsPatchAsync`, `ArmResourcePatchSync`, and `ArmResourcePatchAsync` use `@patch(#{ implicitOptionality: true })` which triggers a deprecation warning. Users must add `#suppress "@typespec/http/deprecated-implicit-optionality" "Legacy"` at the usage site. This is documented in `resource-operations.md`.

## Getting-Started Guide Style

The `@service` decorator should NOT include a `version` parameter (version comes from `@versioned` when used). The guide uses `ArmCustomPatchSync` (not ArmTagsPatch) because that is the recommendation, based on the requirements of the ARM RPC (Resource Provider Contract).

## Envelope Properties Placement

All standard envelope properties (`EntityTagProperty`, `ExtendedLocationProperty`, `ManagedByProperty`, `ManagedServiceIdentityProperty`, `ResourceKindProperty`, `ResourcePlanProperty`, `ResourceSkuProperty`) must be spread on the **resource model** itself — NOT inside the properties bag model. The canonical sample `resource-common-properties/common-properties/main.tsp` demonstrates this pattern with all seven properties on the resource model.

## ResourceNameParameter NamePattern

`ResourceNameParameter` has a `NamePattern` template parameter with default value `"^[a-zA-Z0-9-]{3,24}$"`. In documentation examples, omit `NamePattern` when the value equals the default. Only show it when demonstrating a custom pattern.

## Feedback Corrections Applied

- `step03.md`: Use `...ResourceNameParameter<AddressResource, KeyName = "addressName", SegmentName = "addresses">` instead of manual `@key/@segment name` fields for child resources.
- `step04.md`: Use individual operation declarations (not `TrackedResourceOperations<User, UserProperties>`) in the interface example, with `ArmCustomPatchSync` for the update operation.
- `step05.md`: Remove `version` from `@service` decorator; use `...ResourceNameParameter<User>` instead of manual key/segment/path.
- `deprecation.tsp`: The ExtensionResourceBase deprecation message must say "Foundations.ExtensionResource" (not "ProxyResource").
- `arm-legacy-operations-discourage` rule was removed from linter registration; its rule doc file and linter.md entry should not exist.
- Knowledge base: The reason for using `ArmCustomPatchSync` in docs is "because that is the recommendation, based on the requirements of the ARM RPC" — NOT "to avoid the suppress complexity".

## Agent Base Type (Experimental)

The library provides an experimental **Agent** base type in `lib/base-types/agent.tsp` (namespaces `Azure.ResourceManager.BaseTypes` and `Azure.ResourceManager.BaseTypes.Agents`). Key facts:

- `@azureBaseType(#{ baseType, version })` (from `base-types.tsp`, `Azure.ResourceManager.BaseTypes`) marks a properties model as conforming to a base type. `BaseTypeInfo` has `baseType` and `version` fields. Applying it in a non-`Azure.ResourceManager` namespace emits the `basetypes-experimental` warning, so user specs must `#suppress "@azure-tools/typespec-azure-resource-manager/basetypes-experimental" "..."`.
- `Agent<Properties>` is a `TrackedResource` template that applies `@azureBaseType` automatically. Child templates: `AgentConversation<Properties, AgentResource>` and `AgentResponse<Properties, AgentResource>` (both `ProxyResource`, `@parentResource(AgentResource)`).
- Two deployment variants differ only by property visibility: **Appliance** (service-owned, read-only) and **Platform** (client-owned, writable; `baseTypes` always read-only). Models: `AgentDefinitionAppliance`/`AgentDefinitionPlatform<HasModelDeploymentRef, HasInstructions>` (boolean value params gate `modelDeploymentRef`/`instructions`), `AgentPropertiesAppliance`/`AgentPropertiesPlatform<AgentDefinitionType>`, `AgentToolTypeAppliance`/`AgentToolTypePlatform`. Exception: `modelDeploymentRef` is writable in both variants, so `AgentPropertiesAppliance.definition` is deliberately not marked `@visibility(Lifecycle.Read)` — a read-only container would make every nested field unsettable.
- Child property bases: `ConversationProperties`, `ResponseProperties`; mix-ins `PreviousResponseProperty`, `ResponseOutputProperty`, `ResponseInstructionsProperty`, `InputTypeProperty`.
- `@baseTypeOptional(isPresent, isAppliance)` (private decorator) controls base-type property visibility (invisible when not present; read-only when appliance). `AgentDefinitionAppliance.modelDeploymentRef` passes `isAppliance: false` on purpose so it stays writable in both deployment models.
- New linting rules (registered in `src/linter.ts`, docs already exist under `rules/`): `arm-agent-base-type-child-resources` (Agent must have both a Conversation and a Response child), `arm-agent-base-type-lifecycle-operations` (those children need full CRUD), `no-reserved-resource-property`, `arm-custom-resource-usage-discourage`, `arm-feature-file-usage-discourage`.
- Canonical sample: `packages/samples/specs/resource-manager/resource-types/agent/main.tsp`.
- How-to guide added: `website/src/content/docs/docs/howtos/ARM/agent-base-type.mdx`.
- The ARM howtos sidebar is auto-generated from the directory (`current-sidebar.ts` → `autogenerate` on `howtos`), so new how-to files need no manual sidebar registration.
- Reference docs (`reference/*.md`) for these lib additions were already regenerated in-commit; no `regen-docs` diff was needed for this batch.
