Plugin check: Run node "${PLUGIN_ROOT}/scripts/check-version.js" — if it outputs a message, show it to the user before proceeding.
Create web roles for a Power Pages SPA site. Web roles define the permissions and access levels for different types of site users.
Non-SPA sites use the same role schema and uniqueness constraints, but their metadata root can
be either <projectRoot>/.powerpages-site or a directly opened PAC export.
Before reading or executing the workflow below, perform the existing SPA project lookup first:
powerpages.config.json in the current directory or immediate subdirectories using theexisting file-search patterns.
gates, file naming, caller-suppress contract, or deployment behavior.
powerpages.config.json, run:```bash
node "${PLUGIN_ROOT}/scripts/lib/detect-project-context.js"
```
siteType: "non-spa", read and follow${PLUGIN_ROOT}/skills/create-webroles/references/non-spa-site-workflow.md. Do not execute
any of the SPA workflow below.
${PLUGIN_ROOT}/scripts/generate-uuid.js to produce valid UUID v4 values for each web role.anonymoususersrole: true and only one can have authenticatedusersrole: true. Always check existing roles before setting these flags./add-ai-webapi) with the [CALLED-BY-PARENT-SKILL] sentinel in $ARGUMENTS, suppress this skill's deploy prompts (Phase 1's missing-deploy ask, Phase 6's deploy ask (step 3), and the closing reminder) and return as soon as roles are created. The caller batches the deploy at end-of-orchestration. Human invocations never trigger this mode. See Phase 0 below for parsing.Prerequisite: The site must be deployed at least once before web roles can be created, since deployment creates the .powerpages-site folder structure that stores web role definitions.
Initial request: $ARGUMENTS
Inspect $ARGUMENTS. If the text contains the sentinel [CALLED-BY-PARENT-SKILL], set an
internal flag caller-suppress = true that downstream phases consult. The optional tokencaller=<skill-name> may follow the sentinel for diagnostic purposes (e.g.caller=add-ai-webapi); record it for the final summary but do not branch on it.
When the flag is set, skip every deploy prompt this skill would otherwise issue:
.powerpages-site is absent, do NOT ask the user todeploy now. Stop with a clear contract-violation message back to the caller — the caller
was supposed to gate on this before invoking us.
/deploy-site"reminder: skip both. The caller batches the single deploy decision at end-of-orchestration.
When the sentinel is absent, proceed exactly as today (full interactive flow). This is the
regression guard — no human invocation changes behavior.
.powerpages-site/web-roles/ directoryGoal: Confirm the .powerpages-site/web-roles/ directory exists and is ready for web role files
Actions:
**/powerpages.config.json) and check for .powerpages-site/web-roles/.🚦 Gate (plan · create-webroles:1.deploy-first):.powerpages-sitemissing — skill cannot proceed without that folder. Prompt to deploy first or stop.
Trigger: Phase 1 found no.powerpages-sitedirectory.
Why we ask: Web role YAML files written to a non-existent path will never get picked up by deploy; user thinks roles were created but they weren't.
Cancel leaves: Nothing — no YAML files written.
.powerpages-site does NOT exist:the calling skill should have gated on this folder existing before invoking us.
AskUserQuestion (options: "Yes, deploy now (Recommended)", "No, I'll do it later"). If yes, invoke /deploy-site then resume from Phase 2. If no, stop..powerpages-site exists but web-roles/ does NOT: Create the <PROJECT_ROOT>/.powerpages-site/web-roles/ directory.Output: Confirmed .powerpages-site/web-roles/ directory exists and is ready
Goal: Identify all web roles already defined for the site
Actions:
.powerpages-site/web-roles/ directory. Each file represents one web role with this format:```yaml
anonymoususersrole: false
authenticatedusersrole: false
id: 778fa3d0-a2ef-4d2b-98b8-e6c7d8ce1444
name: Administrators
```
"I found the following existing web roles in your site:"
- Administrators (id:778fa3d0-..., authenticated: false, anonymous: false)
- (etc.)
"No web roles are currently defined for your site."
Output: Complete list of existing web roles with their names, IDs, and flags
Goal: Decide which new web roles to create based on site needs and user input
Actions:
🚦 Gate (plan · create-webroles:3.role-selection): Multi-select over suggested + custom web roles. Drives the Phase 4 YAML file writes.
Trigger: Phase 2 inventoried existing roles; Phase 3 suggests new ones.
Why we ask: Wrong roles get created locally — fixable but adds churn to the.powerpages-site/web-roles/folder.
Cancel leaves: Nothing — no YAML files written yet.
AskUserQuestion to confirm with the user.Common web roles for Power Pages sites include:
authenticatedusersrole: true)anonymoususersrole: true)| Question | Options |
|---|---|
| Which web roles would you like to create for your site? You can select from suggestions or describe custom roles. | (Provide relevant suggestions based on site context, existing roles, and business domain) |
CRITICAL: Do NOT suggest roles that already exist. Filter out any existing role names before presenting options.
Output: Confirmed list of new web roles to create
Goal: Generate properly formatted YAML files with valid UUIDs for each new web role
Actions:
For each new web role the user approved, create a YAML file in .powerpages-site/web-roles/.
For each role, generate a UUID using the Node script. NEVER generate UUIDs yourself — always use the script.
node "${PLUGIN_ROOT}/scripts/generate-uuid.js"
The filename should be the role name in kebab-case with a .yml extension (e.g., Administrators → administrators.yml, Content Editors → content-editors.yml).
Write the file with this exact format (4 fields, no extra whitespace or comments):
anonymoususersrole: <true if this is the anonymous users role, false otherwise>
authenticatedusersrole: <true if this is the authenticated users role, false otherwise>
id: <UUID from generate-uuid.js>
name: <Role Name>
Rules:
anonymoususersrole: trueauthenticatedusersrole: truetrue, do not set it again on a new roleOutput: All new web role YAML files created
Goal: Validate that all created web role files exist, have valid format, and constraints are satisfied
Actions:
.powerpages-site/web-roles/ and read each new file to confirm they were written correctly.id field contains a valid UUID v4 formatname field matches the expected role nameanonymoususersrole and authenticatedusersrole are valid booleansanonymoususersrole: trueauthenticatedusersrole: trueid values exist across rolesOutput: All web role files validated — correct format, valid UUIDs, no constraint violations
Goal: Present a summary of created roles and offer deployment
Actions:
Reference: ${PLUGIN_ROOT}/references/skill-tracking-reference.md
Follow the skill tracking instructions in the reference to record this skill's usage. Use --skillName "CreateWebroles".
"I've created the following new web roles:"
| Role Name | ID | Anonymous | Authenticated |
|-----------|-----|-----------|---------------|
| Content Editors |a1b2c3d4-...| false | false |
| (etc.) |
🚦 Gate (plan · create-webroles:6.deploy): Final post-create prompt — deploy now to make the new roles take effect, or defer.
Trigger: Phase 5 validation succeeded.
Why we ask: Auto-invoking/deploy-sitewould push the site to whatever env PAC CLI happens to point at — wrong-env push is messy to undo.
Cancel leaves: Nothing — the YAML files stay on disk; no deploy fired.
entirely. Return the created-roles summary to the caller and stop. The caller owns the
single end-of-orchestration deploy decision; nesting deploy reminders inside delegations
gives the user 2–3 redundant prompts per parent-skill run.
Otherwise, ask the user if they want to deploy the site to apply the new roles:
| Question | Options |
|---|---|
| The new web roles have been created locally. To apply them in Power Pages, the site needs to be deployed. Would you like to deploy now? | Yes, deploy now (Recommended), No, I'll deploy later |
"Please run /deploy-site to deploy your site and apply the new web roles."
"No problem! Remember to deploy your site using /deploy-site when you're ready to apply the new web roles to your Power Pages environment."
Output: Summary presented and deployment offered
.powerpages-site is missingBefore starting Phase 1, create a task list with all phases using TaskCreate:
| Task subject | activeForm | Description |
|---|---|---|
| Verify site structure | Verifying site structure | Check for .powerpages-site/web-roles/ directory, create if needed |
| Discover existing roles | Discovering existing roles | Read current web role YAML files and compile list of existing roles |
| Determine new roles | Determining new roles | Analyze site needs and ask user which roles to create |
| Create web role files | Creating web role files | Generate YAML files with UUIDs from the Node script for each new role |
| Verify web roles | Verifying web roles | Validate all files exist, have valid UUIDs, and uniqueness constraints are satisfied |
| Review and deploy | Reviewing and deploying | Present summary of created roles and offer deployment |
Mark each task in_progress when starting it and completed when done via TaskUpdate. This gives the user visibility into progress and keeps the workflow deterministic.
Begin with Phase 1: Verify Site Structure