Environment Lifecycle Management - Labs
Status: January 2026 - FSI-AgentGov v1.2.12 Estimated Time: 4-6 hours total
Overview
These hands-on labs guide you through implementing Environment Lifecycle Management from scratch. Complete them in order, as each lab builds on the previous.
| Lab | Title | Time | Prerequisites |
|---|---|---|---|
| 1 | Dataverse Schema | 60 min | Power Platform environment |
| 2 | Copilot Intake Agent | 90 min | Lab 1 complete |
| 3 | Provisioning Flow | 90 min | Lab 1 & 2 complete, Service Principal |
| 4 | End-to-End Test | 60 min | Labs 1-3 complete |
License Prerequisites
Before starting, ensure you have the required licenses:
| License | Required For | Notes |
|---|---|---|
| Power Apps Premium or Power Apps per app | Dataverse tables, Model-driven app | Per user or per app licensing |
| Copilot Studio | Lab 2 - Intake Agent | Included in some M365 plans or standalone |
| Power Automate Premium | Lab 3 - HTTP actions, custom connectors | Required for HTTP with Entra ID preauthorized |
| Azure subscription | Key Vault for secrets | For secure credential storage |
Trial Licenses
Trial licenses can be used for labs but may have limitations. For production deployment, ensure proper licensing is in place.
Lab 1: Dataverse Schema
Objective
Deploy the EnvironmentRequest and ProvisioningLog tables with security roles.
Prerequisites
- Power Platform environment with Dataverse
- System Administrator or System Customizer role
- Access to make.powerapps.com
- Python 3.10+ (for automated deployment option)
Option A: Automated Deployment (Recommended for Lab/Dev)
Use the Python deployment scripts from FSI-AgentGov-Solutions for quick setup:
# Clone the solutions repository
git clone https://github.com/judeper/FSI-AgentGov-Solutions.git
cd FSI-AgentGov-Solutions/environment-lifecycle-management/scripts
# Install dependencies
pip install -r requirements.txt
# Dry run first to preview changes
python deploy.py \
--environment-url https://<your-org>.crm.dynamics.com \
--tenant-id <your-tenant-id> \
--interactive \
--dry-run
# Full deployment
python deploy.py \
--environment-url https://<your-org>.crm.dynamics.com \
--tenant-id <your-tenant-id> \
--interactive
This creates:
- 8 global option sets (State, Zone, Region, etc.)
- EnvironmentRequest table (22 columns, user-owned, auditing enabled)
- ProvisioningLog table (11 columns, org-owned, auditing enabled)
- 4 security roles (Requester, Approver, Admin, Auditor)
- 3 business rules (conditional required fields)
- 8 model-driven app views
- Field security profile for approvers
After automated deployment, skip to Verification below, then continue to Lab 2.
Production Deployment
For production environments, use the manual process below to ensure full audit trail of who created each component.
Option B: Manual Deployment (Production)
Follow the steps below for manual deployment with full audit trail.
Step 1.1: Create EnvironmentRequest Table
- Navigate to make.powerapps.com > Tables
- Select New table > New table
- Configure:
- Display name: Environment Request
- Plural name: Environment Requests
-
Schema name prefix: Uses your publisher prefix (e.g.,
fsi_) -
Configure the Primary Column (Request Number):
- After creating the table, select the primary column (Name)
- Change Data type to Autonumber
- Configure Autonumber settings:
- Format:
REQ-{SEQNUM:5}(produces REQ-00001, REQ-00002, etc.) - Seed value: 1
- Format:
- Click Done
Autonumber Format
The format {SEQNUM:5} creates a 5-digit sequential number with leading zeros. This ensures consistent sorting and prevents duplicate numbers.
- Create columns per Architecture:
Choice Field Integer Values
When creating Choice columns, you must specify both the label and integer value. See Architecture - Choice Field Value Definitions for the complete list of integer values for each Choice field.
| Column | Type | Required | Notes |
|---|---|---|---|
| Environment Name | Single line text (100) | Yes | |
| Environment Type | Choice | Yes | Sandbox (1), Production (2), Developer (3) |
| Region | Choice | Yes | United States, Europe, United Kingdom, Australia |
| Zone | Choice | Yes | Zone 1, Zone 2, Zone 3 |
| Zone Rationale | Multiple lines text | No | Business rule: required for Zone 2/3 |
| Zone Auto Flags | Single line text (500) | No | |
| Business Justification | Multiple lines text | Yes | |
| Data Sensitivity | Choice | Yes | Public, Internal, Confidential, Restricted |
| Expected Users | Choice | Yes | Just me (1), Small team (2-10), Large team (11-50), Department (50+) |
| Security Group ID | Single line text (100) | No | |
| Requester | Lookup (User) | Auto | |
| Requested On | Date and time | Auto | |
| State | Choice | Yes | Draft, Submitted, PendingApproval, Approved, Rejected, Provisioning, Completed, Failed |
| Approver | Lookup (User) | No | |
| Approved On | Date and time | No | |
| Approval Comments | Multiple lines text | No | |
| Environment ID | Single line text (100) | No | |
| Environment URL | URL | No | |
| Provisioning Started | Date and time | No | |
| Provisioning Completed | Date and time | No |
- Save the table
Step 1.2: Create ProvisioningLog Table
- Select New table > New table
- Configure:
- Display name: Provisioning Log
- Plural name: Provisioning Logs
- Schema name prefix:
pl_ -
Table ownership: Organization
-
Create columns:
| Column | Type | Required | Notes |
|---|---|---|---|
| Environment Request | Lookup (Environment Request) | Yes | Cascade: Restrict delete |
| Sequence | Whole number | Yes | |
| Action | Choice | Yes | See architecture for values |
| Action Details | Multiple lines text | No | JSON format |
| Actor | Single line text (200) | Yes | |
| Actor Type | Choice | Yes | User, ServicePrincipal, System |
| Timestamp | Date and time | Auto | Default: Now |
| Success | Yes/No | Yes | Default: Yes |
| Error Message | Multiple lines text | No | |
| Correlation ID | Single line text (100) | No |
- Save the table
Step 1.3: Configure Table Relationships
- Open ProvisioningLog table > Relationships
- Verify lookup to EnvironmentRequest:
- Type: Many-to-one
- Related table: Environment Request
- Delete behavior: Restrict
Step 1.4: Create Security Roles
- Navigate to Settings (gear icon) > Advanced settings
- Select Settings > Security > Security roles
- Select New to create each role
Security Role Privilege Matrix
Configure each role with the following privileges. The depth levels are:
- None = No access
- User = Own records only
- Business Unit = Records in user's business unit
- Parent: Child BU = User's BU and child BUs
- Organization = All records
ELM Requester
| Table | Create | Read | Write | Delete | Append | AppendTo |
|---|---|---|---|---|---|---|
| Environment Request | User | User | User | None | User | User |
| Provisioning Log | None | User | None | None | None | None |
ELM Approver
| Table | Create | Read | Write | Delete | Append | AppendTo |
|---|---|---|---|---|---|---|
| Environment Request | None | Business Unit | Business Unit | None | None | None |
| Provisioning Log | None | Business Unit | None | None | None | None |
Field-Level Security
Approvers can only write to er_state, er_approver, er_approvedon, and er_approvalcomments fields. Configure field-level security profiles to restrict other fields.
ELM Admin
| Table | Create | Read | Write | Delete | Append | AppendTo |
|---|---|---|---|---|---|---|
| Environment Request | Organization | Organization | Organization | None | Organization | Organization |
| Provisioning Log | Organization | Organization | None | None | Organization | Organization |
ProvisioningLog Immutability
The ELM Admin role has no Write or Delete privileges on ProvisioningLog. This enforces immutability. Only Create and Read are granted.
ELM Auditor
| Table | Create | Read | Write | Delete | Append | AppendTo |
|---|---|---|---|---|---|---|
| Environment Request | None | Organization | None | None | None | None |
| Provisioning Log | None | Organization | None | None | None | None |
- Save each role after configuration
Step 1.5: Configure Business Rules
- Navigate to make.powerapps.com > Tables
- Select the Environment Request table
- In the table designer, select Business rules from the left menu (under Customizations)
- Select + New business rule
Create Rule: Zone Rationale Required
- Rule name: Zone Rationale Required
- In the rule designer:
- Add Condition:
- Field: Zone
- Operator: Equals
- Value: Zone 2
- Select + Or to add another condition:
- Field: Zone
- Operator: Equals
- Value: Zone 3
- Add Action (on the true branch):
- Action: Set Business Required
- Field: Zone Rationale
- Status: Business Required
- Select Save
- Select Activate
Create Rule: Security Group Required
- Select + New business rule
- Rule name: Security Group Required
- Follow the same pattern:
- Condition: Zone equals Zone 2 OR Zone equals Zone 3
- Action: Set Security Group ID as Business Required
- Save and Activate
Business Rule Scope
By default, business rules apply to all forms. If you need different behavior on different forms, change the Scope in the rule properties.
Verification
- EnvironmentRequest table has all 22 columns
- ProvisioningLog table has all 11 columns
- Relationship cascade is set to Restrict
- 4 security roles exist with correct permissions
- Business rules are active
Lab 2: Copilot Intake Agent
Objective
Build the conversational intake agent that collects environment requests.
Prerequisites
- Lab 1 complete (Dataverse tables exist)
- Copilot Studio license
- Access to copilotstudio.microsoft.com
Step 2.1: Create New Agent
- Navigate to copilotstudio.microsoft.com
- In the top-right corner, verify your environment matches Lab 1 (click the environment name to switch if needed)
- From the left navigation, select Copilots
- Select + New copilot > New copilot
- In the creation wizard:
- Name: Environment Request Agent
- Description: Collects and processes Power Platform environment provisioning requests
- Language: English (United States)
- Solution: (Optional) Select a solution if using ALM
- Select Create
- Wait for the agent to be created (this may take 1-2 minutes)
Step 2.2: Configure Authentication
- Navigate to Settings > Security
- Authentication: Authenticate with Microsoft
- Require users to sign in: Yes
- Scope: User.Read
Step 2.3: Create Request Environment Topic
- Navigate to Topics > New topic > From blank
- Name: Request New Environment
- Add Trigger phrases:
- I need a new environment
- Create an environment
- Request environment
- New Power Platform environment
-
Provision environment
-
Build conversation flow:
[Trigger] → [Message: "I'll help you request a new Power Platform environment."]
→ [Question: environmentName]
→ [Question: environmentType]
→ [Question: region]
→ [Question: businessPurpose]
→ [Question: expectedUsers]
→ [Question: dataSensitivity]
→ [Question: hasCustomerData]
→ [Question: hasFinancialData]
→ [Question: hasExternalAccess]
→ [Action: Zone Classification]
→ [Condition: Zone >= 2]
→ [Question: securityGroupName]
→ [Condition: Zone == 3]
→ [Question: zoneRationale]
→ [Message: Summary]
→ [Question: Confirm]
→ [Action: Call Power Automate]
→ [Message: Confirmation]
Step 2.4: Configure Questions
For each question node, configure the entity type and prompt. In Copilot Studio:
- Select the Question node
- In the properties pane, set Identify to the appropriate entity type
- Configure the prompt message
environmentName:
- Entity: User's entire response
- Prompt: "What would you like to name this environment? Use format: DEPT-Purpose-TYPE (e.g., FIN-Reporting-PROD)"
- Save response as:
Topic.environmentName
After this question, add a Condition node to validate the format:
- Add Condition node
- Set condition:
IsMatch(Topic.environmentName, "^[A-Z]{2,4}-[A-Za-z0-9]+-[A-Z]+$") - If false: Add message "Invalid format. Please use DEPT-Purpose-TYPE format." and redirect back to question
environmentType:
- Entity: Choice
- Options: Define three options: Sandbox, Production, Developer
- Prompt: "What type of environment do you need?"
- Save response as:
Topic.environmentType
expectedUsers:
- Entity: Choice
- Options: Just me (1), Small team (2-10), Large team (11-50), Department (50+)
- Prompt: "How many users will use this environment?"
- Save response as:
Topic.expectedUsers
dataSensitivity:
- Entity: Choice
- Options: Public, Internal, Confidential, Restricted
- Prompt: "What's the highest data sensitivity level for data in this environment?"
- Save response as:
Topic.dataSensitivity
hasCustomerData, hasFinancialData, hasExternalAccess:
- Entity: Confirmation (not Boolean)
- Prompts: As defined in implementation-copilot-intake.md
- Save response as:
Topic.hasCustomerData, etc.
Confirmation Entity
The Confirmation entity type presents Yes/No options to the user and returns a boolean value. Do not use "Boolean" as an entity type - it doesn't exist in Copilot Studio.
Step 2.5: Implement Zone Classification
- Add Set variable action after collecting all inputs
- Create variable
classifiedZonewith Power Fx:
If(
Topic.dataSensitivity = "Restricted" ||
Topic.hasCustomerData = true ||
Topic.hasFinancialData = true ||
Topic.hasExternalAccess = true,
3,
If(
Topic.dataSensitivity = "Confidential" ||
Topic.environmentType = "Production" ||
Topic.expectedUsers <> "Just me (1)",
2,
1
)
)
- Create variable
zoneFlagsto capture triggers:
Concat(
If(Topic.dataSensitivity = "Restricted", "RESTRICTED_DATA;", ""),
If(Topic.hasCustomerData, "CUSTOMER_PII;", ""),
If(Topic.hasFinancialData, "FINANCIAL_TRANSACTIONS;", ""),
If(Topic.hasExternalAccess, "EXTERNAL_ACCESS;", "")
)
Step 2.6: Create Summary Message
Add Message node with Adaptive Card:
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"text": "Environment Request Summary",
"weight": "Bolder",
"size": "Large"
},
{
"type": "FactSet",
"facts": [
{ "title": "Name", "value": "${Topic.environmentName}" },
{ "title": "Type", "value": "${Topic.environmentType}" },
{ "title": "Region", "value": "${Topic.region}" },
{ "title": "Zone", "value": "Zone ${Topic.classifiedZone}" },
{ "title": "Triggers", "value": "${Topic.zoneFlags}" }
]
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.3"
}
Step 2.7: Connect to Power Automate
- After the confirmation question, add a Call an action node
- In the action panel, select Power Automate
- Select Create a flow to build a new flow, or Add existing flow if you've already created the intake flow from Lab 3
- If creating a new flow:
- The flow will open in Power Automate with a "Run a flow from Copilot" trigger
- Add input parameters for each topic variable (environmentName, environmentType, region, zone, etc.)
- Add flow actions to create the Dataverse record (see Lab 3)
- Add an output parameter for the request number
- Save and return to Copilot Studio
- Map topic variables to flow inputs:
Topic.environmentName→environmentNameTopic.environmentType→environmentTypeTopic.region→regionTopic.classifiedZone→zoneTopic.zoneFlags→zoneFlagsTopic.dataSensitivity→dataSensitivityTopic.hasCustomerData→hasCustomerDataTopic.hasFinancialData→hasFinancialDataTopic.hasExternalAccess→hasExternalAccessTopic.businessPurpose→businessPurposeTopic.expectedUsers→expectedUsersTopic.securityGroupName→securityGroupName(if Zone 2/3)Topic.zoneRationale→zoneRationale(if Zone 3)- After the action, add a Message node to display the returned request number
Verification
- Agent responds to trigger phrases
- All questions collect valid input
- Zone classification works correctly for various scenarios
- Summary displays accurate information
- Authentication requires sign-in
Test Scenarios:
| Scenario | Expected Zone | Triggers |
|---|---|---|
| Internal docs, no customer data | Zone 1 | None |
| Confidential, team use | Zone 2 | CONFIDENTIAL_DATA |
| Customer data, Production | Zone 3 | CUSTOMER_PII, PRODUCTION_WORKLOAD |
Lab 3: Provisioning Flow
Objective
Build the Power Automate flow that provisions environments using Service Principal.
Prerequisites
- Labs 1 & 2 complete
- Service Principal configured per architecture.md
- Power Platform for Admins V2 connector available
Step 3.1: Create Service Principal Connection
- Navigate to make.powerautomate.com > Connections
- New connection > Power Platform for Admins V2
- Select Service Principal authentication
- Enter:
- Tenant ID
- Client ID (from app registration)
- Client Secret (from Key Vault - consider using Azure Key Vault connector)
Step 3.2: Create Main Provisioning Flow
- Create > Automated cloud flow
- Name: ELM - Main Provisioning
- Trigger: When a row is added, modified or deleted (Dataverse)
- Table: Environment Requests
- Scope: Organization
- Change type: Modified
-
Select columns: State
-
Add Condition: State equals Approved
Step 3.3: Add Logging Action
- Add Add a new row (Dataverse)
- Table: Provisioning Logs
- Map fields:
- Environment Request:
triggerBody()?['er_requestid'] - Sequence: 1
- Action: ProvisioningStarted
- Actor Type: ServicePrincipal
- Success: Yes
Step 3.4: Create Environment
- Add Create Environment (V2) action
- Map inputs from trigger:
- Location:
triggerBody()?['er_region'] - Display Name:
triggerBody()?['er_environmentname'] - Environment Type:
triggerBody()?['er_environmenttype']
Security Group Binding
The Power Platform for Admins V2 connector does not support SecurityGroupId at environment creation time. After the environment is created and the polling loop confirms success (Step 3.5), add an Update Environment action or BAP API call to bind the security group using triggerBody()?['er_securitygroupid']. The security group GUID should be the Entra ID Object ID of the target security group.
Step 3.5: Implement Polling Loop
- Add Initialize variable:
pollCount(Integer, 0) - Add Do until:
- Condition:
pollCount>= 120 OR provisioningState = Succeeded - Limit count: 120
-
Timeout: PT60M
-
Inside loop:
- Delay: 30 seconds
- Get Environment (V2)
- Increment variable: pollCount
- Condition: Check for Failed state → Terminate
Step 3.6: Enable Managed Environment
- Add HTTP with Microsoft Entra ID (preauthorized)
- Configure per implementation-provisioning.md
Step 3.7: Assign to Environment Group
- Add HTTP action for group assignment
- Implement retry policy: 3 attempts, exponential backoff
- Use Compose to select group based on zone:
@{if(equals(triggerBody()?['er_zone'], 1), 'FSI-Personal-Dev',
if(equals(triggerBody()?['er_zone'], 2), 'FSI-Team-Collaboration',
'FSI-Enterprise-Production'))}
Step 3.8: Add Error Handling
- Wrap Create Environment in Scope
- Add parallel Scope with
runAfter: Failed - In error scope:
- Log failure to ProvisioningLog
- Update EnvironmentRequest state to Failed
- Terminate with Failed status
Step 3.9: Complete Provisioning
- Add Update row (Dataverse) for EnvironmentRequest:
- State: Completed
- Environment ID: from Create Environment output
- Environment URL: from Create Environment output
-
Provisioning Completed:
utcNow() -
Add final Add a new row for ProvisioningLog:
- Action: ProvisioningCompleted
- Success: Yes
Verification
- Flow triggers on Approved state
- Service Principal connection works
- Polling loop respects timeout
- Error handling catches failures
- Completion updates all fields
Lab 4: End-to-End Test
Objective
Verify the complete solution works from request to provisioned environment.
Prerequisites
- Labs 1-3 complete
- Test user account with ELM Requester role
- Approver account with ELM Approver role
Step 4.1: Prepare Test Data
Create Environment Groups (if not already existing)
Environment Groups must exist before environments can be assigned. Create these in Power Platform admin center:
- Navigate to Power Platform admin center (admin.powerplatform.microsoft.com)
- Select Environment groups from the left navigation
- Select + New group and create each group:
| Group Name | Description | DLP Policies |
|---|---|---|
FSI-Personal-Dev |
Personal productivity environments | Standard DLP |
FSI-Team-Collaboration |
Team collaboration environments | Enhanced DLP |
FSI-Enterprise-Production |
Enterprise managed environments | Restrictive DLP |
- For each group, configure:
- Rules: Add DLP policies appropriate to the zone
- Managed environment settings: Configure sharing limits per zone
Environment Groups Prerequisite
Environment Groups are a prerequisite for ELM. If your organization hasn't configured them yet, refer to Control 2.2 - Environment Groups for full configuration guidance.
Create Test Security Group in Entra ID
- Navigate to Microsoft Entra admin center > Groups > All groups
- Select New group
- Configure:
- Group type: Security
- Group name: Test-ELM-Lab4-Users
- Group description: Test security group for ELM Lab 4
- Membership type: Assigned
- Click Create
- Copy the Object ID - you'll need this for the test
Step 4.2: Test Zone 1 Request
- As Requester: Open Copilot Studio agent
- Say: "I need a new environment"
- Provide responses:
- Name: TEST-Lab4Zone1-DEV
- Type: Developer
- Region: United States
- Purpose: Testing Environment Lifecycle Management
- Users: Individual developer
- Sensitivity: Internal
- Customer data: No
- Financial data: No
-
External access: No
-
Verify:
- Agent classifies as Zone 1
- No security group required
-
Request created in Dataverse with State = Submitted
-
As Approver: Approve the request
- Verify:
- Provisioning flow triggers
- Environment created
- ProvisioningLog has entries
Step 4.3: Test Zone 3 Request
- As Requester: Start new conversation
- Provide responses:
- Name: TEST-Lab4Zone3-PROD
- Type: Production
- Region: United States
- Purpose: Customer data processing for regulatory compliance
- Users: Compliance team, 10 users
- Sensitivity: Confidential
- Customer data: Yes
- Financial data: Yes
-
External access: No
-
Verify:
- Agent classifies as Zone 3
- Zone flags: CUSTOMER_PII, FINANCIAL_TRANSACTIONS
- Requires security group
-
Requires zone rationale — a free-text justification for why this workload requires enterprise-managed governance (e.g., "Environment will process quarterly financial reports containing customer account data")
-
Complete remaining prompts
- As Approver: Approve with Compliance review
- Verify environment configuration:
- Managed Environment: Enabled
- Environment Group: FSI-Enterprise-Production
- Audit retention: 2557 days (7 years)
- Session timeout: 120 minutes
Step 4.4: Test Error Handling
- Create a request with invalid security group ID
- Verify:
- Provisioning flow detects error
- ProvisioningLog records failure
- EnvironmentRequest state = Failed
- Admin notification sent
Step 4.5: Verify Audit Trail
- Navigate to Model-Driven App
- Open a completed request
- View ProvisioningLog subgrid
- Verify entries:
- ProvisioningStarted
- EnvironmentCreated
- ManagedEnabled
- GroupAssigned
- AuditingConfigured
- SessionTimeoutConfigured
- SharingLimitsConfigured
- ProvisioningCompleted
Step 4.6: Clean Up
- Delete test environments:
# First, get the environment IDs (the -EnvironmentName parameter requires the GUID, not display name)
Get-AdminPowerAppEnvironment | Where-Object { $_.DisplayName -like "TEST-Lab4*" } | Select-Object DisplayName, EnvironmentName
# Delete using the environment GUID
Remove-AdminPowerAppEnvironment -EnvironmentName "<environment-guid-from-above>"
!!! warning "Parameter Clarification"
The -EnvironmentName parameter expects the environment's GUID (e.g., 12345678-1234-1234-1234-123456789012), not the display name. Use Get-AdminPowerAppEnvironment to find the GUID first.
- Delete test requests from Dataverse (or mark as test data)
Final Checklist
- Zone 1 request flows end-to-end
- Zone 3 request flows with enhanced approval
- Error handling works correctly
- Audit trail is complete and immutable
- Notifications sent to requester
Troubleshooting
Common Issues
| Issue | Error Message | Cause | Resolution |
|---|---|---|---|
| Agent doesn't trigger flow | "Unable to connect to flow" or no response after confirmation | Missing or broken Power Automate connection | 1. In Copilot Studio, go to Settings > Extensions > Power Automate. 2. Verify the flow connection is active. 3. Re-authenticate if prompted. |
| Environment creation fails | "code": "UnauthorizedAccess", "message": "The caller does not have permission" |
Service Principal not registered as Management Application | 1. Go to PPAC > Settings > Admin settings. 2. Add the Service Principal under Service principal. 3. Wait 5 minutes for propagation. |
| Environment creation fails | "code": "InvalidRequest", "message": "Location is not valid" |
Region value doesn't match Power Platform region codes | Use exact region values: unitedstates, europe, unitedkingdom, australia (lowercase, no spaces). Important: Dataverse stores region as Choice integers (1=United States, 2=Europe, 3=United Kingdom, 4=Australia). The provisioning flow must map these integers to API strings using the expression documented in implementation-provisioning.md. |
| Group assignment fails | "code": "ResourceNotFound", "message": "Environment group not found" |
Environment Group doesn't exist or wrong Group ID | 1. Verify group exists in PPAC > Environment groups. 2. Use the group's GUID, not display name, in API calls. |
| Security group binding fails | "code": "ObjectNotFound", "message": "The specified security group was not found" |
Security Group ID is incorrect or doesn't exist | 1. Verify group exists in Entra ID. 2. Use the Object ID, not the Display Name. 3. Ensure the group is a Security group (not M365 group). |
| Polling timeout | No error - flow just times out | Environment provisioning taking longer than 60 minutes | 1. Check environment status in PPAC manually. 2. If still provisioning, wait and retry. 3. If failed, review PPAC errors and contact support. |
| Flow authentication error | "code": "InvalidAuthenticationToken", "message": "The access token has expired" |
Service Principal secret expired | 1. Generate new secret in Entra ID. 2. Update Azure Key Vault. 3. Refresh the Power Automate connection. |
| Dataverse write fails | "code": "0x80040220", "message": "Principal user is missing prvCreate privilege" |
Service account missing security role | Assign ELM Admin security role to the Service Principal user in Dataverse. |
Debug Steps
- Check Flow Run History: Power Automate > Flow > Run history
- Check Dataverse Audit: Advanced Find > ProvisioningLog
- Check Power Platform Admin Center: Environments list for new environment
Next Steps
After completing labs:
- Production Deployment: Export solution and deploy to production environment
- Configure Approvers: Assign real approvers in approval workflow
- Enable Monitoring: Set up alerts for failed provisioning
- Train Users: Onboard requesters to the new process
FSI Agent Governance Framework v1.2.12 - January 2026