microsoft/resource-designer
Research SDK contracts, design Terraform schema approach, and compose a GitHub issue for a new resource, data source, ephemeral resource, or enhancement to an existing resource. USE FOR: analyzing SDK DTOs, determining design patterns (polymorphic flattening, immutability, enum filtering), and creating well-structured GitHub issues. INVOKES: GitHub MCP tools for issue creation, sdk-contract-navigator skill for SDK analysis.
npx skills add https://github.com/microsoft/terraform-provider-fabric --skill resource-designer
Research SDK contracts, design the Terraform schema approach, and compose a GitHub issue for a new resource, data source, ephemeral resource, or enhancement to an existing resource.
#skill:sdk-contract-navigator has already been run to identify SDK availabilityIf a milestone name was provided (e.g. "2026-04"), resolve it to its numeric ID:
GET /repos/microsoft/terraform-provider-fabric/milestones?state=all&per_page=100
title matches the user's input (case-insensitive)number field from that milestone objectIf no milestone was specified, set milestone: null and proceed.
Choose the correct issue template based on what is being requested.
| Scenario | Title Prefix | Label | Template File |
| ------------------------------------------ | ------------ | ---------------- | ------------------------------------------- |
| New resource (Fabric Item or non-item) | [RS] | tf/resource | tfprovider_resource_request.yml |
| New data source | [DS] | tf/data-source | tfprovider_data_source_request.yml |
| New ephemeral resource | [EPH] | tf/ephemeral | tfprovider_ephemeral_resource_request.yml |
| Enhancement to existing resource | [FEAT] | feature | feature_request.yml |
[RS] / [DS] — A completely new Terraform resource or data source that doesn't exist yet. Applies to both Fabric Items (Lakehouse, Eventhouse, etc.) and non-item resources (Connection, Shortcut, Gateway, Workspace Role Assignment, etc.)[EPH] — A new ephemeral resource (short-lived, not stored in state)[FEAT] — Adding new attributes to an existing resource, changing behavior, adding support for a new API feature on an existing resource, or any other enhancement that modifies existing codeIf both a resource and data source are needed for the same Fabric resource, create two separate issues.
From the user's description and SDK analysis, gather:
| Detail | How to Determine |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Resource name | fabric_<snake_case> — e.g. fabric_lakehouse, fabric_connection, fabric_shortcut |
| Display name | PascalCase with spaces — e.g. "Lakehouse", "Connection", "Shortcut" |
| API doc links | Browse learn.microsoft.com/rest/api/fabric/ for API pages |
| SDK availability | Check if the SDK package/client exists (from #skill:sdk-contract-navigator) |
| Resource category | Fabric Item (~60%) or non-item (~40%) — see below |
| Item archetype | For Fabric Items only: basic, definition, properties, definition-properties, config-properties, config-definition-properties |
| Complexity | easy (basic/definition), moderate (properties/non-item), hard (config-\*/complex non-item) |
| Definition paths | For Fabric Items with definitions: fetch the definition article to list supported definition parts — see below |
| Related resources | Existing resources that interact with this one |
| Preview status | Check if the Fabric API is marked as preview |
| SPN support | Check if the API supports service principal authentication |
Fabric Items — Standard items managed in workspaces (Lakehouse, Eventhouse, SQL Database, Data Pipeline, Notebook, etc.). These use the fabricitem generic abstraction and have ItemType constants in the core SDK.
Non-item resources — Specialized resources with bespoke CRUD logic. Each belongs to an implementation pattern (A–H) that determines canonical reference, lifecycle semantics, and test structure:
| Pattern | Characteristic | SDK Client | Canonical Reference |
| :-----: | ---------------------------------------------------- | ---------------------------------- | -------------------------------------- |
| A | Workspace policy singleton (no ID, delete=reset) | fabcore.WorkspacesClient | internal/services/workspacencp/ |
| B | Workspace settings (dedicated client, validators) | fabspark.* | internal/services/sparkwssettings/ |
| C | Role assignment (parent+principal+role, ImportState) | Various *Client | internal/services/workspacera/ |
| D | Batch assignment (immutable set, no update) | fabadmin.DomainsClient | internal/services/domainra/ |
| E | Standalone entity, standard CRUD | Various dedicated clients | internal/services/workspace/ |
| E | Standalone entity, polymorphic types | fabcore.GatewaysClient | internal/services/gateway/ |
| E | Standalone entity, tenant-scoped | fabadmin.DomainsClient | internal/services/domain/ |
| E | Standalone entity, connect/disconnect lifecycle | fabcore.GitClient | internal/services/workspacegit/ |
| F | Item-scoped (workspace_id+item_id, 3+ path params) | fabcore.OneLakeShortcutsClient | internal/services/shortcut/ |
| F | Item-scoped (ModifyPlan, conditional validation) | fabcore.JobSchedulerClient | internal/services/itemjobscheduler/ |
| F | Item-scoped (simple CRUD, no Update) | fabcore.ExternalDataSharesClient | internal/services/externaldatashare/ |
| G | Tenant-level, custom identity/delete semantics | fabadmin.TenantsClient | internal/services/tenantsetting/ |
| H | Complex: dual clients, write-only secrets, KV refs | fabcore.ConnectionsClient | internal/services/connection/ |
Pattern classification decision tree:
Is it a workspace policy/settings with no real entity ID?
├── YES → Uses WorkspacesClient sub-endpoint, delete=reset? → Pattern A
│ Uses dedicated Spark/Environment client, ConfigValidators? → Pattern B
│
├── NO → Is it an assignment of principals/items to a parent?
│ ├── Single-item assignment with updatable role, ImportState? → Pattern C
│ └── Batch set assignment, fully immutable, no Import? → Pattern D
│
├── NO → Is it scoped to a specific item (workspace_id + item_id)?
│ └── YES → Pattern F
│
├── NO → Is it a tenant-level admin resource with non-UUID identity or custom delete?
│ └── YES → Pattern G
│
├── NO → Does it have write-only secrets, dual clients, KV references?
│ └── YES → Pattern H
│
└── NO → Standalone entity with dedicated client → Pattern E
When composing the issue, include the pattern letter in the "Details / References" section so downstream agents can immediately route to the correct implementation reference.
For Fabric Items that support definitions (archetypes: definition, definition-properties, config-definition-properties), fetch the item definition article to discover the supported definition parts/paths:
https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/<item-kebab-case>-definition
For example:
https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/notebook-definitionhttps://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/report-definitionhttps://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/spark-job-definition-definitionUse the fetch_webpage tool to read the article and extract the list of definition paths (e.g. notebook-content.py, definition.pbir/report.json). Each definition part has a path and format. Record all supported definition paths for inclusion in the issue.
If the article does not exist or returns a 404, the item likely does not support definitions — adjust the archetype accordingly.
Fabric REST API docs follow this pattern (never include en-us locale):
https://learn.microsoft.com/rest/api/fabric/<service>/items
For non-item resources, the API path varies:
https://learn.microsoft.com/rest/api/fabric/core/connections
https://learn.microsoft.com/rest/api/fabric/core/shortcuts
https://learn.microsoft.com/rest/api/fabric/core/gateways
https://learn.microsoft.com/rest/api/fabric/core/workspaces
After gathering SDK details (Step 3), analyze the DTOs to determine which design patterns apply to this resource. This produces the "🎨 Terraform Design Notes" section in the issue body, giving the implementor explicit guidance.
Perform each check by comparing the SDK DTOs discovered in Step 3:
| # | Check | How to Detect | Output |
| --- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| 1 | Immutable fields | Fields present in Create<Resource>Request but absent from Update<Resource>Request (or no Update method exists) | List fields → RequiresReplace |
| 2 | Computed-only fields | Fields in response DTO absent from all request DTOs | List fields → Computed: true + UseStateForUnknown |
| 3 | Polymorphic flattening | Response/request DTO has an interface type, or a struct with a Type/Kind discriminator and variant-specific fields | Describe variants → separate optional nested blocks + ExactlyOneOf |
| 4 | Write-only secrets | Request DTO has *Password/*Secret/*Token/*Key/*Credential fields absent from response DTO | List fields → WriteOnly: true + *_reference alternative |
| 5 | Conditional fields | Properties that only apply when a type discriminator has a specific value (variant-specific fields) | List field→type mappings → NullIfAttributeIsOneOf/RequireIfAttributeIsOneOf |
| 6 | Enum filtering | Possible*Values() contains values representing system-managed/read-only states that cannot be set via Create/Update | List values to exclude from OneOf validator |
| 7 | Composite ID for import | Sub-resource with 3+ path parameters (e.g., workspace_id + item_id + name) | Describe import ID format |
basic or definition with no properties), checks 3–6 typically don't apply — skip them.[FEAT]), only run checks relevant to the new fields being added.| Type | Format |
| --------------- | ------------------------------------------- |
| New resource | [RS] fabric_<snake_case_name> |
| New data source | [DS] fabric_<snake_case_name> |
| New ephemeral | [EPH] fabric_<snake_case_name> |
| Enhancement | [FEAT] <short description of enhancement> |
[RS]) and Data Sources ([DS])Use Job Story format:
When managing Microsoft Fabric infrastructure as code,
I want to create/manage <ResourceName> resources via Terraform,
so I can automate provisioning and maintain consistent <ResourceName> configurations across environments.
For Fabric Items:
> Important: Do NOT include SDK CRUD method signatures (e.g. Get, Create, Update, Delete, List, GetDefinition, UpdateDefinition) in the issue body. Fabric Items follow standardized method patterns determined by the archetype — listing them adds noise without value. Only include the SDK package, archetype, DTO fields (Properties/CreationPayload), enum types, and definition paths.
- Resource Name: `fabric_<snake_case_name>`
- API documentation:
- https://learn.microsoft.com/rest/api/fabric/<itemtype>/items/create-<item>
- https://learn.microsoft.com/rest/api/fabric/<itemtype>/items/get-<item>
- https://learn.microsoft.com/rest/api/fabric/<itemtype>/items/list-<items>
- Definition article: https://learn.microsoft.com/rest/api/fabric/articles/item-management/definitions/<item-kebab-case>-definition
- SDK Package: `github.com/microsoft/fabric-sdk-go/fabric/<package>`
- Item Archetype: `<archetype>`
- Definition Paths (if applicable):
- `<path>` (format: `<format>`)
- `<path>` (format: `<format>`)
- Estimated complexity/effort: <easy|moderate|hard>
- Preview: <yes|no>
- SPN Supported: <yes|no>
- Related resources/data-sources:
- `fabric_workspace` (required parent)
For non-item resources:
- Resource Name: `fabric_<snake_case_name>`
- API documentation:
- https://learn.microsoft.com/rest/api/fabric/core/<service>/create-<resource>
- https://learn.microsoft.com/rest/api/fabric/core/<service>/get-<resource>
- https://learn.microsoft.com/rest/api/fabric/core/<service>/list-<resources>
- SDK Client: `fabcore.<Resource>Client`
- Resource Category: non-item (bespoke CRUD)
- Implementation Pattern: <A|B|C|D|E|F|G|H> — <pattern description>
- Estimated complexity/effort: <easy|moderate|hard>
- Preview: <yes|no>
- SPN Supported: <yes|no>
- Related resources/data-sources:
- <related resources>
> Pattern key: A=Workspace policy singleton, B=Workspace settings (Spark), C=Role assignment, D=Batch assignment, E=Standalone entity, F=Item-scoped, G=Tenant-level custom, H=Connection (complex credentials)
Include this section only for [RS] and [DS] issues where the SDK DTOs have 3+ nesting levels (slices containing structs with nested slices/pointers to other structs). Skip for flat resources (Workspace, Domain, role assignments, basic Fabric Items without properties).
Render a tree showing the SDK DTO hierarchy with type annotations. This helps implementors plan model structs, set() methods, and SetNull(ctx) placement.
Format — use indented tree with type annotations at leaf/branch nodes:
<RootDTO>
├── Field1 (string)
├── Field2 (enum)
├── NestedSlice []ChildDTO ← Level 1
│ ├── ScalarField (string)
│ ├── DeepSlice []GrandchildDTO ← Level 2
│ │ ├── LeafSlice []string ← Level 3
│ │ └── LeafField (enum)
│ └── OptionalNested *AnotherDTO ← Level 2
│ └── Items []ItemDTO ← Level 3
└── OptionalTop *TopDTO ← Level 1
└── Children []ChildDTO ← Level 2
Rules:
[]Type, optional nested as *Type, scalars as (type)← Level N comments on lines introducing a new struct depth...)Include this section for all [RS] and [DS] issues. Populate from the analysis in Step 3.5. Only include applicable items — omit checks that returned no findings.
Format:
**Immutable fields** (→ `RequiresReplace`):
- `<field_name>` — only in Create request, not updatable
**Computed-only fields** (→ `Computed: true`):
- `<field_name>` — response-only, server-generated
**Polymorphic type** (→ separate optional blocks + `ExactlyOneOf`):
- SDK type `<InterfaceName>` has variants: `<Variant1>`, `<Variant2>`, ...
- Model as: `<variant_1> {}`, `<variant_2> {}` optional nested blocks
**Write-only secrets** (→ `WriteOnly: true` + `*_reference` alternative):
- `<field_name>` — credential/secret in request, absent from response
**Conditional fields** (→ `NullIfAttributeIsOneOf` / `RequireIfAttributeIsOneOf`):
- `<field_name>` only applies when `type == "<value>"`
**Enum filtering** (→ exclude from `OneOf` validator):
- `<EnumType>`: exclude `<Value1>`, `<Value2>` (system-managed/non-creatable)
**Import ID format**:
- `<workspace_id>/<item_id>/<name>` (composite)
Generate sample HCL based on SDK properties discovered and informed by the design notes above (use optional blocks for polymorphic types, add comments for immutable/computed fields):
resource "fabric_<snake_case_name>" "example" {
display_name = "example"
description = "Example resource"
workspace_id = fabric_workspace.example.id
# Item-specific attributes
}
- [ ] Can create a new <ResourceName> with required attributes
- [ ] Can read <ResourceName> by ID
- [ ] Can update <ResourceName> mutable attributes
- [ ] Can delete <ResourceName>
- [ ] Can import existing <ResourceName>
- [ ] Properties are correctly mapped from SDK response
For Resource:
- [ ] Data Transfer Objects (DTOs)
- [ ] Resource Implementation
- [ ] Resource Added to Provider
- [ ] Unit Tests for Happy path
- [ ] Unit Tests for Error path
- [ ] Acceptance Tests
- [ ] Example in the ./examples folder
- [ ] Schema documentation in code
- [ ] Updated auto-generated provider docs with `task docs`
For Data Source:
- [ ] Data Transfer Objects (DTOs)
- [ ] Data-Source Implementation
- [ ] Data-Source Added to Provider
- [ ] Unit Tests for Happy path
- [ ] Unit Tests for Error path
- [ ] Acceptance Tests
- [ ] Example in the ./examples folder
- [ ] Schema documentation in code
- [ ] Updated auto-generated provider docs with `task docs`
[FEAT])Use the feature_request.yml template structure.
Job Story format describing the enhancement:
When using the existing `fabric_<resource>` resource,
I want to <what is missing or needs to change>,
so I can <expected outcome>.
Explain why the enhancement is needed — e.g. new API capability, missing attribute, user request.
Describe workarounds or alternative approaches considered.
#skill:sdk-contract-navigator)Compare the current SDK DTOs against the existing implementation to identify what's new. Include this section in the issue body so the implementor agent has a clear change list:
For Fabric Item enhancements:
### SDK Diff
Resource: `fabric_<snake_case_name>`
Category: Fabric Item (`<archetype>`)
Service package: `internal/services/<package>/`
| Change | SDK Field | Go Type | Current Status |
| --------- | ----------------------------- | ------------------------ | --------------------------------- |
| + New | `Properties.<FieldName>` | `*string` | Not in `<item>PropertiesModel` |
| + New | `Properties.<NestedField>` | `*<NestedDTO>` | New sub-model needed |
| + New | `CreationPayload.<FieldName>` | `*bool` | Not in `<item>ConfigurationModel` |
| ~ Changed | `Properties.<FieldName>` | `*int32` (was `*string`) | Type change in model |
For non-item enhancements:
### SDK Diff
Resource: `fabric_<snake_case_name>`
Category: non-item (bespoke CRUD)
Service package: `internal/services/<package>/`
SDK Client: `fabcore.<Resource>Client`
| Change | SDK Field | Go Type | Current Status |
| ------------ | --------------------------- | --------- | --------------------------------------- |
| + New | `<ResponseDTO>.<FieldName>` | `*string` | Not in `base<Resource>Model` |
| + New | `<RequestDTO>.<FieldName>` | `*bool` | Not in `request<Action><Resource>Model` |
| + New method | `client.<NewMethod>(...)` | — | No CRUD handler |
Show HCL demonstrating the desired new behavior:
resource "fabric_<existing_resource>" "example" {
# existing attributes...
# NEW: proposed enhancement
new_attribute = "value"
}
- [ ] New attribute `<name>` is added to the schema
- [ ] SDK mapping is correct for new fields
- [ ] `set()` methods updated for new fields
- [ ] Fakes updated with new field test data
- [ ] Existing tests still pass
- [ ] New test assertions for added attributes
- [ ] Documentation updated
Use the GitHub MCP server create_issue tool:
owner: microsoft
repo: terraform-provider-fabric
title: <composed title from Step 4>
body: <composed body from Step 5>
labels: [<appropriate label>]
milestone: <resolved milestone number from Step 1, or null if not specified>
Label mapping:
[RS] → ["tf/resource"][DS] → ["tf/data-source"][EPH] → ["tf/ephemeral"][FEAT] → ["feature"]After creating the issue, report:
Take microsoft/resource-designer from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.