[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-microsoft-add-server-logic":3,"mdc--v8z3la-key":40,"related-org-microsoft-add-server-logic":13767,"related-repo-microsoft-add-server-logic":13964},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":35,"sourceUrl":38,"mdContent":39},"add-server-logic","manage Power Pages server logic","Creates, edits, and manages Power Pages Server Logic files — server-side JavaScript that runs securely on the Power Pages runtime. Orchestrates the full lifecycle: gathering requirements, fetching documentation, implementing code, configuring site settings, and deploying. Use when the user wants to add server-side code, create API endpoints, or move logic from the browser to the server in their Power Pages site.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"microsoft","Microsoft","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fmicrosoft.png",[12,16,19,22],{"name":13,"slug":14,"type":15},"Backend","backend","tag",{"name":17,"slug":18,"type":15},"JavaScript","javascript",{"name":20,"slug":21,"type":15},"Power Pages","power-pages",{"name":9,"slug":8,"type":15},564,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fpower-platform-skills","2026-07-03T16:31:53.068842",null,114,[29,30,31,32,33,21,34],"claude-code-plugin","claude-code-skills","code-apps","github-copilot-plugin","power-apps","power-platform",{"repoUrl":24,"stars":23,"forks":27,"topics":36,"description":37},[29,30,31,32,33,21,34],"A plugin marketplace for Claude Code\u002FGitHub Copilot that provides Power Platform development plugins, including reusable skills, agents, and commands for building and deploying solutions.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fpower-platform-skills\u002Ftree\u002FHEAD\u002Fplugins\u002Fpower-pages\u002Fskills\u002Fadd-server-logic","---\nname: add-server-logic\ndescription: >-\n  Creates, edits, and manages Power Pages Server Logic files — server-side JavaScript that\n  runs securely on the Power Pages runtime. Orchestrates the full lifecycle: gathering\n  requirements, fetching documentation, implementing code, configuring site settings, and\n  deploying. Use when the user wants to add server-side code, create API endpoints, or move\n  logic from the browser to the server in their Power Pages site.\nuser-invocable: true\nallowed-tools: Read, Write, Edit, Bash, Grep, Glob, AskUserQuestion, Skill, Task, TaskCreate, TaskUpdate, TaskList, mcp__plugin_power-pages_microsoft-learn__microsoft_docs_search, mcp__plugin_power-pages_microsoft-learn__microsoft_code_sample_search, mcp__plugin_power-pages_microsoft-learn__microsoft_docs_fetch\nmodel: opus\n---\n\n> **Plugin check**: Run `node \"${PLUGIN_ROOT}\u002Fscripts\u002Fcheck-version.js\"` — if it outputs a message, show it to the user before proceeding.\n\n# Add Server Logic\n\nCreate and manage one or more Power Pages Server Logic files — server-side JavaScript that runs securely on the Power Pages runtime, hidden from the browser and protected by web roles and table permissions. Server Logic enables secure external API integrations, Dataverse operations, and custom business logic without exposing sensitive code or credentials to the client.\n\n## Core Principles\n\n- **Microsoft Learn is the source of truth**: Always fetch the latest documentation before writing code. The Server Logic feature is in preview and the SDK may change — never rely on cached knowledge alone.\n- **No browser APIs, no dependencies**: Server Logic runs in a sandboxed server environment with ECMAScript 2023 support. There is no `fetch`, `XMLHttpRequest`, `setTimeout`, or any DOM API. No npm packages are available.\n- **Five functions only**: A server logic file can only export these top-level functions: `get`, `post`, `put`, `patch`, `del`. The name `delete` is a reserved word in JavaScript and cannot be used.\n- **Always return a string**: Every function must return a string. Use `JSON.stringify()` when returning objects or arrays.\n- **Use TaskCreate\u002FTaskUpdate**: Track all progress throughout all phases — create the todo list upfront with all phases before starting any work.\n\n> **Prerequisites:**\n> - An existing Power Pages code site created\n> - The site **must** be deployed at least once (`.powerpages-site` folder must exist) — server logic files live inside `.powerpages-site\u002Fserver-logic\u002F`, so deployment is required before any server logic can be created\n\n**Initial request:** $ARGUMENTS\n\n---\n\n## Workflow\n\n1. **Verify Site Exists** — Locate the Power Pages project, explore existing patterns, and verify prerequisites\n2. **Understand Requirements** — Determine the user intent and whether the solution needs one or more server logic files\n3. **Fetch Latest Documentation** — Query Microsoft Learn for the most current Server Logic SDK reference\n4. **Review Implementation Plan** — Present the plan to the user and confirm before writing code\n5. **Implement Server Logic** — Create the approved `.js` and `.serverlogic.yml` files in `.powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F`\n6. **Configure Table Permissions** — *(Conditional: only if Server.Connector.Dataverse is used)* Set up table permissions for Dataverse tables accessed by the server logic\n7. **Manage Secrets & Environment Variables** — *(Conditional: only if the server logic requires secrets)* Store sensitive values securely using Azure Key Vault (recommended) or direct environment variables in Dataverse\n8. **Configure Site Settings** — Set up ServerLogic site settings if needed\n9. **Client-Side Integration** — Help wire the server logic into the site's frontend code\n10. **Verify & Test Guidance** — Validate the code and provide testing instructions\n11. **Review & Deploy** — Present summary and offer deployment\n\n---\n\n## Phase 1: Verify Site Exists\n\n**Goal**: Locate the Power Pages project root and confirm prerequisites\n\n**Actions**:\n\n1. Create todo list with all 11 phases (see [Progress Tracking](#progress-tracking) table)\n\n### 1.1 Locate Project\n\nLook for `powerpages.config.json` in the current directory or immediate subdirectories\n\n**If not found**: Tell the user to create a site first with `\u002Fcreate-site`.\n\n### 1.2 Read Existing Config\n\nRead `powerpages.config.json` to get the site name and configuration:\n\n### 1.3 Detect Framework\n\nRead `package.json` to determine the frontend framework (React, Vue, Angular, or Astro). This is needed for Phase 8 (client-side integration guidance). See `${PLUGIN_ROOT}\u002Freferences\u002Fframework-conventions.md` for the full framework detection mapping.\n\n### 1.4 Explore Existing Server Logic and Frontend Code\n\nUse the **Explore agent** (via `Task` tool with `agent_type: \"explore\"`) to analyze the site for existing server logic patterns and frontend code that may call or need to call server logic endpoints.\n\n**Prompt for the Explore agent:**\n\n> \"Analyze this Power Pages code site for server logic context. Check:\n> 1. Does `.powerpages-site\u002Fserver-logic\u002F` exist? If yes, list all subdirectories and their .js files. Summarize what each server logic does (which functions it implements, what SDK features it uses). Also read the corresponding .serverlogic.yml files to check web role assignments.\n> 2. Search the frontend source code (`src\u002F**\u002F*.{ts,tsx,js,jsx,vue,astro}`) for any existing calls to `\u002F_api\u002Fserverlogics\u002F` — these indicate server logic endpoints already being consumed.\n> 3. Look for CSRF token handling patterns (`__RequestVerificationToken`, `_layout\u002Ftokenhtml`) — these show how the site currently makes authenticated API calls.\n> 4. Check for any TODO\u002FFIXME comments mentioning server logic, backend, or server-side processing.\n> 5. Look for hardcoded API URLs, mock data, or placeholder fetch calls that might need to be replaced with server logic calls.\n> 6. Check for any existing service layer or API utility files in `src\u002Fshared\u002F`, `src\u002Fservices\u002F`, or similar directories that could be reused for server logic integration.\n> 7. Read `.powerpages-site\u002Fweb-roles\u002F*.webrole.yml` files to list available web roles and their GUIDs — these are needed when creating the server logic metadata YAML.\n> 8. For each existing server logic, assess whether it can be reused or safely extended for the requested capability instead of creating a brand-new server logic file. Call out any strong reuse candidates and explain why.\n> Report all findings so we can avoid duplicating work and match existing patterns.\"\n\nFrom the Explore agent's findings, note:\n- **Existing server logic files** — what's already implemented, and which ones are candidates for reuse or extension\n- **Frontend calling patterns** — how the site makes API calls (match this pattern in Phase 9)\n- **Existing service\u002Futility files** — reuse these when adding client-side integration\n- **Gaps** — frontend code that references server logic endpoints that don't exist yet\n\n### 1.5 Check Deployment Status (Mandatory)\n\nLook for the `.powerpages-site` folder:\n\n\n**If not found**: The site **must** be deployed before server logic can be created — server logic files live inside `.powerpages-site\u002Fserver-logic\u002F`. Tell the user:\n\n> \"The `.powerpages-site` folder was not found. Server logic files are stored inside this folder, so the site must be deployed at least once before creating server logic. Would you like to deploy now?\"\n\n\u003C!-- gate: add-server-logic:1.5.deploy-first | category=plan | cancel-leaves=nothing -->\n\n> 🚦 **Gate (plan · add-server-logic:1.5.deploy-first):** `.powerpages-site` missing — server logic files live inside it. Deploy first or stop.\n>\n> **Trigger:** Phase 1.5 found no `.powerpages-site` directory.\n> **Why we ask:** Server logic `.js`\u002F`.yml` files written to a non-existent path won't deploy.\n> **Cancel leaves:** Nothing — no server logic files written yet.\n\nUse `AskUserQuestion`:\n\n| Question | Options |\n|----------|---------|\n| The `.powerpages-site` folder is required for server logic. Would you like to deploy the site now? | Yes, deploy now (Required), Cancel |\n\n**If \"Yes, deploy now\"**: Invoke `\u002Fdeploy-site` first, then continue to Phase 2.\n\n**If \"Cancel\"**: Stop the workflow — server logic cannot be created without `.powerpages-site`.\n\n**Output**: Confirmed project root, `.powerpages-site` exists, existing server logic (if any), available web roles\n\n---\n\n## Phase 2: Understand Requirements\n\n**Goal**: Determine the user intent, identify whether one or more server logic files are needed, and capture the required HTTP methods for each item\n\n**Actions**:\n\n### 2.1 Analyze User Request\n\nFrom the user's request, determine:\n\n- **Intent shape**: Does the request map to a single server logic or multiple server logic?\n- **Reuse opportunities**: Can an existing server logic satisfy or be safely extended for part of the request?\n- **Server logic inventory**: For each required server logic, capture the purpose, suggested endpoint name, and whether it should be reused, extended, or created new\n- **HTTP methods needed**: Which of the 5 functions should be implemented for each server logic (`get`, `post`, `put`, `patch`, `del`)\n\nPrefer reuse or safe extension of an existing server logic when it already matches the domain, security model, and lifecycle of the requested capability. Only create a new server logic when reuse would make the existing file confusing, over-broad, or unsafe.\n\nPrefer multiple server logic files when the use case naturally separates into different responsibilities, security boundaries, or lifecycle concerns. Examples:\n\n- Separate read vs. write workflows with different web role requirements\n- Distinct integrations with different external systems or site settings\n- Independent business capabilities that would be harder to test or reason about if merged into one endpoint\n\n### 2.1.1 Identify Validate-and-Execute Patterns\n\nFor each planned server logic item, determine whether it should **validate-and-execute** — meaning the server logic both validates a business rule AND performs the resulting Dataverse write, rather than just returning a validation result for the client to act on.\n\nA server logic item should validate-and-execute when **any** of these are true:\n\n| Condition | Example |\n|-----------|---------|\n| It enforces a state machine or lifecycle | Order status: Draft → Submitted → Approved |\n| The write is conditional on a business rule that must be tamper-proof | \"Only allow bid submission before the deadline\" |\n| The operation spans multiple tables atomically | Award a bid + reject all others + update event status |\n| The write involves a computed or derived value | Server calculates a score and writes it |\n| The client should not have direct write access to the field | Status fields with strict transition rules |\n\nFor each validate-and-execute item, note:\n- **Which Dataverse writes the server logic will perform** (UpdateRecord, CreateRecord, etc.)\n- **Which fields are being written** — these fields should NOT be writable via Web API from the client\n- **What the server logic returns to the client** — typically a success\u002Ffailure result with the before\u002Fafter state, NOT a validation flag that the client acts on\n\n**Anti-pattern to avoid**: A server logic item that only validates and returns `{ valid: true\u002Ffalse }`, expecting the client to make a separate Web API call to perform the write. This allows the client to skip validation and write directly.\n\n### 2.1.2 Discover Dataverse Custom Actions\n\nIf any planned server logic item involves Dataverse operations, check whether the user's Dataverse environment has existing custom actions (Custom APIs or Custom Process Actions) that could be leveraged instead of building logic from scratch.\n\n**Step 1 — Fetch custom actions:**\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fscripts\u002Flist-custom-actions.js\" \"\u003CENV_URL>\"\n```\n\nThe script outputs a JSON object with:\n- `customApis` — Modern Custom APIs with full request parameters and response properties\n- `customProcessActions` — Legacy Custom Process Actions (activated only)\n- `total` — Total count of both types combined\n\nEach entry includes: `name`, `displayName`, `description`, `type` (`action` or `function`), `binding` (`unbound`, `entity`, or `entityCollection`), `boundEntity`, and `source` (`customApi` or `customProcessAction`). Custom APIs also include `requestParameters` and `responseProperties` arrays.\n\n**Step 2 — Present and ask the user:**\n\nIf custom actions are found (`total > 0`), present a summary to the user grouped by binding type (unbound vs. entity-bound) and ask whether any should be used:\n\n\u003C!-- gate: add-server-logic:2.1.2.use-custom-actions | category=plan | cancel-leaves=nothing -->\n\n> 🚦 **Gate (plan · add-server-logic:2.1.2.use-custom-actions):** Custom actions discovered — decide whether to wrap existing Dataverse Custom APIs\u002FProcess Actions or build server logic from scratch. Choice changes the Phase 5 implementation shape.\n>\n> **Trigger:** `list-custom-actions.js` returned at least one entry.\n> **Why we ask:** Auto-wrapping could attach the wrong action; auto-skipping duplicates logic that already exists in Dataverse.\n> **Cancel leaves:** Nothing — no server logic files written yet.\n\nUse `AskUserQuestion`:\n\n| Question | Options |\n|----------|---------|\n| Your Dataverse environment has `\u003Ctotal>` custom action(s). Would you like to use any of these in your server logic instead of writing the logic from scratch? | Yes, let me choose which ones to use; No, build everything from scratch |\n\nPresent the list clearly — for each action show: name, description, type (action\u002Ffunction), binding, and bound entity (if applicable). Group them as **Unbound** and **Entity-bound** for readability.\n\nIf the user says **No**, skip to Phase 2.2.\n\n**Step 3 — Map custom actions to server logic items:**\n\nIf the user says **Yes**, for each server logic item being created, ask which custom action (if any) it should wrap:\n\n\u003C!-- not-a-gate: per-item custom-action mapping — data-gathering sub-prompt under the Phase 2.1.2 Yes path; final intent is locked in by the Phase 4.4 plan gate -->\n\nUse `AskUserQuestion` for each server logic item:\n\n| Question | Context |\n|----------|---------|\n| For the `\u003Cserver-logic-name>` endpoint, which custom action should it use? | Present the list of custom actions with their names, descriptions, and binding types. Include **\"None — build from scratch\"** as an option. |\n\nRecord the mapping for each server logic item. For items that wrap a custom action, note:\n- The custom action name (used in the `InvokeCustomApi` call)\n- Whether it's a function (`GET`) or action (`POST`)\n- The binding type and bound entity (if applicable)\n- The request parameters and response properties (if available from Custom APIs)\n\nThis mapping will be used in Phase 5.3 when generating the server logic code, and will appear in the HTML plan (Phase 4) to indicate which items wrap existing custom actions.\n\n### 2.2 Identify SDK Features Needed\n\nBased on each planned server logic item's purpose, identify which Server SDK features are required:\n\n| Feature | When to use |\n|---------|-------------|\n| `Server.Connector.HttpClient` | Calling external REST APIs (NOT Dataverse) |\n| `Server.Connector.Dataverse` | Reading\u002Fwriting Dataverse records (CRUD + `InvokeCustomApi` for Dataverse Custom APIs) |\n| `Server.Context` | Accessing request parameters, headers, body |\n| `Server.User` | User-scoped operations, role checks |\n| `Server.Logger` | Always — every function should log entry\u002Fexit and errors |\n| `Server.Sitesetting` | Reading site setting configuration values |\n| `Server.EnvironmentVariable` | Reading Dataverse environment variable values directly via `Server.EnvironmentVariable.get(name)` — an alternative to `Server.Sitesetting` for non-secret config |\n| `Server.Website` | Accessing site metadata |\n\n### 2.3 Identify Secret Values\n\nDetermine whether any server logic item requires secret or sensitive configuration values that should not be hardcoded. Common examples:\n\n| Scenario | Secret needed |\n|----------|---------------|\n| Calling an authenticated external API | API key, client secret, bearer token |\n| Connecting to a third-party service | Connection string, access token |\n| OAuth2 client credentials flow | Client ID + client secret |\n| Webhook verification | Signing secret, shared key |\n\nFor each identified secret, capture:\n- **Secret name**: A descriptive name (e.g., `ExchangeRateApiKey`, `PaymentGatewaySecret`)\n- **Purpose**: Why the secret is needed\n- **Site setting name**: The name the server logic will use with `Server.Sitesetting.Get()` (e.g., `ExternalApi\u002FExchangeRateApiKey`)\n- **Environment variable schema name**: The Dataverse environment variable schema name (e.g., `cr5b4_ExchangeRateApiKey`)\n\nThese values will be used in Phase 7 to create the environment variables and site settings.\n\n### 2.3.1 Key Vault Decision\n\nIf secrets were identified in Phase 2.3, ask the user now whether they want to use Azure Key Vault. This decision must happen before Phase 4 so the implementation plan can show the chosen secret management approach.\n\n\u003C!-- gate: add-server-logic:2.3.1.keyvault | category=plan | cancel-leaves=nothing -->\n\n> 🚦 **Gate (plan · add-server-logic:2.3.1.keyvault):** Pick secret-storage mechanism (Key Vault vs plain env var). Choice changes the Phase 4 rendered plan and the Phase 7 implementation pipeline.\n>\n> **Trigger:** Phase 2.3 identified at least one secret value.\n> **Why we ask:** Plain env var creation can expose secrets in solution exports; auto-picking Key Vault forces additional Azure setup.\n> **Cancel leaves:** Nothing — no env var definitions written yet.\n\nUse `AskUserQuestion`:\n\n| Question | Options |\n|----------|---------|\n| This server logic requires secret values (e.g., API keys, client secrets). Azure Key Vault is the recommended way to store secrets securely. Would you like to use Azure Key Vault? | Yes, use Azure Key Vault (Recommended), No, store directly as environment variable |\n\nRecord the user's choice — it will be shown in the HTML plan (Phase 4) and executed in Phase 7.\n\n### 2.4 Confirm with User\n\n\u003C!-- not-a-gate: requirement clarification — multi-question data-gathering that shapes the upcoming Phase 4.4 plan gate -->\n\nIf the requirements are ambiguous, use `AskUserQuestion` to clarify:\n\n| Question | Context |\n|----------|---------|\n| What should this server logic solution do overall? | If the purpose is unclear |\n| Should this be one server logic or multiple server logic? | If the request could reasonably be modeled either way |\n| Which HTTP methods does each server logic need? | If not specified — suggest based on the use case (e.g., read-only = GET, form processing = POST) |\n| Does each server logic need to call external APIs, Dataverse, or both? | Determines which connectors to use |\n| What should each server logic be named? | Suggest URL-friendly names based on the responsibilities |\n| Does the server logic need any secret or sensitive values (API keys, client secrets, tokens)? | If the server logic calls authenticated external APIs or services |\n\n**Output**: Clear understanding of the overall intent, the list of server logic items to reuse\u002Fextend\u002Fcreate, their HTTP methods, SDK features needed, and any secrets required\n\n---\n\n## Phase 3: Fetch Latest Documentation\n\n**Goal**: Discover and read all current Server Logic documentation from Microsoft Learn before writing any code\n\nThis step is critical because Server Logic is a preview feature and the SDK surface may change. The documentation on Microsoft Learn is the authoritative source.\n\n**Actions**:\n\n### 3.1 Follow the Documentation Reference\n\nUse the reference document below as the source of truth for how to discover, classify, fetch, and reconcile Server Logic documentation:\n\n> Reference: `${PLUGIN_ROOT}\u002Fskills\u002Fadd-server-logic\u002Freferences\u002Fserver-logic-docs.md`\n\nFollow that reference to:\n\n- Search Microsoft Learn dynamically for all current Server Logic docs\n- Fetch the core reference pages and any relevant scenario-specific pages\n- Search for current code samples\n- Reconcile the discovered documentation with the known SDK baseline in the reference\n\n### 3.2 Extract Task-Specific Notes\n\nFrom the fetched docs, extract and note the items that matter for the current task:\n\n- All SDK method signatures, parameter types, and return types\n- Current supported HTTP methods and function signatures\n- Site settings and their defaults\n- Security model (web roles, table permissions, CSRF)\n- Client-side calling patterns and response format\n- Any new methods or breaking changes discovered in Microsoft Learn\n\n**Output**: Up-to-date SDK reference verified against all relevant Microsoft Learn documentation pages\n\n---\n\n## Phase 4: Review Implementation Plan\n\n**Goal**: Present the implementation plan to the user and confirm before writing any code\n\n**Actions**:\n\n### 4.1 Prepare the Plan Data\n\nBuild the server logic plan data and render the HTML plan before asking for approval.\n\n> Reference: `${PLUGIN_ROOT}\u002Fskills\u002Fadd-server-logic\u002Freferences\u002Fserver-logic-plan-data-format.md`\n\nThe rendered plan should summarize:\n\n- The number of server logic items being created or reused\n- Each endpoint name, API URL, and files to be created\n- The functions that will be implemented and what each one does\n- The SDK features, external services, and Dataverse tables involved for each item\n- The web roles, security constraints, and site settings that apply to each item\n- Any secrets or sensitive values that will be stored as environment variables (with or without Azure Key Vault). If the user chose Azure Key Vault in Phase 2.3.1, populate `SECRETS_DATA` with `useKeyVault: true` and the list of secrets — the HTML plan will render a Key Vault banner explaining the security benefits and show which secrets each server logic depends on. If no secrets are needed, set `SECRETS_DATA` to `null`.\n- The expected next steps after approval\n\n### 4.2 Render the HTML Plan\n\nGenerate the HTML plan file from the template and open it in the user's default browser before asking for approval.\n\nWhen working inside a Power Pages project, write the plan to:\n\n```text\n\u003CPROJECT_ROOT>\u002Fdocs\u002Fserverlogic-plan.html\n```\n\nCreate the `docs\u002F` folder if it does not already exist. Keep this HTML file inside the repository so it can be reviewed and committed with the rest of the server logic work.\n\nDo **not** hand-author the HTML. Use the render script:\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fscripts\u002Frender-serverlogic-plan.js\" --output \"\u003COUTPUT_PATH>\" --data \"\u003CDATA_JSON_PATH>\"\n```\n\nThe render script refuses to overwrite existing files. Before calling it, check if the default output path (`\u003CPROJECT_ROOT>\u002Fdocs\u002Fserverlogic-plan.html`) already exists. If it does, choose a new descriptive filename based on context — e.g., `serverlogic-plan-exchange-rate.html`, `serverlogic-plan-apr-2026.html`. Pass the chosen name via `--output`.\n\n### 4.3 Present Plan Summary\n\nDo **not** present a second detailed plan in the CLI. The HTML file is the single detailed plan artifact.\n\nIn the CLI, give only a brief summary that points the user to the HTML plan open in the browser. Keep it to:\n\n- Total server logic count\n- Whether the plan is creating, updating, or reusing items\n- Whether web roles, table permissions, or site settings are involved\n- The actual output path returned by the render script\n- A note that the browser-opened HTML contains the full details\n\nDo not restate the per-server-logic breakdown, rationale, role assignments, or function details inline in the CLI unless the user explicitly asks for a text version. Tell the user where the detailed HTML plan file was saved, that it has been opened in the browser for review, and that the repo copy of the plan will be committed with the implementation artifacts unless the user asks to discard it.\n\n### 4.4 Confirm with User\n\n\u003C!-- gate: add-server-logic:4.4.plan-approval | category=plan | cancel-leaves=nothing -->\n\n> 🚦 **Gate (plan · add-server-logic:4.4.plan-approval):** Final sign-off on the rendered HTML plan before Phase 5 writes any `.serverlogic.yml` \u002F `.js` files or Phase 7 creates env vars.\n>\n> **Trigger:** Phase 4.2 rendered the HTML plan; Phase 4.3 surfaced the CLI summary.\n> **Why we ask:** Server logic files committed under wrong names \u002F wrong roles; env var definitions created against the wrong secret-storage mode.\n> **Cancel leaves:** Nothing — no server logic files written yet.\n\nUse `AskUserQuestion`:\n\n| Question | Options |\n|----------|---------|\n| Here's the implementation plan for this server logic work. Does it look correct? | Approve and implement (Recommended), Request changes, Cancel |\n\n**If \"Request changes\"**: Ask what needs to change, update the plan, and present again.\n\n**If \"Cancel\"**: Stop the workflow.\n\n**Output**: User-approved implementation plan\n\n---\n\n## Phase 5: Implement Server Logic\n\n**Goal**: Create each approved server logic `.js` file and metadata YAML following the constraints verified in Phase 3\n\n**Actions**:\n\n### 5.1 Create Server Logic Folder\n\nFor each approved server logic item:\n\n- **If the approved plan says `reuse`**: Do not create a new folder. Reuse the existing server logic as-is and only update the surrounding integration work if needed.\n- **If the approved plan says `update` \u002F extend**: Reuse the existing folder and update the existing `.js` \u002F `.serverlogic.yml` files rather than creating duplicates.\n- **If the approved plan says `create`**: Create the folder inside `.powerpages-site\u002Fserver-logic\u002F` (note: singular `server-logic`, no trailing 's'). Ensure the folder name matches that endpoint name exactly.\n\n### 5.2 Read or Create Web Roles\n\nUse the **Create Web Role** skill to determine which web roles are required for the approved server logic plan and to create any missing roles before writing metadata.\n\nDo **not** assume every server logic should get every available role. Instead, determine the minimum set of roles required for each server logic based on its purpose, security model, and the approved plan.\n\nExample web role file content:\n```yaml\nadx_anonymoususersrole: false\nadx_authenticatedusersrole: true\ndescription: Role for authenticated users\nid: a1b2c3d4-e5f6-7890-abcd-ef1234567890\nname: Authenticated Users\n```\n\nIn the skill workflow, explicitly invoke the **Create Web Role** skill when:\n\n- The site has no suitable existing web roles\n- The approved plan includes proposed roles that do not exist yet\n- The role assignments need to be refined before metadata can be created\n\nAfter the Create Web Role skill completes, read the resulting web role YAML files and collect the `id` and `name` values needed for each server logic's metadata YAML.\n\n### 5.3 Create the Server Logic File\n\nRepeat this step for each approved server logic item. Create or update `\u003CPROJECT_ROOT>\u002F.powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F\u003Cname>.js` according to the approved plan status (`create`, `update`, or `reuse`) and follow these mandatory patterns:\n\n#### Structure Rules\n\n1. **Only top-level functions**: The file can only contain these 5 functions at the top level: `get`, `post`, `put`, `patch`, `del`. Only include the functions the user needs.\n2. **Each function returns a string**: Use `JSON.stringify()` for objects\u002Farrays.\n3. **Each function has try\u002Fcatch**: Every function must wrap its logic in a try\u002Fcatch block.\n4. **Each function logs**: Use `Server.Logger.Log()` at entry and `Server.Logger.Error()` in catch blocks.\n5. **No imports or requires**: No `import`, `require`, or external dependencies.\n6. **No browser APIs**: No `fetch`, `XMLHttpRequest`, `setTimeout`, `setInterval`, `console.log`, or DOM APIs.\n7. **Async when needed**: Mark functions as `async` only when they use `await` (HttpClient calls). Dataverse connector methods (`Server.Connector.Dataverse.*`) are **synchronous** — do NOT use `async`\u002F`await` with them.\n\n#### Prohibited Script Patterns\n\nThe Power Pages server-side script validator rejects scripts containing certain patterns at runtime. Violations surface as `RTSL01: Script validation failed: prohibited pattern found - Pattern: \u003Cregex>` in diagnostics, and the function silently falls through without executing user code.\n\n| Pattern | Regex | Caveat |\n|---------|-------|--------|\n| JavaScript `with` statement | `with\\s*\\(` | The regex matches the substring `with(` **anywhere** in the file — including inside string literals and inside other identifiers. OData filter functions like `startswith(`, `endswith(`, and `groupwith(` will trip it because they end with `with(`. |\n\n**Workaround for OData functions** — split the literal so `with(` is not contiguous in source:\n\n```javascript\n\u002F\u002F ❌ Triggers validator: \"startswith(\" contains the substring \"with(\"\nvar query = \"$filter=startswith(name,'INV-')\";\n\n\u002F\u002F ✅ Split the literal — server still receives \"startswith(name,...)\"\nvar query = \"$filter=startswith\" + \"(name,'INV-')\";\n```\n\nThe same trick applies to `endswith(`, `groupwith(`, and any other identifier that ends with `with(`.\n\n#### Code Template\n\n```javascript\n\u002F\u002F Server Logic: \u003Cname>\n\u002F\u002F Purpose: \u003Cdescription>\n\u002F\u002F API URL: https:\u002F\u002F\u003Csite-url>\u002F_api\u002Fserverlogics\u002F\u003Cname>\n\nfunction get() {\n    try {\n        Server.Logger.Log(\"\u003Cname> GET called\");\n\n        \u002F\u002F Access query parameters\n        \u002F\u002F const id = Server.Context.QueryParameters[\"id\"];\n\n        \u002F\u002F Your logic here...\n\n        return JSON.stringify({\n            status: \"success\",\n            method: \"GET\",\n            data: null \u002F\u002F replace with actual data\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> GET failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            method: \"GET\",\n            message: err.message\n        });\n    }\n}\n```\n\n#### Validate-and-Execute Template\n\nWhen a server logic item is identified as validate-and-execute (see Phase 2.1.1), use this pattern. The key difference: the server logic reads the current state, validates the business rule, AND writes the result to Dataverse — all in one call. The client never writes the protected field directly.\n\n```javascript\n\u002F\u002F Server Logic: \u003Cname>\n\u002F\u002F Purpose: Validate and execute \u003Cdescribe the operation>\n\u002F\u002F Pattern: Validate-and-execute — this endpoint both validates the business rule\n\u002F\u002F          and performs the Dataverse write. The client should NOT write \u003Cprotected fields>\n\u002F\u002F          via Web API — all writes to those fields go through this endpoint.\n\u002F\u002F API URL: https:\u002F\u002F\u003Csite-url>\u002F_api\u002Fserverlogics\u002F\u003Cname>\n\nfunction post() {\n    try {\n        Server.Logger.Log(\"\u003Cname> POST called\");\n\n        const body = JSON.parse(Server.Context.Body);\n        const entityId = body.entityId;\n        const targetStatus = body.targetStatus;\n\n        \u002F\u002F 1. Read the current record from Dataverse\n        const current = Server.Connector.Dataverse.RetrieveRecord(\"\u003Ctable-name>\", entityId, \"?$select=\u003Cstatus-field>\");\n        const currentStatus = current[\"\u003Cstatus-field>\"];\n\n        \u002F\u002F 2. Validate the transition\n        const allowedTransitions = {\n            \"Draft\": [\"Submitted\"],\n            \"Submitted\": [\"Approved\", \"Rejected\"],\n            \"Approved\": [\"Fulfilled\"]\n        };\n\n        const allowed = allowedTransitions[currentStatus] || [];\n        if (!allowed.includes(targetStatus)) {\n            return JSON.stringify({\n                status: \"error\",\n                message: \"Invalid transition: \" + currentStatus + \" → \" + targetStatus + \" is not allowed\",\n                currentStatus: currentStatus,\n                targetStatus: targetStatus,\n                allowedTargets: allowed\n            });\n        }\n\n        \u002F\u002F 3. Execute the write — server performs the Dataverse update\n        const updateData = {};\n        updateData[\"\u003Cstatus-field>\"] = targetStatus;\n        Server.Connector.Dataverse.UpdateRecord(\"\u003Ctable-name>\", entityId, JSON.stringify(updateData));\n\n        Server.Logger.Log(\"\u003Cname> transition executed: \" + currentStatus + \" → \" + targetStatus);\n\n        \u002F\u002F 4. Return the result — client receives confirmation, not a validation flag\n        return JSON.stringify({\n            status: \"success\",\n            previousStatus: currentStatus,\n            newStatus: targetStatus,\n            entityId: entityId\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> POST failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            message: err.message\n        });\n    }\n}\n```\n\n**Key differences from the basic template:**\n1. The server logic reads the current state from Dataverse (not trusting the client's view)\n2. It validates the business rule server-side\n3. It writes the result to Dataverse via `Server.Connector.Dataverse.UpdateRecord`\n4. It returns a success\u002Ffailure result — NOT a `{ valid: true\u002Ffalse }` flag for the client to act on\n5. The client calls this one endpoint — it does NOT make a separate Web API PATCH call\n\n#### Custom Action Wrapping Template\n\nWhen a server logic item wraps a Dataverse custom action (mapped in Phase 2.1.2), use this pattern with `Server.Connector.Dataverse.InvokeCustomApi`. The server logic acts as a portal-friendly wrapper, exposing the custom action through a `\u002F_api\u002Fserverlogics\u002F\u003Cname>` endpoint with proper web role authorization.\n\n**Unbound action:**\n\n```javascript\n\u002F\u002F Server Logic: \u003Cname>\n\u002F\u002F Purpose: Wraps Dataverse custom action \"\u003Ccustom-action-name>\" for portal consumption\n\u002F\u002F Custom Action: \u003Ccustom-action-name> (unbound, action)\n\u002F\u002F API URL: https:\u002F\u002F\u003Csite-url>\u002F_api\u002Fserverlogics\u002F\u003Cname>\n\nfunction post() {\n    try {\n        Server.Logger.Log(\"\u003Cname> POST called — invoking custom action \u003Ccustom-action-name>\");\n\n        const body = JSON.parse(Server.Context.Body);\n\n        \u002F\u002F Build the request payload matching the custom action's input parameters\n        const payload = JSON.stringify({\n            \u002F\u002F \"\u003CParameterName>\": body.\u003CclientFieldName>\n        });\n\n        const result = Server.Connector.Dataverse.InvokeCustomApi(\n            \"POST\",\n            \"\u003Ccustom-action-name>\",\n            payload\n        );\n\n        Server.Logger.Log(\"\u003Cname> custom action completed successfully\");\n\n        return JSON.stringify({\n            status: \"success\",\n            data: result\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> POST failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            message: err.message\n        });\n    }\n}\n```\n\n**Entity-bound action:**\n\n```javascript\nfunction post() {\n    try {\n        Server.Logger.Log(\"\u003Cname> POST called — invoking bound action \u003Ccustom-action-name>\");\n\n        const body = JSON.parse(Server.Context.Body);\n        const entityId = body.entityId;\n\n        const payload = JSON.stringify({\n            \u002F\u002F \"\u003CParameterName>\": body.\u003CclientFieldName>\n        });\n\n        \u002F\u002F Include the entity set and record ID, followed by the fully qualified action name\n        const result = Server.Connector.Dataverse.InvokeCustomApi(\n            \"POST\",\n            \"\u003Centity-set-name>(\" + entityId + \")\u002FMicrosoft.Dynamics.CRM.\u003Ccustom-action-name>\",\n            payload\n        );\n\n        Server.Logger.Log(\"\u003Cname> bound action completed for entity \" + entityId);\n\n        return JSON.stringify({\n            status: \"success\",\n            data: result,\n            entityId: entityId\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> POST failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            message: err.message\n        });\n    }\n}\n```\n\n**Unbound function (read-only, GET):**\n\n```javascript\nfunction get() {\n    try {\n        Server.Logger.Log(\"\u003Cname> GET called — invoking custom function \u003Ccustom-function-name>\");\n\n        \u002F\u002F Pass parameters as query string for functions\n        const param1 = Server.Context.QueryParameters[\"param1\"];\n        const queryString = \"\u003Ccustom-function-name>(Param1='\" + param1 + \"')\";\n\n        const result = Server.Connector.Dataverse.InvokeCustomApi(\n            \"GET\",\n            queryString,\n            null\n        );\n\n        Server.Logger.Log(\"\u003Cname> custom function completed successfully\");\n\n        return JSON.stringify({\n            status: \"success\",\n            data: result\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> GET failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            message: err.message\n        });\n    }\n}\n```\n\n**Key points:**\n- **Unbound actions**: Use the action name as the URL, pass parameters as JSON body\n- **Entity-bound actions**: Include the entity set and record ID in the URL path, followed by `Microsoft.Dynamics.CRM.\u003Caction-name>`\n- **Functions (GET)**: Use `\"GET\"` as the HTTP method and pass parameters inline in the URL using OData function call syntax\n- **Actions (POST)**: Use `\"POST\"` as the HTTP method and pass parameters as JSON body payload\n- `InvokeCustomApi` is **synchronous** — do NOT use `async`\u002F`await`\n- The server logic can add additional validation, transformation, or logging around the custom action call — it doesn't have to be a pass-through\n- When Custom API response properties are known (from Phase 2.1.2), map them to the response object for clarity\n\n#### Dataverse Response Shape (Critical for Frontend Integration)\n\nWhen a function returns the result of a `Server.Connector.Dataverse.*` method, the client sees a double-wrapped payload — the most common cause of broken frontend integrations. Before writing the function, pick one of three response shapes and record the choice for Phase 9: **Approach A — raw passthrough** (return the connector result as-is), **Approach B — envelope that wraps the connector result** (return `{ status, data: result }` without unwrapping `Body`), or **Approach C — fully normalized** (parse `Body` server-side and return a feature-specific shape — recommended for non-generic endpoints).\n\nSee `${PLUGIN_ROOT}\u002Fskills\u002Fadd-server-logic\u002Freferences\u002Ffrontend-integration-reference.md` → \"Dataverse Connector Response Format\" for the double-wrapping explanation, the `CreateRecord` \u002F `entityid` header behavior, and server- and client-side examples for each shape.\n\n#### Referencing Secrets in Code\n\nWhen the server logic needs a secret value identified in Phase 2.3, **never hardcode the value**. Instead, read it at runtime from a site setting backed by an environment variable:\n\n```javascript\nconst apiKey = Server.Sitesetting.Get(\"ExternalApi\u002FExchangeRateApiKey\");\n```\n\nUse the site setting name planned in Phase 2.3. The actual environment variable and site setting YAML will be created in Phase 7.\n\n#### SDK Usage Guidance\n\nDo **not** duplicate Microsoft Learn SDK usage patterns inline in this skill. Use the documentation fetched in Phase 3 as the source of truth for connector methods, signatures, and supported patterns, then apply only the task-specific notes that were captured in the approved plan.\n\n### 5.4 Create the Metadata YAML\n\nFor each approved server logic item where the plan status is `create`, generate the metadata file with the deterministic writer script instead of hand-authoring the YAML. The script generates the UUID, writes the fields in the correct order, and returns the created file path as JSON. **Skip this step for `update` \u002F `reuse` items** — the YAML already exists and should be updated manually if needed.\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fskills\u002Fadd-server-logic\u002Fscripts\u002Fcreate-serverlogic-metadata.js\" --projectRoot \"\u003CPROJECT_ROOT>\" --name \"\u003Cname>\" --displayName \"\u003Chuman-readable display name>\" --description \"\u003Cdescription of what this server logic does>\" --webRoleIds \"\u003Cuuid1,uuid2,uuid3>\"\n```\n\nThe generated `\u003CPROJECT_ROOT>\u002F.powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F\u003Cname>.serverlogic.yml` file has this structure:\n\n```yaml\nadx_serverlogic_adx_webrole:\n  - \u003Cweb-role-guid-1>\n  - \u003Cweb-role-guid-2>\n  - \u003Cweb-role-guid-3>\ndescription: \u003Cdescription of what this server logic does>\ndisplay_name: \u003Chuman-readable display name>\nid: \u003Cgenerated-uuid>\nname: \u003Cname>\n```\n\n**Critical requirements:**\n\n- **`id` field is mandatory** — The script generates a new UUID (v4). PAC CLI crashes with `Expected Guid for primary key 'id'` if this is missing.\n- **`adx_serverlogic_adx_webrole`** — Array of web role GUIDs from step 5.2. Include only the roles required for that server logic item.\n- **`name`** — Must match the folder name and `.js` file name (the URL-friendly name used in `\u002F_api\u002Fserverlogics\u002F\u003Cname>`).\n- **`display_name`** — Human-readable name (e.g., \"Exchange Rate API\", \"Order Processor\").\n- **Alphabetical field ordering** — Fields must be sorted alphabetically: `adx_serverlogic_adx_webrole`, `description`, `display_name`, `id`, `name`.\n\n### 5.5 Validate the Code\n\nBefore saving, verify the code against these constraints:\n\n| Constraint | Check |\n|-----------|-------|\n| Only allowed top-level functions | No functions other than get, post, put, patch, del |\n| Every function returns a string | All code paths return a string (including catch blocks) |\n| try\u002Fcatch in every function | Every function body is wrapped in try\u002Fcatch |\n| Server.Logger in every function | Log at entry, Error in catch |\n| No external dependencies | No `import`, `require`, `module.exports` |\n| No browser APIs | No `fetch`, `XMLHttpRequest`, `setTimeout`, `console.log`, `document`, `window` |\n| Async only when needed | Only functions using `await` are marked `async` |\n| ECMAScript 2023 compliant | Standard JS features only (optional chaining, nullish coalescing, etc. are fine) |\n\n### 5.6 Git Commit\n\nAfter creating the approved server logic files, do a git commit for the server logic changes.\n\nIf the HTML plan was generated inside the project, include it in the same commit (use the actual output path from the render script's JSON response).\n\n**Output**: Server logic `.js` and `.serverlogic.yml` files created, validated, and committed\n\n---\n\n## Phase 6: Configure Table Permissions (Conditional)\n\n**Goal**: Set up table permissions for Dataverse tables accessed by `Server.Connector.Dataverse` in the server logic code\n\n**This phase only runs when the server logic uses `Server.Connector.Dataverse`.** If the server logic only uses `Server.Connector.HttpClient` (external APIs) or doesn't access Dataverse at all, skip this phase entirely and proceed to Phase 7.\n\n`Server.Connector.Dataverse` does **NOT** bypass table permissions — it respects them. Without table permissions configured, the Dataverse connector silently returns 0 records instead of the actual data. This is a common source of confusion.\n\n**Actions**:\n\n### 6.1 Detect Dataverse Tables and Required Privileges\n\nParse the server logic `.js` file created in Phase 5 to identify which Dataverse tables are accessed and what CRUD operations are performed:\n\n| Dataverse SDK Method | Required Table Permission |\n|---------------------|--------------------------|\n| `RetrieveMultipleRecords(\"tablename\", ...)` | Read |\n| `RetrieveRecord(\"tablename\", ...)` | Read |\n| `CreateRecord(\"tablename\", ...)` | Create |\n| `UpdateRecord(\"tablename\", ...)` | Write |\n| `DeleteRecord(\"tablename\", ...)` | Delete |\n\nExtract the entity set name (first argument) from each method call. Build a mapping:\n\n| Table (entity set name) | Read | Create | Write | Delete |\n|------------------------|:----:|:------:|:-----:|:------:|\n| `accounts` | Yes | — | — | — |\n| `contacts` | Yes | Yes | — | — |\n\n### 6.2 Use the Table Permissions Architect\n\nWhen any approved server logic item uses `Server.Connector.Dataverse`, invoke the `table-permissions-architect` agent at `${PLUGIN_ROOT}\u002Fagents\u002Ftable-permissions-architect.md` to determine and create the required table permissions.\n\n**Prompt:**\n\n> \"Analyze this Power Pages code site and propose table permissions for Dataverse tables accessed by the approved server logic plan. The following tables need permissions:\n>\n> [list each table with required CRUD privileges from step 6.1, grouped by server logic item]\n>\n> Context:\n> - These permissions are needed because the server logic uses `Server.Connector.Dataverse`, which respects table permissions — without them, the connector silently returns 0 records.\n> - The scope should typically be **Global** for server logic that fetches all records, unless the server logic filters by the current user (in which case use **Contact** scope).\n> - The web roles assigned to these server logic items are: [list web role names and GUIDs from Phase 5.2]\n> - Project root: [path]\n>\n> Check for existing table permissions and web roles. If new web roles are needed, create them using the create-web-role.js script. Propose a plan, then after approval create the table permission YAML files using the deterministic scripts.\"\n\nThe agent will:\n1. Discover existing table permissions and web roles\n2. Create any missing web roles via `create-web-role.js` if needed\n3. Propose a table permissions plan (with HTML visualization)\n4. Present the plan via plan mode for user approval\n5. After approval, create table permission YAML files in `.powerpages-site\u002Ftable-permissions\u002F` using `create-table-permission.js`\n\n### 6.3 Git Commit\n\nAfter table permissions (and any new web roles) are created, do a git commit for the table permissions changes.\n\n**Output**: Table permissions (and web roles if created) configured for all Dataverse tables accessed by the server logic\n\n---\n\n## Phase 7: Manage Secrets & Environment Variables\n\n**Goal**: Securely store any secret values (API keys, client secrets, connection strings) required by the server logic as environment variables in Dataverse, optionally backed by Azure Key Vault\n\n**This phase only runs when the server logic requires secret or sensitive configuration values** (identified in Phase 2.3). If no secrets are needed, skip this phase and proceed to Phase 8.\n\n**Actions**:\n\n### 7.1 Recall Key Vault Decision\n\nThe user already chose whether to use Azure Key Vault in Phase 2.3.1 (before the plan was presented). Use that decision here — do **not** re-ask.\n\n### 7.2a Azure Key Vault Path\n\nIf the user chose Azure Key Vault in Phase 2.3.1:\n\n**Step 1 — List available Key Vaults:**\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fscripts\u002Flist-azure-keyvaults.js\"\n```\n\nThe script outputs a JSON array of Key Vaults (`name`, `resourceGroup`, `location`) from the user's Azure subscription.\n\n**Step 2 — Select or create a Key Vault:**\n\nIf Key Vaults were found, present the list and ask which one to use:\n\n\u003C!-- not-a-gate: Key Vault selection — data-gathering for the secret-store call under the Phase 2.3.1 Key Vault branch -->\n\nUse `AskUserQuestion`:\n\n| Question | Context |\n|----------|---------|\n| Which Azure Key Vault would you like to use for storing secrets? | Present the names from the script output |\n\nIf **no Key Vaults are found**, ask the user how to proceed:\n\n\u003C!-- gate: add-server-logic:7.2a.no-vaults | category=plan | cancel-leaves=nothing -->\n\n> 🚦 **Gate (plan · add-server-logic:7.2a.no-vaults):** No Key Vaults found in the user's subscription — create one or fall back to plain env vars. Branches the secret-storage flow.\n>\n> **Trigger:** Phase 2.3.1 chose Key Vault but `list-azure-keyvaults.js` returned an empty list.\n> **Why we ask:** Auto-creating a Key Vault provisions Azure resources without explicit consent; auto-falling-back stores secrets as plain env vars after the user explicitly opted in to Key Vault.\n> **Cancel leaves:** Nothing — no Azure or Dataverse writes yet.\n\nUse `AskUserQuestion`:\n\n| Question | Options |\n|----------|---------|\n| No Azure Key Vaults were found in your subscription. Would you like to create one, or fall back to storing secrets directly as environment variables? | Create a new Key Vault (Recommended), Store directly as environment variable |\n\n**If \"Create a new Key Vault\"**: Ask for a vault name, resource group, and location, then create it:\n\n\u003C!-- not-a-gate: Key Vault provisioning parameters — data-gathering for the create-azure-keyvault.js call under the Phase 7.2a \"Create new\" path -->\n\nUse `AskUserQuestion`:\n\n| Question | Context |\n|----------|---------|\n| What name, resource group, and Azure region would you like for the new Key Vault? | Vault names must be 3-24 characters, globally unique, start with a letter, and contain only alphanumerics and hyphens. Suggest a name based on the project\u002Fsite name. |\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-azure-keyvault.js\" \\\n  --name \"\u003Cvault-name>\" \\\n  --resourceGroup \"\u003Cresource-group>\" \\\n  --location \"\u003Clocation>\"\n```\n\nThe script outputs a JSON object with `name`, `resourceGroup`, and `location`. Use the created vault for the remaining steps.\n\n**If \"Store directly as environment variable\"**: Skip the rest of Phase 7.2a and proceed to Phase 7.2b (direct environment variable path).\n\n**Step 3 — Provide instructions for storing each secret in Key Vault:**\n\nFor each secret identified in Phase 2.3, give the user instructions to store the value themselves. Do **not** ask for the secret value — secret values must never pass through the conversation.\n\nPresent **both** methods (CLI and Azure Portal) so the user can choose whichever they prefer:\n\n**Option A — Azure CLI (recommended for automation):**\n\nPresent the commands as a numbered list the user can copy and run. Use the stdin form so the secret value does not appear in process listings:\n\n```\nFor each secret, run the following command (replacing \u003CYOUR_SECRET_VALUE> with the actual value):\n\n1. \u003Csecret-name>:\n   printf '%s' '\u003CYOUR_SECRET_VALUE>' | node \"${PLUGIN_ROOT}\u002Fscripts\u002Fstore-keyvault-secret.js\" \\\n     --vaultName \"\u003Cselected-vault>\" \\\n     --secretName \"\u003Csecret-name>\"\n```\n\nTell the user each command outputs a JSON object with a `secretUri` and to share the output (which contains only the URI, not the secret) so the workflow can continue.\n\n**Option B — Azure Portal:**\n\nProvide these steps for each secret:\n\n```\n1. Go to the Azure Portal (https:\u002F\u002Fportal.azure.com)\n2. Search for \"Key vaults\" in the top search bar and select it\n3. Select the Key Vault: \u003Cselected-vault>\n4. In the left menu under \"Objects\", click \"Secrets\"\n5. Click \"+ Generate\u002FImport\" at the top\n6. Fill in the fields:\n   - Upload options: Manual\n   - Name: \u003Csecret-name>\n   - Secret value: paste your secret value here\n   - Leave other fields as defaults\n7. Click \"Create\"\n8. After creation, click on the secret name, then click the current version\n9. Copy the \"Secret Identifier\" URI and share it here so the workflow can continue\n```\n\nTell the user the Secret Identifier URI looks like `https:\u002F\u002F\u003Cvault-name>.vault.azure.net\u002Fsecrets\u002F\u003Csecret-name>\u002F\u003Cversion>` and that this URI (not the secret value) is what should be shared back.\n\n**Step 4 — Create environment variable in Dataverse:**\n\nAfter the user shares the `secretUri` output from each command, create an environment variable definition in Dataverse that references the Key Vault secret. Use the `secret` type:\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-environment-variable.js\" \"\u003CENV_URL>\" \\\n  --schemaName \"\u003Cprefix_SecretName>\" \\\n  --displayName \"\u003CSecret Display Name>\" \\\n  --type \"secret\" \\\n  --value \"\u003CsecretUri-from-step-3>\"\n```\n\n**Step 5 — Create site setting for the environment variable:**\n\nFor each environment variable, create a site setting YAML that maps to it:\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-site-setting.js\" \\\n  --projectRoot \"\u003CPROJECT_ROOT>\" \\\n  --name \"\u003CSiteSetting\u002FName>\" \\\n  --envVarSchema \"\u003CschemaName-from-step-4>\"\n```\n\nThis creates a site setting with `envvar_schema` and `source: 1`, which tells Power Pages to resolve the value from the Dataverse environment variable (backed by Key Vault).\n\n### 7.2b Direct Environment Variable Path\n\nIf the user chose not to use Azure Key Vault:\n\n**Step 1 — Create environment variables with placeholder values:**\n\nFor each secret identified in Phase 2.3, create the environment variable in Dataverse with a placeholder value:\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-environment-variable.js\" \"\u003CENV_URL>\" \\\n  --schemaName \"\u003Cprefix_SecretName>\" \\\n  --displayName \"\u003CSecret Display Name>\" \\\n  --value \"PLACEHOLDER_SET_ACTUAL_VALUE\"\n```\n\n**Step 2 — Create site setting for the environment variable:**\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-site-setting.js\" \\\n  --projectRoot \"\u003CPROJECT_ROOT>\" \\\n  --name \"\u003CSiteSetting\u002FName>\" \\\n  --envVarSchema \"\u003CschemaName-from-step-1>\"\n```\n\n**Step 3 — Give the user steps to set the actual secret values:**\n\nDo **not** ask for secret values — they must never pass through the conversation. Instead, tell the user to update each placeholder with the real value using one of these approaches:\n\n1. **Power Apps maker portal** ([make.powerapps.com](https:\u002F\u002Fmake.powerapps.com)) — Go to **Solutions** → **Default Solution** → **Environment variables** → find the variable by display name → update the value\n\nPresent the list of environment variables that need updating (display name and schema name for each) so the user knows exactly which ones to set.\n\n### 7.3 Verify Environment Variable Configuration\n\nAfter creating all environment variables and site settings:\n\n- Confirm each site setting YAML was created in `.powerpages-site\u002Fsite-settings\u002F`\n- Verify each YAML contains `envvar_schema` and `source: 1`\n- Confirm the server logic code references the correct site setting names via `Server.Sitesetting.Get(\"\u003CSiteSetting\u002FName>\")`\n\n### 7.4 Git Commit\n\nDo a git commit for the environment variable site setting changes.\n\n**Output**: Environment variables created in Dataverse (with or without Azure Key Vault backing), site settings configured, server logic referencing correct setting names\n\n---\n\n## Phase 8: Configure Site Settings\n\n**Goal**: Set up site settings for the server logic feature\n\n**Actions**:\n\n### 8.1 Configure Server Logic Site Settings\n\nThe `.powerpages-site` folder is guaranteed to exist at this point (verified in Phase 1.5).\n\nThe following site settings control server logic behavior. Only create settings that differ from defaults or are specifically needed:\n\n| Setting | Description | Default | When to configure |\n|---------|-------------|---------|-------------------|\n| `ServerLogic\u002FEnabled` | Enable\u002Fdisable server logic feature | `true` | Only if explicitly disabled and needs re-enabling |\n| `ServerLogic\u002FAllowedDomains` | Restrict which external domains HttpClient can call | All domains | When the server logic calls external APIs and you want to restrict to specific domains for security |\n| `ServerLogic\u002FTimeoutInSeconds` | Maximum execution time | `120` | The platform caps this at **120 seconds** — values above 120 are silently clamped. Only configure when you need to lower the timeout, not raise it. |\n| `ServerLogic\u002FAllowNetworkingToAllDomains` | Allow networking across domains | `true` | Set to `false` when restricting via AllowedDomains |\n\nUse the existing site setting creation script:\n\n```bash\nnode \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-site-setting.js\" --projectRoot \"\u003CPROJECT_ROOT>\" --name \"ServerLogic\u002FAllowedDomains\" --value \"api.example.com,api.other.com\" --description \"Restrict server logic external API calls to these domains\"\n```\n\n### 8.2 Git Commit\n\nIf any settings were created:\n\nDo a git commit for the site settings changes.\n\n**Output**: Site settings configured and committed (or skipped if not needed\u002Fdeployed)\n\n---\n\n## Phase 9: Client-Side Integration\n\n**Goal**: Help the user call the server logic endpoints from their site's frontend code, matching existing patterns discovered in Phase 1\n\nServer logic creates the backend — but without frontend code to call it, the endpoints are unused. This phase creates or updates frontend code to consume the server logic APIs, using the patterns and conventions already established in the codebase.\n\n**Actions**:\n\n### 9.1 Ask User About Integration Scope\n\n\u003C!-- gate: add-server-logic:9.1.frontend-scope | category=plan | cancel-leaves=nothing -->\n\n> 🚦 **Gate (plan · add-server-logic:9.1.frontend-scope):** Decide whether the skill also wires the server logic into the frontend UI or stops at the backend.\n>\n> **Trigger:** Phase 8 completed (server logic deployed-ready).\n> **Why we ask:** Auto-integrating mutates UI files the user wanted to handle themselves; auto-skipping leaves the endpoints unreachable from the app.\n> **Cancel leaves:** Nothing — server logic backend is already on disk; this prompt only decides frontend follow-through.\n\nUse `AskUserQuestion`:\n\n| Question | Options |\n|----------|---------|\n| I've created the server logic backend. Would you like me to also fully integrate it into the frontend UI? | Yes, fully integrate it into the UI (Recommended), No, I'll handle the frontend myself |\n\n**If \"No\"**: Skip to Phase 10, but provide the API URL and a code snippet the user can copy.\n\n### 9.2 Follow the Frontend Integration Reference\n\nUse the reference below for the frontend integration approach, examples, and framework-specific patterns:\n\n> Reference: `${PLUGIN_ROOT}\u002Fskills\u002Fadd-server-logic\u002Freferences\u002Ffrontend-integration-reference.md`\n\nBased on the Explore agent's findings from Phase 1.4 and the approved plan, choose the integration approach from that reference and apply it consistently across all server logic endpoints being wired into the frontend.\n\n### 9.3 Create or Update Frontend Integration\n\nFollowing the reference:\n\n- Reuse the existing service layer or API utility when the site already has one\n- Create a lightweight CSRF-aware helper only when the site has no established API client pattern\n- Group multiple server logic endpoints into a coherent service module when that improves maintainability\n- Add framework-specific hooks\u002Fcomposables\u002Fservices only when the codebase already follows that pattern\n- Fully integrate the server logic into the actual UI flow — do **not** stop at creating service\u002Fhelper code\n- Update the relevant pages, components, forms, buttons, or user journeys so the new backend behavior is reachable from the interface\n- Replace placeholder data, mock handlers, or temporary actions when they are meant to be backed by the new server logic endpoints\n- Add or preserve loading, success, empty, and error states so the UI behaves like a finished feature\n- **For validate-and-execute endpoints**: The frontend must call the server logic endpoint for the protected operation (e.g., status transition) — it must NOT make a separate Web API PATCH for the same field. Ensure the UI for that operation (e.g., a \"Submit\" or \"Approve\" button) calls the server logic service function, not the Web API service\n- **For Dataverse-backed endpoints**: Match the frontend parsing to the response shape chosen in Phase 5.3. See \"Dataverse Connector Response Format\" in the frontend integration reference for the exact parsing per shape.\n- **If the response shape is unclear**: Do not guess. After the site is deployed, invoke `\u002Ftest-site` against the live site so the actual server logic response can be captured from the network tab and used to drive the integration\n\n### 9.4 Git Commit\n\nIf frontend integration code was created:\n\nDo a git commit for the frontend integration changes.\n\n**Output**: Frontend service\u002Fhook created as needed, UI components\u002Fpages fully integrated, and changes committed\n\n---\n\n## Phase 10: Verify & Test Guidance\n\n**Goal**: Validate the code and provide the user with everything needed to test the server logic\n\n**Actions**:\n\n### 10.1 Final Code Validation\n\nRe-read each created `.js` file and verify:\n\n- [ ] Only allowed top-level functions (get, post, put, patch, del)\n- [ ] Every function returns a string\n- [ ] try\u002Fcatch in every function\n- [ ] Server.Logger calls in every function\n- [ ] No `import`, `require`, or external dependencies\n- [ ] No browser APIs (`fetch`, `XMLHttpRequest`, `setTimeout`, `console.log`, `document`, `window`)\n- [ ] Async only on functions that use await\n- [ ] Correct SDK method usage (verified against Phase 3 documentation)\n- [ ] HttpClient used only for external APIs (not Dataverse)\n- [ ] Dataverse connector used for Dataverse operations\n\nRe-read each `.serverlogic.yml` file and verify:\n\n- [ ] `id` field exists and is a valid UUID\n- [ ] `adx_serverlogic_adx_webrole` array is non-empty (at least one web role)\n- [ ] `name` matches the folder name and `.js` file name\n- [ ] `display_name` and `description` are populated\n- [ ] Fields are alphabetically sorted\n- [ ] File names match: folder name, `.js` name, `.serverlogic.yml` name, and `name` field all use the same value\n\n### 10.2 Provide API URL\n\nTell the user each endpoint URL:\n\n```\nhttps:\u002F\u002F\u003Csite-url>\u002F_api\u002Fserverlogics\u002F\u003Cserver-logic-name>\n```\n\n### 10.3 Test Guidance\n\nProvide testing instructions:\n\n1. **Deploy the site first** — The server logic must be deployed via `\u002Fdeploy-site` before it can be called\n2. **CSRF token required for non-GET requests** — POST, PUT, PATCH, and DELETE calls to server logic endpoints require a CSRF token. Fetch the token from `\u002F_layout\u002Ftokenhtml` and include it as `__RequestVerificationToken` header. GET requests are **exempt** from antiforgery validation — no token is needed for read-only calls.\n3. **Authentication** — Server logic respects the site's authentication. Calls from authenticated sessions use cookie-based auth automatically. Anonymous access depends on governance settings.\n4. **Testing from browser console**:\n\nUse the frontend integration reference from Phase 9 for the exact calling pattern that matches the site's stack.\n\n5. **Check diagnostics** — Server.Logger output can be viewed in Power Pages design studio diagnostics\n6. **If the endpoint returns an error or unexpected response** — see [Troubleshooting Server Logic Execution Errors](#troubleshooting-server-logic-execution-errors) for the Playwright + `X-Ms-UserTrace` debugging flow\n\n**Output**: Code validated, API URL provided, test guidance given\n\n---\n\n## Phase 11: Review & Deploy\n\n**Goal**: Present a summary of all work performed and offer deployment\n\n**Actions**:\n\n### 11.1 Record Skill Usage\n\n> Reference: `${PLUGIN_ROOT}\u002Freferences\u002Fskill-tracking-reference.md`\n\nFollow the skill tracking instructions in the reference to record this skill's usage. Use `--skillName \"AddServerLogic\"`.\n\n### 11.2 Present Summary\n\nPresent a summary of everything that was done:\n\n| Step | Status | Details |\n|------|--------|---------|\n| Server Logic JS | Created | List each created `.powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F\u003Cname>.js` file |\n| Server Logic YAML | Created | List each created `.powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F\u003Cname>.serverlogic.yml` file |\n| HTML Plan | Created\u002FUpdated | Actual path from render script output |\n| Functions | Implemented | Summarize methods implemented per server logic item |\n| SDK Features Used | — | Summarize features used per server logic item |\n| Table Permissions | Created\u002FSkipped | `accounts` (Read), `contacts` (Read, Create), etc. |\n| Secrets & Env Vars | Created\u002FSkipped | Environment variables (Key Vault-backed or direct), site settings with `envvar_schema` |\n| Site Settings | Created\u002FSkipped | ServerLogic\u002FAllowedDomains, etc. |\n| Client-Side Service | Created\u002FSkipped | List created or updated frontend service files |\n| UI Integration | Created\u002FSkipped | Pages, components, forms, or actions fully wired to the server logic endpoints |\n| API URL | — | List each `\u002F_api\u002Fserverlogics\u002F\u003Cname>` URL |\n\n### 11.3 Ask to Deploy\n\n\u003C!-- gate: add-server-logic:11.3.deploy | category=plan | cancel-leaves=nothing -->\n\n> 🚦 **Gate (plan · add-server-logic:11.3.deploy):** Post-implementation deploy prompt — server logic endpoints aren't reachable until deployed.\n>\n> **Trigger:** All server logic artifacts written and committed.\n> **Why we ask:** Auto-deploy picks wrong env.\n> **Cancel leaves:** Nothing — artifacts stay on disk; no deploy fired.\n\nUse `AskUserQuestion`:\n\n| Question | Options |\n|----------|---------|\n| The server logic work is ready. To make it live, the site needs to be deployed. Would you like to deploy now? | Yes, deploy now (Recommended), No, I'll deploy later |\n\n\u003C!-- gate: add-server-logic:11.3.test | category=plan | cancel-leaves=nothing -->\n\n> 🚦 **Gate (plan · add-server-logic:11.3.test):** Post-deploy validation prompt — invokes `\u002Ftest-site` to exercise the new endpoints live.\n>\n> **Trigger:** Deploy from the previous gate succeeded.\n> **Why we ask:** Skipping is harmless (manual test still possible); auto-invoking `\u002Ftest-site` adds runtime.\n> **Cancel leaves:** Nothing — deploy has already completed.\n\n**If \"Yes, deploy now\"**: Invoke the `\u002Fdeploy-site` skill to deploy the site.\n\nAfter deployment succeeds, use `AskUserQuestion`:\n\n| Question | Options |\n|----------|---------|\n| The site has been deployed. Would you like me to run `\u002Ftest-site` to validate it now? | Yes, run `\u002Ftest-site` (Recommended), No, skip testing |\n\n**If \"Yes, run `\u002Ftest-site`\"**: Invoke the `\u002Ftest-site` skill.\n\n**If \"No, I'll deploy later\"**: Acknowledge and remind:\n\n> \"No problem! Remember to deploy your site using `\u002Fdeploy-site` when you're ready. The server logic endpoints won't be accessible until the site is deployed.\"\n\n### 11.4 Post-Deploy Notes\n\nAfter deployment (or if skipped), remind the user:\n\n- **Test the endpoints**: Call each `\u002F_api\u002Fserverlogics\u002F\u003Cname>` URL with the appropriate HTTP method (include CSRF token for non-GET requests)\n- **Recommended full-site validation**: After deployment, ask whether to run `\u002Ftest-site` so the live site can be validated end to end\n- **Check logs**: Use Server.Logger output in Power Pages design studio diagnostics to debug issues\n- **Table permissions**: Table permissions were configured for Dataverse tables used by this server logic. If you add new Dataverse tables later, run the table permissions setup again — without permissions, `Server.Connector.Dataverse` silently returns 0 records\n- **Timeout**: Default execution timeout is 120 seconds — this is also the platform maximum (values above 120 are silently clamped)\n- **Anonymous access**: If the site's governance control disables anonymous access, anonymous users cannot invoke server logic that integrates with external systems\n- **Preview feature**: Server Logic is currently in preview — monitor Microsoft Learn for updates\n- **Environment variables with placeholder values**: If Phase 7 created environment variables with placeholder values, remind the user to update them with the actual secret values before testing. They can do this via:\n  1. **Power Platform admin center** — **Environments** → select environment → **Environment variables** → find by display name → update value\n  2. **Power Apps maker portal** — **Solutions** → open solution → **Environment variables** → edit value\n\n**Output**: Summary presented, deployment completed or deferred, post-deploy guidance provided\n\n---\n\n## Troubleshooting Server Logic Execution Errors\n\nWhen a deployed server logic endpoint returns an error or unexpected response, the underlying cause is usually hidden inside the `X-Ms-UserTrace` response header — a base64-encoded blob containing the runtime diagnostic logs. The Power Pages Edge browser extension shows the same data, but inspecting the response header is the fastest path when iterating against a live site.\n\nUse this flow whenever a server logic call fails or returns a different response than expected:\n\n### 1. Open the Live Site in a Browser via Playwright\n\nUse the Playwright MCP tools to drive the site:\n\n1. Navigate to the deployed site URL (the `websiteUrl` returned by `\u002Factivate-site` or shown in the Power Pages admin center).\n2. Ask the user to sign in if the endpoint requires authentication and wait for confirmation.\n3. Trigger the action that calls the failing server logic endpoint (click the button, submit the form, etc.) — or call the endpoint directly with `fetch()`.\n\n### 2. Capture the Network Response\n\nUse `mcp__plugin_power-pages_playwright__browser_network_requests` to list network activity, then locate the request to `\u002F_api\u002Fserverlogics\u002F\u003Cname>`. Note:\n\n- The HTTP status code (e.g., 200, 400, 500)\n- The response body (often a generic error or empty payload when validation fails)\n- **Most importantly: the `X-Ms-UserTrace` response header** — this is where the actual diagnostic logs live\n\nIf `browser_network_requests` does not surface the response headers directly, fall back to `mcp__plugin_power-pages_playwright__browser_evaluate` and read the headers from a `fetch()` call:\n\n```javascript\nconst res = await fetch('\u002F_api\u002Fserverlogics\u002F\u003Cname>', { method: 'GET', credentials: 'include' });\nconst trace = res.headers.get('X-Ms-UserTrace');\nreturn { status: res.status, body: await res.text(), trace };\n```\n\n### 3. Decode the `X-Ms-UserTrace` Header\n\nThe header value is base64-encoded JSON. Decode it.\n\nThe decoded payload contains the diagnostic log entries — including the actual error message, the prohibited pattern (if script validation failed).\n\nAfter fixing, redeploy via `\u002Fdeploy-site` and restart the site so the change is picked up immediately.\n\n---\n\n## Important Notes\n\n### Throughout All Phases\n\n- **Use TaskCreate\u002FTaskUpdate** to track progress at every phase\n- **Always fetch Microsoft Learn docs** in Phase 3 before writing code — the docs are the source of truth\n- **Ask for user confirmation** at key decision points\n- **Commit at milestones** — after server logic code, table permissions (if any), secrets\u002Fenvironment variables (if any), site settings, and frontend integration (if any)\n- **Validate thoroughly** — server logic has strict constraints and violations cause runtime errors\n\n### Key Decision Points (Wait for User)\n\n1. At Phase 1.5: Deploy now or cancel (if `.powerpages-site` missing — mandatory)\n2. At Phase 2.1.2: Use existing Dataverse custom actions or build from scratch (if custom actions found)\n3. At Phase 2: Confirm requirements (purpose, name, HTTP methods, secrets)\n4. At Phase 4: Approve implementation plan before writing code\n5. At Phase 6.2: Review and approve the `table-permissions-architect` plan (if Dataverse connector is used)\n6. At Phase 2.3.1: Choose Azure Key Vault or direct environment variable (if secrets needed)\n7. At Phase 7.2a Step 2: Create a new Key Vault or fall back to direct environment variable (if no vaults found)\n8. At Phase 9.1: Create frontend integration or skip\n9. At Phase 11.3: Deploy now or deploy later\n\n### SDK Pattern Source of Truth\n\nDo not treat this skill file as the canonical SDK reference. The Phase 3 Microsoft Learn fetch is the source of truth for SDK usage patterns, supported methods, signatures, and connector behavior. Keep only task-specific decisions in the plan and implementation notes.\n\n### Progress Tracking\n\nBefore starting Phase 1, create a task list with all phases using `TaskCreate`:\n\n| Task subject | activeForm | Description |\n|-------------|------------|-------------|\n| Verify site exists | Verifying site prerequisites | Locate project root, detect framework, explore existing server logics and frontend patterns, verify .powerpages-site exists (mandatory) |\n| Understand requirements | Gathering requirements | Determine user intent, whether one or more server logic files are needed, the methods\u002Ffeatures for each item, discover Dataverse custom actions, and any secrets required |\n| Fetch latest documentation | Fetching Microsoft Learn docs | Query Microsoft Learn for current Server Logic SDK reference and samples |\n| Review implementation plan | Reviewing plan with user | Present plan (server logic inventory, functions, SDK features, external APIs, secrets) and confirm before writing code |\n| Implement server logic | Writing server logic code | Determine\u002Fcreate required web roles, create approved `.js` and `.serverlogic.yml` files, validate code |\n| Configure table permissions | Setting up Dataverse table permissions | (Conditional) Parse `.js` files for Dataverse tables, launch `table-permissions-architect`, create permission YAML files |\n| Manage secrets and environment variables | Configuring secrets and env vars | (Conditional) Recommend Azure Key Vault, list vaults, store secrets, create environment variables in Dataverse, create site settings with envvar_schema |\n| Configure site settings | Configuring site settings | Set up ServerLogic\u002F* site settings if needed |\n| Client-side integration | Wiring frontend to server logic | Follow the frontend integration reference, create\u002Fupdate service files as needed, and fully wire the UI to the server logic endpoints |\n| Verify and test guidance | Validating and providing test guidance | Final validation, API URLs, CSRF token instructions, testing guide |\n| Review and deploy | Reviewing summary and deploying | Present summary, ask about deployment, provide post-deploy guidance |\n\nMark each task `in_progress` when starting it and `completed` when done via `TaskUpdate`. Use `TaskList` between phase transitions and before the final summary to confirm there are no incomplete work items left.\n\n---\n\n**Begin with Phase 1: Verify Site Exists**\n",{"data":41,"body":45},{"name":4,"description":6,"user-invocable":42,"allowed-tools":43,"model":44},true,"Read, Write, Edit, Bash, Grep, Glob, AskUserQuestion, Skill, Task, TaskCreate, TaskUpdate, TaskList, mcp__plugin_power-pages_microsoft-learn__microsoft_docs_search, mcp__plugin_power-pages_microsoft-learn__microsoft_code_sample_search, mcp__plugin_power-pages_microsoft-learn__microsoft_docs_fetch","opus",{"type":46,"children":47},"root",[48,75,81,86,93,223,270,280,284,290,440,443,449,459,469,486,493,506,524,530,542,548,568,574,602,610,721,726,769,775,787,809,824,892,904,952,970,986,1003,1006,1012,1021,1029,1035,1040,1114,1119,1124,1142,1148,1160,1172,1259,1264,1297,1315,1321,1326,1334,1400,1405,1441,1565,1573,1586,1627,1637,1678,1696,1708,1716,1727,1738,1787,1792,1838,1843,1849,1854,2034,2040,2045,2119,2124,2203,2208,2214,2219,2254,2264,2297,2302,2308,2320,2418,2427,2430,2436,2445,2450,2458,2464,2469,2483,2488,2511,2517,2522,2555,2564,2567,2573,2582,2590,2596,2601,2614,2619,2687,2693,2698,2703,2713,2726,2738,2809,2844,2850,2860,2865,2893,2898,2904,2952,2962,2995,3005,3014,3023,3026,3032,3048,3056,3062,3067,3146,3152,3163,3173,3178,3276,3287,3305,3323,3329,3361,3368,3585,3591,3604,3703,3720,3840,3864,3870,4426,4432,4437,6009,6017,6058,6064,6085,6093,6813,6821,7580,7588,8254,8262,8361,8367,8422,8450,8456,8468,8538,8543,8549,8559,8565,8597,8722,8735,8857,8865,8984,8990,8995,9186,9192,9197,9202,9224,9227,9233,9249,9272,9289,9297,9303,9315,9421,9426,9517,9523,9551,9559,9639,9644,9694,9700,9705,9714,9717,9723,9732,9742,9750,9756,9767,9773,9778,9786,9821,9847,9855,9860,9870,9903,9915,9958,9968,10001,10011,10021,10054,10165,10189,10199,10207,10218,10230,10238,10243,10252,10265,10273,10278,10287,10300,10308,10328,10474,10482,10487,10595,10615,10621,10626,10634,10639,10755,10763,10867,10875,10885,10926,10931,10937,10942,10983,10989,10994,11003,11006,11012,11021,11029,11035,11046,11051,11217,11222,11323,11329,11334,11339,11348,11351,11357,11366,11371,11379,11385,11420,11430,11463,11473,11479,11484,11496,11501,11507,11512,11599,11605,11610,11615,11624,11627,11633,11642,11650,11656,11668,11815,11826,11942,11948,11953,11962,11968,11973,12044,12049,12088,12097,12100,12106,12115,12123,12129,12142,12154,12160,12165,12421,12427,12462,12472,12505,12554,12570,12581,12628,12650,12660,12675,12681,12686,12835,12844,12847,12852,12864,12869,12875,12880,12921,12927,12946,12976,13003,13264,13277,13282,13287,13299,13302,13308,13314,13366,13372,13434,13440,13445,13450,13462,13713,13750,13753,13761],{"type":49,"tag":50,"props":51,"children":52},"element","blockquote",{},[53],{"type":49,"tag":54,"props":55,"children":56},"p",{},[57,64,66,73],{"type":49,"tag":58,"props":59,"children":60},"strong",{},[61],{"type":62,"value":63},"text","Plugin check",{"type":62,"value":65},": Run ",{"type":49,"tag":67,"props":68,"children":70},"code",{"className":69},[],[71],{"type":62,"value":72},"node \"${PLUGIN_ROOT}\u002Fscripts\u002Fcheck-version.js\"",{"type":62,"value":74}," — if it outputs a message, show it to the user before proceeding.",{"type":49,"tag":76,"props":77,"children":78},"h1",{"id":4},[79],{"type":62,"value":80},"Add Server Logic",{"type":49,"tag":54,"props":82,"children":83},{},[84],{"type":62,"value":85},"Create and manage one or more Power Pages Server Logic files — server-side JavaScript that runs securely on the Power Pages runtime, hidden from the browser and protected by web roles and table permissions. Server Logic enables secure external API integrations, Dataverse operations, and custom business logic without exposing sensitive code or credentials to the client.",{"type":49,"tag":87,"props":88,"children":90},"h2",{"id":89},"core-principles",[91],{"type":62,"value":92},"Core Principles",{"type":49,"tag":94,"props":95,"children":96},"ul",{},[97,108,141,195,213],{"type":49,"tag":98,"props":99,"children":100},"li",{},[101,106],{"type":49,"tag":58,"props":102,"children":103},{},[104],{"type":62,"value":105},"Microsoft Learn is the source of truth",{"type":62,"value":107},": Always fetch the latest documentation before writing code. The Server Logic feature is in preview and the SDK may change — never rely on cached knowledge alone.",{"type":49,"tag":98,"props":109,"children":110},{},[111,116,118,124,126,132,133,139],{"type":49,"tag":58,"props":112,"children":113},{},[114],{"type":62,"value":115},"No browser APIs, no dependencies",{"type":62,"value":117},": Server Logic runs in a sandboxed server environment with ECMAScript 2023 support. There is no ",{"type":49,"tag":67,"props":119,"children":121},{"className":120},[],[122],{"type":62,"value":123},"fetch",{"type":62,"value":125},", ",{"type":49,"tag":67,"props":127,"children":129},{"className":128},[],[130],{"type":62,"value":131},"XMLHttpRequest",{"type":62,"value":125},{"type":49,"tag":67,"props":134,"children":136},{"className":135},[],[137],{"type":62,"value":138},"setTimeout",{"type":62,"value":140},", or any DOM API. No npm packages are available.",{"type":49,"tag":98,"props":142,"children":143},{},[144,149,151,157,158,164,165,171,172,178,179,185,187,193],{"type":49,"tag":58,"props":145,"children":146},{},[147],{"type":62,"value":148},"Five functions only",{"type":62,"value":150},": A server logic file can only export these top-level functions: ",{"type":49,"tag":67,"props":152,"children":154},{"className":153},[],[155],{"type":62,"value":156},"get",{"type":62,"value":125},{"type":49,"tag":67,"props":159,"children":161},{"className":160},[],[162],{"type":62,"value":163},"post",{"type":62,"value":125},{"type":49,"tag":67,"props":166,"children":168},{"className":167},[],[169],{"type":62,"value":170},"put",{"type":62,"value":125},{"type":49,"tag":67,"props":173,"children":175},{"className":174},[],[176],{"type":62,"value":177},"patch",{"type":62,"value":125},{"type":49,"tag":67,"props":180,"children":182},{"className":181},[],[183],{"type":62,"value":184},"del",{"type":62,"value":186},". The name ",{"type":49,"tag":67,"props":188,"children":190},{"className":189},[],[191],{"type":62,"value":192},"delete",{"type":62,"value":194}," is a reserved word in JavaScript and cannot be used.",{"type":49,"tag":98,"props":196,"children":197},{},[198,203,205,211],{"type":49,"tag":58,"props":199,"children":200},{},[201],{"type":62,"value":202},"Always return a string",{"type":62,"value":204},": Every function must return a string. Use ",{"type":49,"tag":67,"props":206,"children":208},{"className":207},[],[209],{"type":62,"value":210},"JSON.stringify()",{"type":62,"value":212}," when returning objects or arrays.",{"type":49,"tag":98,"props":214,"children":215},{},[216,221],{"type":49,"tag":58,"props":217,"children":218},{},[219],{"type":62,"value":220},"Use TaskCreate\u002FTaskUpdate",{"type":62,"value":222},": Track all progress throughout all phases — create the todo list upfront with all phases before starting any work.",{"type":49,"tag":50,"props":224,"children":225},{},[226,234],{"type":49,"tag":54,"props":227,"children":228},{},[229],{"type":49,"tag":58,"props":230,"children":231},{},[232],{"type":62,"value":233},"Prerequisites:",{"type":49,"tag":94,"props":235,"children":236},{},[237,242],{"type":49,"tag":98,"props":238,"children":239},{},[240],{"type":62,"value":241},"An existing Power Pages code site created",{"type":49,"tag":98,"props":243,"children":244},{},[245,247,252,254,260,262,268],{"type":62,"value":246},"The site ",{"type":49,"tag":58,"props":248,"children":249},{},[250],{"type":62,"value":251},"must",{"type":62,"value":253}," be deployed at least once (",{"type":49,"tag":67,"props":255,"children":257},{"className":256},[],[258],{"type":62,"value":259},".powerpages-site",{"type":62,"value":261}," folder must exist) — server logic files live inside ",{"type":49,"tag":67,"props":263,"children":265},{"className":264},[],[266],{"type":62,"value":267},".powerpages-site\u002Fserver-logic\u002F",{"type":62,"value":269},", so deployment is required before any server logic can be created",{"type":49,"tag":54,"props":271,"children":272},{},[273,278],{"type":49,"tag":58,"props":274,"children":275},{},[276],{"type":62,"value":277},"Initial request:",{"type":62,"value":279}," $ARGUMENTS",{"type":49,"tag":281,"props":282,"children":283},"hr",{},[],{"type":49,"tag":87,"props":285,"children":287},{"id":286},"workflow",[288],{"type":62,"value":289},"Workflow",{"type":49,"tag":291,"props":292,"children":293},"ol",{},[294,304,314,324,334,366,384,400,410,420,430],{"type":49,"tag":98,"props":295,"children":296},{},[297,302],{"type":49,"tag":58,"props":298,"children":299},{},[300],{"type":62,"value":301},"Verify Site Exists",{"type":62,"value":303}," — Locate the Power Pages project, explore existing patterns, and verify prerequisites",{"type":49,"tag":98,"props":305,"children":306},{},[307,312],{"type":49,"tag":58,"props":308,"children":309},{},[310],{"type":62,"value":311},"Understand Requirements",{"type":62,"value":313}," — Determine the user intent and whether the solution needs one or more server logic files",{"type":49,"tag":98,"props":315,"children":316},{},[317,322],{"type":49,"tag":58,"props":318,"children":319},{},[320],{"type":62,"value":321},"Fetch Latest Documentation",{"type":62,"value":323}," — Query Microsoft Learn for the most current Server Logic SDK reference",{"type":49,"tag":98,"props":325,"children":326},{},[327,332],{"type":49,"tag":58,"props":328,"children":329},{},[330],{"type":62,"value":331},"Review Implementation Plan",{"type":62,"value":333}," — Present the plan to the user and confirm before writing code",{"type":49,"tag":98,"props":335,"children":336},{},[337,342,344,350,352,358,360],{"type":49,"tag":58,"props":338,"children":339},{},[340],{"type":62,"value":341},"Implement Server Logic",{"type":62,"value":343}," — Create the approved ",{"type":49,"tag":67,"props":345,"children":347},{"className":346},[],[348],{"type":62,"value":349},".js",{"type":62,"value":351}," and ",{"type":49,"tag":67,"props":353,"children":355},{"className":354},[],[356],{"type":62,"value":357},".serverlogic.yml",{"type":62,"value":359}," files in ",{"type":49,"tag":67,"props":361,"children":363},{"className":362},[],[364],{"type":62,"value":365},".powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F",{"type":49,"tag":98,"props":367,"children":368},{},[369,374,376,382],{"type":49,"tag":58,"props":370,"children":371},{},[372],{"type":62,"value":373},"Configure Table Permissions",{"type":62,"value":375}," — ",{"type":49,"tag":377,"props":378,"children":379},"em",{},[380],{"type":62,"value":381},"(Conditional: only if Server.Connector.Dataverse is used)",{"type":62,"value":383}," Set up table permissions for Dataverse tables accessed by the server logic",{"type":49,"tag":98,"props":385,"children":386},{},[387,392,393,398],{"type":49,"tag":58,"props":388,"children":389},{},[390],{"type":62,"value":391},"Manage Secrets & Environment Variables",{"type":62,"value":375},{"type":49,"tag":377,"props":394,"children":395},{},[396],{"type":62,"value":397},"(Conditional: only if the server logic requires secrets)",{"type":62,"value":399}," Store sensitive values securely using Azure Key Vault (recommended) or direct environment variables in Dataverse",{"type":49,"tag":98,"props":401,"children":402},{},[403,408],{"type":49,"tag":58,"props":404,"children":405},{},[406],{"type":62,"value":407},"Configure Site Settings",{"type":62,"value":409}," — Set up ServerLogic site settings if needed",{"type":49,"tag":98,"props":411,"children":412},{},[413,418],{"type":49,"tag":58,"props":414,"children":415},{},[416],{"type":62,"value":417},"Client-Side Integration",{"type":62,"value":419}," — Help wire the server logic into the site's frontend code",{"type":49,"tag":98,"props":421,"children":422},{},[423,428],{"type":49,"tag":58,"props":424,"children":425},{},[426],{"type":62,"value":427},"Verify & Test Guidance",{"type":62,"value":429}," — Validate the code and provide testing instructions",{"type":49,"tag":98,"props":431,"children":432},{},[433,438],{"type":49,"tag":58,"props":434,"children":435},{},[436],{"type":62,"value":437},"Review & Deploy",{"type":62,"value":439}," — Present summary and offer deployment",{"type":49,"tag":281,"props":441,"children":442},{},[],{"type":49,"tag":87,"props":444,"children":446},{"id":445},"phase-1-verify-site-exists",[447],{"type":62,"value":448},"Phase 1: Verify Site Exists",{"type":49,"tag":54,"props":450,"children":451},{},[452,457],{"type":49,"tag":58,"props":453,"children":454},{},[455],{"type":62,"value":456},"Goal",{"type":62,"value":458},": Locate the Power Pages project root and confirm prerequisites",{"type":49,"tag":54,"props":460,"children":461},{},[462,467],{"type":49,"tag":58,"props":463,"children":464},{},[465],{"type":62,"value":466},"Actions",{"type":62,"value":468},":",{"type":49,"tag":291,"props":470,"children":471},{},[472],{"type":49,"tag":98,"props":473,"children":474},{},[475,477,484],{"type":62,"value":476},"Create todo list with all 11 phases (see ",{"type":49,"tag":478,"props":479,"children":481},"a",{"href":480},"#progress-tracking",[482],{"type":62,"value":483},"Progress Tracking",{"type":62,"value":485}," table)",{"type":49,"tag":487,"props":488,"children":490},"h3",{"id":489},"_11-locate-project",[491],{"type":62,"value":492},"1.1 Locate Project",{"type":49,"tag":54,"props":494,"children":495},{},[496,498,504],{"type":62,"value":497},"Look for ",{"type":49,"tag":67,"props":499,"children":501},{"className":500},[],[502],{"type":62,"value":503},"powerpages.config.json",{"type":62,"value":505}," in the current directory or immediate subdirectories",{"type":49,"tag":54,"props":507,"children":508},{},[509,514,516,522],{"type":49,"tag":58,"props":510,"children":511},{},[512],{"type":62,"value":513},"If not found",{"type":62,"value":515},": Tell the user to create a site first with ",{"type":49,"tag":67,"props":517,"children":519},{"className":518},[],[520],{"type":62,"value":521},"\u002Fcreate-site",{"type":62,"value":523},".",{"type":49,"tag":487,"props":525,"children":527},{"id":526},"_12-read-existing-config",[528],{"type":62,"value":529},"1.2 Read Existing Config",{"type":49,"tag":54,"props":531,"children":532},{},[533,535,540],{"type":62,"value":534},"Read ",{"type":49,"tag":67,"props":536,"children":538},{"className":537},[],[539],{"type":62,"value":503},{"type":62,"value":541}," to get the site name and configuration:",{"type":49,"tag":487,"props":543,"children":545},{"id":544},"_13-detect-framework",[546],{"type":62,"value":547},"1.3 Detect Framework",{"type":49,"tag":54,"props":549,"children":550},{},[551,552,558,560,566],{"type":62,"value":534},{"type":49,"tag":67,"props":553,"children":555},{"className":554},[],[556],{"type":62,"value":557},"package.json",{"type":62,"value":559}," to determine the frontend framework (React, Vue, Angular, or Astro). This is needed for Phase 8 (client-side integration guidance). See ",{"type":49,"tag":67,"props":561,"children":563},{"className":562},[],[564],{"type":62,"value":565},"${PLUGIN_ROOT}\u002Freferences\u002Fframework-conventions.md",{"type":62,"value":567}," for the full framework detection mapping.",{"type":49,"tag":487,"props":569,"children":571},{"id":570},"_14-explore-existing-server-logic-and-frontend-code",[572],{"type":62,"value":573},"1.4 Explore Existing Server Logic and Frontend Code",{"type":49,"tag":54,"props":575,"children":576},{},[577,579,584,586,592,594,600],{"type":62,"value":578},"Use the ",{"type":49,"tag":58,"props":580,"children":581},{},[582],{"type":62,"value":583},"Explore agent",{"type":62,"value":585}," (via ",{"type":49,"tag":67,"props":587,"children":589},{"className":588},[],[590],{"type":62,"value":591},"Task",{"type":62,"value":593}," tool with ",{"type":49,"tag":67,"props":595,"children":597},{"className":596},[],[598],{"type":62,"value":599},"agent_type: \"explore\"",{"type":62,"value":601},") to analyze the site for existing server logic patterns and frontend code that may call or need to call server logic endpoints.",{"type":49,"tag":54,"props":603,"children":604},{},[605],{"type":49,"tag":58,"props":606,"children":607},{},[608],{"type":62,"value":609},"Prompt for the Explore agent:",{"type":49,"tag":50,"props":611,"children":612},{},[613,618],{"type":49,"tag":54,"props":614,"children":615},{},[616],{"type":62,"value":617},"\"Analyze this Power Pages code site for server logic context. Check:",{"type":49,"tag":291,"props":619,"children":620},{},[621,633,654,674,679,684,704,716],{"type":49,"tag":98,"props":622,"children":623},{},[624,626,631],{"type":62,"value":625},"Does ",{"type":49,"tag":67,"props":627,"children":629},{"className":628},[],[630],{"type":62,"value":267},{"type":62,"value":632}," exist? If yes, list all subdirectories and their .js files. Summarize what each server logic does (which functions it implements, what SDK features it uses). Also read the corresponding .serverlogic.yml files to check web role assignments.",{"type":49,"tag":98,"props":634,"children":635},{},[636,638,644,646,652],{"type":62,"value":637},"Search the frontend source code (",{"type":49,"tag":67,"props":639,"children":641},{"className":640},[],[642],{"type":62,"value":643},"src\u002F**\u002F*.{ts,tsx,js,jsx,vue,astro}",{"type":62,"value":645},") for any existing calls to ",{"type":49,"tag":67,"props":647,"children":649},{"className":648},[],[650],{"type":62,"value":651},"\u002F_api\u002Fserverlogics\u002F",{"type":62,"value":653}," — these indicate server logic endpoints already being consumed.",{"type":49,"tag":98,"props":655,"children":656},{},[657,659,665,666,672],{"type":62,"value":658},"Look for CSRF token handling patterns (",{"type":49,"tag":67,"props":660,"children":662},{"className":661},[],[663],{"type":62,"value":664},"__RequestVerificationToken",{"type":62,"value":125},{"type":49,"tag":67,"props":667,"children":669},{"className":668},[],[670],{"type":62,"value":671},"_layout\u002Ftokenhtml",{"type":62,"value":673},") — these show how the site currently makes authenticated API calls.",{"type":49,"tag":98,"props":675,"children":676},{},[677],{"type":62,"value":678},"Check for any TODO\u002FFIXME comments mentioning server logic, backend, or server-side processing.",{"type":49,"tag":98,"props":680,"children":681},{},[682],{"type":62,"value":683},"Look for hardcoded API URLs, mock data, or placeholder fetch calls that might need to be replaced with server logic calls.",{"type":49,"tag":98,"props":685,"children":686},{},[687,689,695,696,702],{"type":62,"value":688},"Check for any existing service layer or API utility files in ",{"type":49,"tag":67,"props":690,"children":692},{"className":691},[],[693],{"type":62,"value":694},"src\u002Fshared\u002F",{"type":62,"value":125},{"type":49,"tag":67,"props":697,"children":699},{"className":698},[],[700],{"type":62,"value":701},"src\u002Fservices\u002F",{"type":62,"value":703},", or similar directories that could be reused for server logic integration.",{"type":49,"tag":98,"props":705,"children":706},{},[707,708,714],{"type":62,"value":534},{"type":49,"tag":67,"props":709,"children":711},{"className":710},[],[712],{"type":62,"value":713},".powerpages-site\u002Fweb-roles\u002F*.webrole.yml",{"type":62,"value":715}," files to list available web roles and their GUIDs — these are needed when creating the server logic metadata YAML.",{"type":49,"tag":98,"props":717,"children":718},{},[719],{"type":62,"value":720},"For each existing server logic, assess whether it can be reused or safely extended for the requested capability instead of creating a brand-new server logic file. Call out any strong reuse candidates and explain why.\nReport all findings so we can avoid duplicating work and match existing patterns.\"",{"type":49,"tag":54,"props":722,"children":723},{},[724],{"type":62,"value":725},"From the Explore agent's findings, note:",{"type":49,"tag":94,"props":727,"children":728},{},[729,739,749,759],{"type":49,"tag":98,"props":730,"children":731},{},[732,737],{"type":49,"tag":58,"props":733,"children":734},{},[735],{"type":62,"value":736},"Existing server logic files",{"type":62,"value":738}," — what's already implemented, and which ones are candidates for reuse or extension",{"type":49,"tag":98,"props":740,"children":741},{},[742,747],{"type":49,"tag":58,"props":743,"children":744},{},[745],{"type":62,"value":746},"Frontend calling patterns",{"type":62,"value":748}," — how the site makes API calls (match this pattern in Phase 9)",{"type":49,"tag":98,"props":750,"children":751},{},[752,757],{"type":49,"tag":58,"props":753,"children":754},{},[755],{"type":62,"value":756},"Existing service\u002Futility files",{"type":62,"value":758}," — reuse these when adding client-side integration",{"type":49,"tag":98,"props":760,"children":761},{},[762,767],{"type":49,"tag":58,"props":763,"children":764},{},[765],{"type":62,"value":766},"Gaps",{"type":62,"value":768}," — frontend code that references server logic endpoints that don't exist yet",{"type":49,"tag":487,"props":770,"children":772},{"id":771},"_15-check-deployment-status-mandatory",[773],{"type":62,"value":774},"1.5 Check Deployment Status (Mandatory)",{"type":49,"tag":54,"props":776,"children":777},{},[778,780,785],{"type":62,"value":779},"Look for the ",{"type":49,"tag":67,"props":781,"children":783},{"className":782},[],[784],{"type":62,"value":259},{"type":62,"value":786}," folder:",{"type":49,"tag":54,"props":788,"children":789},{},[790,794,796,800,802,807],{"type":49,"tag":58,"props":791,"children":792},{},[793],{"type":62,"value":513},{"type":62,"value":795},": The site ",{"type":49,"tag":58,"props":797,"children":798},{},[799],{"type":62,"value":251},{"type":62,"value":801}," be deployed before server logic can be created — server logic files live inside ",{"type":49,"tag":67,"props":803,"children":805},{"className":804},[],[806],{"type":62,"value":267},{"type":62,"value":808},". Tell the user:",{"type":49,"tag":50,"props":810,"children":811},{},[812],{"type":49,"tag":54,"props":813,"children":814},{},[815,817,822],{"type":62,"value":816},"\"The ",{"type":49,"tag":67,"props":818,"children":820},{"className":819},[],[821],{"type":62,"value":259},{"type":62,"value":823}," folder was not found. Server logic files are stored inside this folder, so the site must be deployed at least once before creating server logic. Would you like to deploy now?\"",{"type":49,"tag":50,"props":825,"children":826},{},[827,846],{"type":49,"tag":54,"props":828,"children":829},{},[830,832,837,839,844],{"type":62,"value":831},"🚦 ",{"type":49,"tag":58,"props":833,"children":834},{},[835],{"type":62,"value":836},"Gate (plan · add-server-logic:1.5.deploy-first):",{"type":62,"value":838}," ",{"type":49,"tag":67,"props":840,"children":842},{"className":841},[],[843],{"type":62,"value":259},{"type":62,"value":845}," missing — server logic files live inside it. Deploy first or stop.",{"type":49,"tag":54,"props":847,"children":848},{},[849,854,856,861,863,868,870,875,877,883,885,890],{"type":49,"tag":58,"props":850,"children":851},{},[852],{"type":62,"value":853},"Trigger:",{"type":62,"value":855}," Phase 1.5 found no ",{"type":49,"tag":67,"props":857,"children":859},{"className":858},[],[860],{"type":62,"value":259},{"type":62,"value":862}," directory.\n",{"type":49,"tag":58,"props":864,"children":865},{},[866],{"type":62,"value":867},"Why we ask:",{"type":62,"value":869}," Server logic ",{"type":49,"tag":67,"props":871,"children":873},{"className":872},[],[874],{"type":62,"value":349},{"type":62,"value":876},"\u002F",{"type":49,"tag":67,"props":878,"children":880},{"className":879},[],[881],{"type":62,"value":882},".yml",{"type":62,"value":884}," files written to a non-existent path won't deploy.\n",{"type":49,"tag":58,"props":886,"children":887},{},[888],{"type":62,"value":889},"Cancel leaves:",{"type":62,"value":891}," Nothing — no server logic files written yet.",{"type":49,"tag":54,"props":893,"children":894},{},[895,897,903],{"type":62,"value":896},"Use ",{"type":49,"tag":67,"props":898,"children":900},{"className":899},[],[901],{"type":62,"value":902},"AskUserQuestion",{"type":62,"value":468},{"type":49,"tag":905,"props":906,"children":907},"table",{},[908,927],{"type":49,"tag":909,"props":910,"children":911},"thead",{},[912],{"type":49,"tag":913,"props":914,"children":915},"tr",{},[916,922],{"type":49,"tag":917,"props":918,"children":919},"th",{},[920],{"type":62,"value":921},"Question",{"type":49,"tag":917,"props":923,"children":924},{},[925],{"type":62,"value":926},"Options",{"type":49,"tag":928,"props":929,"children":930},"tbody",{},[931],{"type":49,"tag":913,"props":932,"children":933},{},[934,947],{"type":49,"tag":935,"props":936,"children":937},"td",{},[938,940,945],{"type":62,"value":939},"The ",{"type":49,"tag":67,"props":941,"children":943},{"className":942},[],[944],{"type":62,"value":259},{"type":62,"value":946}," folder is required for server logic. Would you like to deploy the site now?",{"type":49,"tag":935,"props":948,"children":949},{},[950],{"type":62,"value":951},"Yes, deploy now (Required), Cancel",{"type":49,"tag":54,"props":953,"children":954},{},[955,960,962,968],{"type":49,"tag":58,"props":956,"children":957},{},[958],{"type":62,"value":959},"If \"Yes, deploy now\"",{"type":62,"value":961},": Invoke ",{"type":49,"tag":67,"props":963,"children":965},{"className":964},[],[966],{"type":62,"value":967},"\u002Fdeploy-site",{"type":62,"value":969}," first, then continue to Phase 2.",{"type":49,"tag":54,"props":971,"children":972},{},[973,978,980,985],{"type":49,"tag":58,"props":974,"children":975},{},[976],{"type":62,"value":977},"If \"Cancel\"",{"type":62,"value":979},": Stop the workflow — server logic cannot be created without ",{"type":49,"tag":67,"props":981,"children":983},{"className":982},[],[984],{"type":62,"value":259},{"type":62,"value":523},{"type":49,"tag":54,"props":987,"children":988},{},[989,994,996,1001],{"type":49,"tag":58,"props":990,"children":991},{},[992],{"type":62,"value":993},"Output",{"type":62,"value":995},": Confirmed project root, ",{"type":49,"tag":67,"props":997,"children":999},{"className":998},[],[1000],{"type":62,"value":259},{"type":62,"value":1002}," exists, existing server logic (if any), available web roles",{"type":49,"tag":281,"props":1004,"children":1005},{},[],{"type":49,"tag":87,"props":1007,"children":1009},{"id":1008},"phase-2-understand-requirements",[1010],{"type":62,"value":1011},"Phase 2: Understand Requirements",{"type":49,"tag":54,"props":1013,"children":1014},{},[1015,1019],{"type":49,"tag":58,"props":1016,"children":1017},{},[1018],{"type":62,"value":456},{"type":62,"value":1020},": Determine the user intent, identify whether one or more server logic files are needed, and capture the required HTTP methods for each item",{"type":49,"tag":54,"props":1022,"children":1023},{},[1024,1028],{"type":49,"tag":58,"props":1025,"children":1026},{},[1027],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":1030,"children":1032},{"id":1031},"_21-analyze-user-request",[1033],{"type":62,"value":1034},"2.1 Analyze User Request",{"type":49,"tag":54,"props":1036,"children":1037},{},[1038],{"type":62,"value":1039},"From the user's request, determine:",{"type":49,"tag":94,"props":1041,"children":1042},{},[1043,1053,1063,1073],{"type":49,"tag":98,"props":1044,"children":1045},{},[1046,1051],{"type":49,"tag":58,"props":1047,"children":1048},{},[1049],{"type":62,"value":1050},"Intent shape",{"type":62,"value":1052},": Does the request map to a single server logic or multiple server logic?",{"type":49,"tag":98,"props":1054,"children":1055},{},[1056,1061],{"type":49,"tag":58,"props":1057,"children":1058},{},[1059],{"type":62,"value":1060},"Reuse opportunities",{"type":62,"value":1062},": Can an existing server logic satisfy or be safely extended for part of the request?",{"type":49,"tag":98,"props":1064,"children":1065},{},[1066,1071],{"type":49,"tag":58,"props":1067,"children":1068},{},[1069],{"type":62,"value":1070},"Server logic inventory",{"type":62,"value":1072},": For each required server logic, capture the purpose, suggested endpoint name, and whether it should be reused, extended, or created new",{"type":49,"tag":98,"props":1074,"children":1075},{},[1076,1081,1083,1088,1089,1094,1095,1100,1101,1106,1107,1112],{"type":49,"tag":58,"props":1077,"children":1078},{},[1079],{"type":62,"value":1080},"HTTP methods needed",{"type":62,"value":1082},": Which of the 5 functions should be implemented for each server logic (",{"type":49,"tag":67,"props":1084,"children":1086},{"className":1085},[],[1087],{"type":62,"value":156},{"type":62,"value":125},{"type":49,"tag":67,"props":1090,"children":1092},{"className":1091},[],[1093],{"type":62,"value":163},{"type":62,"value":125},{"type":49,"tag":67,"props":1096,"children":1098},{"className":1097},[],[1099],{"type":62,"value":170},{"type":62,"value":125},{"type":49,"tag":67,"props":1102,"children":1104},{"className":1103},[],[1105],{"type":62,"value":177},{"type":62,"value":125},{"type":49,"tag":67,"props":1108,"children":1110},{"className":1109},[],[1111],{"type":62,"value":184},{"type":62,"value":1113},")",{"type":49,"tag":54,"props":1115,"children":1116},{},[1117],{"type":62,"value":1118},"Prefer reuse or safe extension of an existing server logic when it already matches the domain, security model, and lifecycle of the requested capability. Only create a new server logic when reuse would make the existing file confusing, over-broad, or unsafe.",{"type":49,"tag":54,"props":1120,"children":1121},{},[1122],{"type":62,"value":1123},"Prefer multiple server logic files when the use case naturally separates into different responsibilities, security boundaries, or lifecycle concerns. Examples:",{"type":49,"tag":94,"props":1125,"children":1126},{},[1127,1132,1137],{"type":49,"tag":98,"props":1128,"children":1129},{},[1130],{"type":62,"value":1131},"Separate read vs. write workflows with different web role requirements",{"type":49,"tag":98,"props":1133,"children":1134},{},[1135],{"type":62,"value":1136},"Distinct integrations with different external systems or site settings",{"type":49,"tag":98,"props":1138,"children":1139},{},[1140],{"type":62,"value":1141},"Independent business capabilities that would be harder to test or reason about if merged into one endpoint",{"type":49,"tag":487,"props":1143,"children":1145},{"id":1144},"_211-identify-validate-and-execute-patterns",[1146],{"type":62,"value":1147},"2.1.1 Identify Validate-and-Execute Patterns",{"type":49,"tag":54,"props":1149,"children":1150},{},[1151,1153,1158],{"type":62,"value":1152},"For each planned server logic item, determine whether it should ",{"type":49,"tag":58,"props":1154,"children":1155},{},[1156],{"type":62,"value":1157},"validate-and-execute",{"type":62,"value":1159}," — meaning the server logic both validates a business rule AND performs the resulting Dataverse write, rather than just returning a validation result for the client to act on.",{"type":49,"tag":54,"props":1161,"children":1162},{},[1163,1165,1170],{"type":62,"value":1164},"A server logic item should validate-and-execute when ",{"type":49,"tag":58,"props":1166,"children":1167},{},[1168],{"type":62,"value":1169},"any",{"type":62,"value":1171}," of these are true:",{"type":49,"tag":905,"props":1173,"children":1174},{},[1175,1191],{"type":49,"tag":909,"props":1176,"children":1177},{},[1178],{"type":49,"tag":913,"props":1179,"children":1180},{},[1181,1186],{"type":49,"tag":917,"props":1182,"children":1183},{},[1184],{"type":62,"value":1185},"Condition",{"type":49,"tag":917,"props":1187,"children":1188},{},[1189],{"type":62,"value":1190},"Example",{"type":49,"tag":928,"props":1192,"children":1193},{},[1194,1207,1220,1233,1246],{"type":49,"tag":913,"props":1195,"children":1196},{},[1197,1202],{"type":49,"tag":935,"props":1198,"children":1199},{},[1200],{"type":62,"value":1201},"It enforces a state machine or lifecycle",{"type":49,"tag":935,"props":1203,"children":1204},{},[1205],{"type":62,"value":1206},"Order status: Draft → Submitted → Approved",{"type":49,"tag":913,"props":1208,"children":1209},{},[1210,1215],{"type":49,"tag":935,"props":1211,"children":1212},{},[1213],{"type":62,"value":1214},"The write is conditional on a business rule that must be tamper-proof",{"type":49,"tag":935,"props":1216,"children":1217},{},[1218],{"type":62,"value":1219},"\"Only allow bid submission before the deadline\"",{"type":49,"tag":913,"props":1221,"children":1222},{},[1223,1228],{"type":49,"tag":935,"props":1224,"children":1225},{},[1226],{"type":62,"value":1227},"The operation spans multiple tables atomically",{"type":49,"tag":935,"props":1229,"children":1230},{},[1231],{"type":62,"value":1232},"Award a bid + reject all others + update event status",{"type":49,"tag":913,"props":1234,"children":1235},{},[1236,1241],{"type":49,"tag":935,"props":1237,"children":1238},{},[1239],{"type":62,"value":1240},"The write involves a computed or derived value",{"type":49,"tag":935,"props":1242,"children":1243},{},[1244],{"type":62,"value":1245},"Server calculates a score and writes it",{"type":49,"tag":913,"props":1247,"children":1248},{},[1249,1254],{"type":49,"tag":935,"props":1250,"children":1251},{},[1252],{"type":62,"value":1253},"The client should not have direct write access to the field",{"type":49,"tag":935,"props":1255,"children":1256},{},[1257],{"type":62,"value":1258},"Status fields with strict transition rules",{"type":49,"tag":54,"props":1260,"children":1261},{},[1262],{"type":62,"value":1263},"For each validate-and-execute item, note:",{"type":49,"tag":94,"props":1265,"children":1266},{},[1267,1277,1287],{"type":49,"tag":98,"props":1268,"children":1269},{},[1270,1275],{"type":49,"tag":58,"props":1271,"children":1272},{},[1273],{"type":62,"value":1274},"Which Dataverse writes the server logic will perform",{"type":62,"value":1276}," (UpdateRecord, CreateRecord, etc.)",{"type":49,"tag":98,"props":1278,"children":1279},{},[1280,1285],{"type":49,"tag":58,"props":1281,"children":1282},{},[1283],{"type":62,"value":1284},"Which fields are being written",{"type":62,"value":1286}," — these fields should NOT be writable via Web API from the client",{"type":49,"tag":98,"props":1288,"children":1289},{},[1290,1295],{"type":49,"tag":58,"props":1291,"children":1292},{},[1293],{"type":62,"value":1294},"What the server logic returns to the client",{"type":62,"value":1296}," — typically a success\u002Ffailure result with the before\u002Fafter state, NOT a validation flag that the client acts on",{"type":49,"tag":54,"props":1298,"children":1299},{},[1300,1305,1307,1313],{"type":49,"tag":58,"props":1301,"children":1302},{},[1303],{"type":62,"value":1304},"Anti-pattern to avoid",{"type":62,"value":1306},": A server logic item that only validates and returns ",{"type":49,"tag":67,"props":1308,"children":1310},{"className":1309},[],[1311],{"type":62,"value":1312},"{ valid: true\u002Ffalse }",{"type":62,"value":1314},", expecting the client to make a separate Web API call to perform the write. This allows the client to skip validation and write directly.",{"type":49,"tag":487,"props":1316,"children":1318},{"id":1317},"_212-discover-dataverse-custom-actions",[1319],{"type":62,"value":1320},"2.1.2 Discover Dataverse Custom Actions",{"type":49,"tag":54,"props":1322,"children":1323},{},[1324],{"type":62,"value":1325},"If any planned server logic item involves Dataverse operations, check whether the user's Dataverse environment has existing custom actions (Custom APIs or Custom Process Actions) that could be leveraged instead of building logic from scratch.",{"type":49,"tag":54,"props":1327,"children":1328},{},[1329],{"type":49,"tag":58,"props":1330,"children":1331},{},[1332],{"type":62,"value":1333},"Step 1 — Fetch custom actions:",{"type":49,"tag":1335,"props":1336,"children":1341},"pre",{"className":1337,"code":1338,"language":1339,"meta":1340,"style":1340},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","node \"${PLUGIN_ROOT}\u002Fscripts\u002Flist-custom-actions.js\" \"\u003CENV_URL>\"\n","bash","",[1342],{"type":49,"tag":67,"props":1343,"children":1344},{"__ignoreMap":1340},[1345],{"type":49,"tag":1346,"props":1347,"children":1350},"span",{"class":1348,"line":1349},"line",1,[1351,1357,1363,1369,1374,1380,1385,1390,1395],{"type":49,"tag":1346,"props":1352,"children":1354},{"style":1353},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1355],{"type":62,"value":1356},"node",{"type":49,"tag":1346,"props":1358,"children":1360},{"style":1359},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1361],{"type":62,"value":1362}," \"${",{"type":49,"tag":1346,"props":1364,"children":1366},{"style":1365},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1367],{"type":62,"value":1368},"PLUGIN_ROOT",{"type":49,"tag":1346,"props":1370,"children":1371},{"style":1359},[1372],{"type":62,"value":1373},"}",{"type":49,"tag":1346,"props":1375,"children":1377},{"style":1376},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1378],{"type":62,"value":1379},"\u002Fscripts\u002Flist-custom-actions.js",{"type":49,"tag":1346,"props":1381,"children":1382},{"style":1359},[1383],{"type":62,"value":1384},"\"",{"type":49,"tag":1346,"props":1386,"children":1387},{"style":1359},[1388],{"type":62,"value":1389}," \"",{"type":49,"tag":1346,"props":1391,"children":1392},{"style":1376},[1393],{"type":62,"value":1394},"\u003CENV_URL>",{"type":49,"tag":1346,"props":1396,"children":1397},{"style":1359},[1398],{"type":62,"value":1399},"\"\n",{"type":49,"tag":54,"props":1401,"children":1402},{},[1403],{"type":62,"value":1404},"The script outputs a JSON object with:",{"type":49,"tag":94,"props":1406,"children":1407},{},[1408,1419,1430],{"type":49,"tag":98,"props":1409,"children":1410},{},[1411,1417],{"type":49,"tag":67,"props":1412,"children":1414},{"className":1413},[],[1415],{"type":62,"value":1416},"customApis",{"type":62,"value":1418}," — Modern Custom APIs with full request parameters and response properties",{"type":49,"tag":98,"props":1420,"children":1421},{},[1422,1428],{"type":49,"tag":67,"props":1423,"children":1425},{"className":1424},[],[1426],{"type":62,"value":1427},"customProcessActions",{"type":62,"value":1429}," — Legacy Custom Process Actions (activated only)",{"type":49,"tag":98,"props":1431,"children":1432},{},[1433,1439],{"type":49,"tag":67,"props":1434,"children":1436},{"className":1435},[],[1437],{"type":62,"value":1438},"total",{"type":62,"value":1440}," — Total count of both types combined",{"type":49,"tag":54,"props":1442,"children":1443},{},[1444,1446,1452,1453,1459,1460,1466,1467,1473,1475,1481,1483,1489,1491,1497,1498,1504,1505,1511,1513,1519,1520,1526,1528,1534,1535,1541,1542,1548,1550,1556,1557,1563],{"type":62,"value":1445},"Each entry includes: ",{"type":49,"tag":67,"props":1447,"children":1449},{"className":1448},[],[1450],{"type":62,"value":1451},"name",{"type":62,"value":125},{"type":49,"tag":67,"props":1454,"children":1456},{"className":1455},[],[1457],{"type":62,"value":1458},"displayName",{"type":62,"value":125},{"type":49,"tag":67,"props":1461,"children":1463},{"className":1462},[],[1464],{"type":62,"value":1465},"description",{"type":62,"value":125},{"type":49,"tag":67,"props":1468,"children":1470},{"className":1469},[],[1471],{"type":62,"value":1472},"type",{"type":62,"value":1474}," (",{"type":49,"tag":67,"props":1476,"children":1478},{"className":1477},[],[1479],{"type":62,"value":1480},"action",{"type":62,"value":1482}," or ",{"type":49,"tag":67,"props":1484,"children":1486},{"className":1485},[],[1487],{"type":62,"value":1488},"function",{"type":62,"value":1490},"), ",{"type":49,"tag":67,"props":1492,"children":1494},{"className":1493},[],[1495],{"type":62,"value":1496},"binding",{"type":62,"value":1474},{"type":49,"tag":67,"props":1499,"children":1501},{"className":1500},[],[1502],{"type":62,"value":1503},"unbound",{"type":62,"value":125},{"type":49,"tag":67,"props":1506,"children":1508},{"className":1507},[],[1509],{"type":62,"value":1510},"entity",{"type":62,"value":1512},", or ",{"type":49,"tag":67,"props":1514,"children":1516},{"className":1515},[],[1517],{"type":62,"value":1518},"entityCollection",{"type":62,"value":1490},{"type":49,"tag":67,"props":1521,"children":1523},{"className":1522},[],[1524],{"type":62,"value":1525},"boundEntity",{"type":62,"value":1527},", and ",{"type":49,"tag":67,"props":1529,"children":1531},{"className":1530},[],[1532],{"type":62,"value":1533},"source",{"type":62,"value":1474},{"type":49,"tag":67,"props":1536,"children":1538},{"className":1537},[],[1539],{"type":62,"value":1540},"customApi",{"type":62,"value":1482},{"type":49,"tag":67,"props":1543,"children":1545},{"className":1544},[],[1546],{"type":62,"value":1547},"customProcessAction",{"type":62,"value":1549},"). Custom APIs also include ",{"type":49,"tag":67,"props":1551,"children":1553},{"className":1552},[],[1554],{"type":62,"value":1555},"requestParameters",{"type":62,"value":351},{"type":49,"tag":67,"props":1558,"children":1560},{"className":1559},[],[1561],{"type":62,"value":1562},"responseProperties",{"type":62,"value":1564}," arrays.",{"type":49,"tag":54,"props":1566,"children":1567},{},[1568],{"type":49,"tag":58,"props":1569,"children":1570},{},[1571],{"type":62,"value":1572},"Step 2 — Present and ask the user:",{"type":49,"tag":54,"props":1574,"children":1575},{},[1576,1578,1584],{"type":62,"value":1577},"If custom actions are found (",{"type":49,"tag":67,"props":1579,"children":1581},{"className":1580},[],[1582],{"type":62,"value":1583},"total > 0",{"type":62,"value":1585},"), present a summary to the user grouped by binding type (unbound vs. entity-bound) and ask whether any should be used:",{"type":49,"tag":50,"props":1587,"children":1588},{},[1589,1600],{"type":49,"tag":54,"props":1590,"children":1591},{},[1592,1593,1598],{"type":62,"value":831},{"type":49,"tag":58,"props":1594,"children":1595},{},[1596],{"type":62,"value":1597},"Gate (plan · add-server-logic:2.1.2.use-custom-actions):",{"type":62,"value":1599}," Custom actions discovered — decide whether to wrap existing Dataverse Custom APIs\u002FProcess Actions or build server logic from scratch. Choice changes the Phase 5 implementation shape.",{"type":49,"tag":54,"props":1601,"children":1602},{},[1603,1607,1608,1614,1616,1620,1622,1626],{"type":49,"tag":58,"props":1604,"children":1605},{},[1606],{"type":62,"value":853},{"type":62,"value":838},{"type":49,"tag":67,"props":1609,"children":1611},{"className":1610},[],[1612],{"type":62,"value":1613},"list-custom-actions.js",{"type":62,"value":1615}," returned at least one entry.\n",{"type":49,"tag":58,"props":1617,"children":1618},{},[1619],{"type":62,"value":867},{"type":62,"value":1621}," Auto-wrapping could attach the wrong action; auto-skipping duplicates logic that already exists in Dataverse.\n",{"type":49,"tag":58,"props":1623,"children":1624},{},[1625],{"type":62,"value":889},{"type":62,"value":891},{"type":49,"tag":54,"props":1628,"children":1629},{},[1630,1631,1636],{"type":62,"value":896},{"type":49,"tag":67,"props":1632,"children":1634},{"className":1633},[],[1635],{"type":62,"value":902},{"type":62,"value":468},{"type":49,"tag":905,"props":1638,"children":1639},{},[1640,1654],{"type":49,"tag":909,"props":1641,"children":1642},{},[1643],{"type":49,"tag":913,"props":1644,"children":1645},{},[1646,1650],{"type":49,"tag":917,"props":1647,"children":1648},{},[1649],{"type":62,"value":921},{"type":49,"tag":917,"props":1651,"children":1652},{},[1653],{"type":62,"value":926},{"type":49,"tag":928,"props":1655,"children":1656},{},[1657],{"type":49,"tag":913,"props":1658,"children":1659},{},[1660,1673],{"type":49,"tag":935,"props":1661,"children":1662},{},[1663,1665,1671],{"type":62,"value":1664},"Your Dataverse environment has ",{"type":49,"tag":67,"props":1666,"children":1668},{"className":1667},[],[1669],{"type":62,"value":1670},"\u003Ctotal>",{"type":62,"value":1672}," custom action(s). Would you like to use any of these in your server logic instead of writing the logic from scratch?",{"type":49,"tag":935,"props":1674,"children":1675},{},[1676],{"type":62,"value":1677},"Yes, let me choose which ones to use; No, build everything from scratch",{"type":49,"tag":54,"props":1679,"children":1680},{},[1681,1683,1688,1689,1694],{"type":62,"value":1682},"Present the list clearly — for each action show: name, description, type (action\u002Ffunction), binding, and bound entity (if applicable). Group them as ",{"type":49,"tag":58,"props":1684,"children":1685},{},[1686],{"type":62,"value":1687},"Unbound",{"type":62,"value":351},{"type":49,"tag":58,"props":1690,"children":1691},{},[1692],{"type":62,"value":1693},"Entity-bound",{"type":62,"value":1695}," for readability.",{"type":49,"tag":54,"props":1697,"children":1698},{},[1699,1701,1706],{"type":62,"value":1700},"If the user says ",{"type":49,"tag":58,"props":1702,"children":1703},{},[1704],{"type":62,"value":1705},"No",{"type":62,"value":1707},", skip to Phase 2.2.",{"type":49,"tag":54,"props":1709,"children":1710},{},[1711],{"type":49,"tag":58,"props":1712,"children":1713},{},[1714],{"type":62,"value":1715},"Step 3 — Map custom actions to server logic items:",{"type":49,"tag":54,"props":1717,"children":1718},{},[1719,1720,1725],{"type":62,"value":1700},{"type":49,"tag":58,"props":1721,"children":1722},{},[1723],{"type":62,"value":1724},"Yes",{"type":62,"value":1726},", for each server logic item being created, ask which custom action (if any) it should wrap:",{"type":49,"tag":54,"props":1728,"children":1729},{},[1730,1731,1736],{"type":62,"value":896},{"type":49,"tag":67,"props":1732,"children":1734},{"className":1733},[],[1735],{"type":62,"value":902},{"type":62,"value":1737}," for each server logic item:",{"type":49,"tag":905,"props":1739,"children":1740},{},[1741,1756],{"type":49,"tag":909,"props":1742,"children":1743},{},[1744],{"type":49,"tag":913,"props":1745,"children":1746},{},[1747,1751],{"type":49,"tag":917,"props":1748,"children":1749},{},[1750],{"type":62,"value":921},{"type":49,"tag":917,"props":1752,"children":1753},{},[1754],{"type":62,"value":1755},"Context",{"type":49,"tag":928,"props":1757,"children":1758},{},[1759],{"type":49,"tag":913,"props":1760,"children":1761},{},[1762,1775],{"type":49,"tag":935,"props":1763,"children":1764},{},[1765,1767,1773],{"type":62,"value":1766},"For the ",{"type":49,"tag":67,"props":1768,"children":1770},{"className":1769},[],[1771],{"type":62,"value":1772},"\u003Cserver-logic-name>",{"type":62,"value":1774}," endpoint, which custom action should it use?",{"type":49,"tag":935,"props":1776,"children":1777},{},[1778,1780,1785],{"type":62,"value":1779},"Present the list of custom actions with their names, descriptions, and binding types. Include ",{"type":49,"tag":58,"props":1781,"children":1782},{},[1783],{"type":62,"value":1784},"\"None — build from scratch\"",{"type":62,"value":1786}," as an option.",{"type":49,"tag":54,"props":1788,"children":1789},{},[1790],{"type":62,"value":1791},"Record the mapping for each server logic item. For items that wrap a custom action, note:",{"type":49,"tag":94,"props":1793,"children":1794},{},[1795,1808,1828,1833],{"type":49,"tag":98,"props":1796,"children":1797},{},[1798,1800,1806],{"type":62,"value":1799},"The custom action name (used in the ",{"type":49,"tag":67,"props":1801,"children":1803},{"className":1802},[],[1804],{"type":62,"value":1805},"InvokeCustomApi",{"type":62,"value":1807}," call)",{"type":49,"tag":98,"props":1809,"children":1810},{},[1811,1813,1819,1821,1827],{"type":62,"value":1812},"Whether it's a function (",{"type":49,"tag":67,"props":1814,"children":1816},{"className":1815},[],[1817],{"type":62,"value":1818},"GET",{"type":62,"value":1820},") or action (",{"type":49,"tag":67,"props":1822,"children":1824},{"className":1823},[],[1825],{"type":62,"value":1826},"POST",{"type":62,"value":1113},{"type":49,"tag":98,"props":1829,"children":1830},{},[1831],{"type":62,"value":1832},"The binding type and bound entity (if applicable)",{"type":49,"tag":98,"props":1834,"children":1835},{},[1836],{"type":62,"value":1837},"The request parameters and response properties (if available from Custom APIs)",{"type":49,"tag":54,"props":1839,"children":1840},{},[1841],{"type":62,"value":1842},"This mapping will be used in Phase 5.3 when generating the server logic code, and will appear in the HTML plan (Phase 4) to indicate which items wrap existing custom actions.",{"type":49,"tag":487,"props":1844,"children":1846},{"id":1845},"_22-identify-sdk-features-needed",[1847],{"type":62,"value":1848},"2.2 Identify SDK Features Needed",{"type":49,"tag":54,"props":1850,"children":1851},{},[1852],{"type":62,"value":1853},"Based on each planned server logic item's purpose, identify which Server SDK features are required:",{"type":49,"tag":905,"props":1855,"children":1856},{},[1857,1873],{"type":49,"tag":909,"props":1858,"children":1859},{},[1860],{"type":49,"tag":913,"props":1861,"children":1862},{},[1863,1868],{"type":49,"tag":917,"props":1864,"children":1865},{},[1866],{"type":62,"value":1867},"Feature",{"type":49,"tag":917,"props":1869,"children":1870},{},[1871],{"type":62,"value":1872},"When to use",{"type":49,"tag":928,"props":1874,"children":1875},{},[1876,1893,1917,1934,1951,1968,1985,2017],{"type":49,"tag":913,"props":1877,"children":1878},{},[1879,1888],{"type":49,"tag":935,"props":1880,"children":1881},{},[1882],{"type":49,"tag":67,"props":1883,"children":1885},{"className":1884},[],[1886],{"type":62,"value":1887},"Server.Connector.HttpClient",{"type":49,"tag":935,"props":1889,"children":1890},{},[1891],{"type":62,"value":1892},"Calling external REST APIs (NOT Dataverse)",{"type":49,"tag":913,"props":1894,"children":1895},{},[1896,1905],{"type":49,"tag":935,"props":1897,"children":1898},{},[1899],{"type":49,"tag":67,"props":1900,"children":1902},{"className":1901},[],[1903],{"type":62,"value":1904},"Server.Connector.Dataverse",{"type":49,"tag":935,"props":1906,"children":1907},{},[1908,1910,1915],{"type":62,"value":1909},"Reading\u002Fwriting Dataverse records (CRUD + ",{"type":49,"tag":67,"props":1911,"children":1913},{"className":1912},[],[1914],{"type":62,"value":1805},{"type":62,"value":1916}," for Dataverse Custom APIs)",{"type":49,"tag":913,"props":1918,"children":1919},{},[1920,1929],{"type":49,"tag":935,"props":1921,"children":1922},{},[1923],{"type":49,"tag":67,"props":1924,"children":1926},{"className":1925},[],[1927],{"type":62,"value":1928},"Server.Context",{"type":49,"tag":935,"props":1930,"children":1931},{},[1932],{"type":62,"value":1933},"Accessing request parameters, headers, body",{"type":49,"tag":913,"props":1935,"children":1936},{},[1937,1946],{"type":49,"tag":935,"props":1938,"children":1939},{},[1940],{"type":49,"tag":67,"props":1941,"children":1943},{"className":1942},[],[1944],{"type":62,"value":1945},"Server.User",{"type":49,"tag":935,"props":1947,"children":1948},{},[1949],{"type":62,"value":1950},"User-scoped operations, role checks",{"type":49,"tag":913,"props":1952,"children":1953},{},[1954,1963],{"type":49,"tag":935,"props":1955,"children":1956},{},[1957],{"type":49,"tag":67,"props":1958,"children":1960},{"className":1959},[],[1961],{"type":62,"value":1962},"Server.Logger",{"type":49,"tag":935,"props":1964,"children":1965},{},[1966],{"type":62,"value":1967},"Always — every function should log entry\u002Fexit and errors",{"type":49,"tag":913,"props":1969,"children":1970},{},[1971,1980],{"type":49,"tag":935,"props":1972,"children":1973},{},[1974],{"type":49,"tag":67,"props":1975,"children":1977},{"className":1976},[],[1978],{"type":62,"value":1979},"Server.Sitesetting",{"type":49,"tag":935,"props":1981,"children":1982},{},[1983],{"type":62,"value":1984},"Reading site setting configuration values",{"type":49,"tag":913,"props":1986,"children":1987},{},[1988,1997],{"type":49,"tag":935,"props":1989,"children":1990},{},[1991],{"type":49,"tag":67,"props":1992,"children":1994},{"className":1993},[],[1995],{"type":62,"value":1996},"Server.EnvironmentVariable",{"type":49,"tag":935,"props":1998,"children":1999},{},[2000,2002,2008,2010,2015],{"type":62,"value":2001},"Reading Dataverse environment variable values directly via ",{"type":49,"tag":67,"props":2003,"children":2005},{"className":2004},[],[2006],{"type":62,"value":2007},"Server.EnvironmentVariable.get(name)",{"type":62,"value":2009}," — an alternative to ",{"type":49,"tag":67,"props":2011,"children":2013},{"className":2012},[],[2014],{"type":62,"value":1979},{"type":62,"value":2016}," for non-secret config",{"type":49,"tag":913,"props":2018,"children":2019},{},[2020,2029],{"type":49,"tag":935,"props":2021,"children":2022},{},[2023],{"type":49,"tag":67,"props":2024,"children":2026},{"className":2025},[],[2027],{"type":62,"value":2028},"Server.Website",{"type":49,"tag":935,"props":2030,"children":2031},{},[2032],{"type":62,"value":2033},"Accessing site metadata",{"type":49,"tag":487,"props":2035,"children":2037},{"id":2036},"_23-identify-secret-values",[2038],{"type":62,"value":2039},"2.3 Identify Secret Values",{"type":49,"tag":54,"props":2041,"children":2042},{},[2043],{"type":62,"value":2044},"Determine whether any server logic item requires secret or sensitive configuration values that should not be hardcoded. Common examples:",{"type":49,"tag":905,"props":2046,"children":2047},{},[2048,2064],{"type":49,"tag":909,"props":2049,"children":2050},{},[2051],{"type":49,"tag":913,"props":2052,"children":2053},{},[2054,2059],{"type":49,"tag":917,"props":2055,"children":2056},{},[2057],{"type":62,"value":2058},"Scenario",{"type":49,"tag":917,"props":2060,"children":2061},{},[2062],{"type":62,"value":2063},"Secret needed",{"type":49,"tag":928,"props":2065,"children":2066},{},[2067,2080,2093,2106],{"type":49,"tag":913,"props":2068,"children":2069},{},[2070,2075],{"type":49,"tag":935,"props":2071,"children":2072},{},[2073],{"type":62,"value":2074},"Calling an authenticated external API",{"type":49,"tag":935,"props":2076,"children":2077},{},[2078],{"type":62,"value":2079},"API key, client secret, bearer token",{"type":49,"tag":913,"props":2081,"children":2082},{},[2083,2088],{"type":49,"tag":935,"props":2084,"children":2085},{},[2086],{"type":62,"value":2087},"Connecting to a third-party service",{"type":49,"tag":935,"props":2089,"children":2090},{},[2091],{"type":62,"value":2092},"Connection string, access token",{"type":49,"tag":913,"props":2094,"children":2095},{},[2096,2101],{"type":49,"tag":935,"props":2097,"children":2098},{},[2099],{"type":62,"value":2100},"OAuth2 client credentials flow",{"type":49,"tag":935,"props":2102,"children":2103},{},[2104],{"type":62,"value":2105},"Client ID + client secret",{"type":49,"tag":913,"props":2107,"children":2108},{},[2109,2114],{"type":49,"tag":935,"props":2110,"children":2111},{},[2112],{"type":62,"value":2113},"Webhook verification",{"type":49,"tag":935,"props":2115,"children":2116},{},[2117],{"type":62,"value":2118},"Signing secret, shared key",{"type":49,"tag":54,"props":2120,"children":2121},{},[2122],{"type":62,"value":2123},"For each identified secret, capture:",{"type":49,"tag":94,"props":2125,"children":2126},{},[2127,2151,2161,2186],{"type":49,"tag":98,"props":2128,"children":2129},{},[2130,2135,2137,2143,2144,2150],{"type":49,"tag":58,"props":2131,"children":2132},{},[2133],{"type":62,"value":2134},"Secret name",{"type":62,"value":2136},": A descriptive name (e.g., ",{"type":49,"tag":67,"props":2138,"children":2140},{"className":2139},[],[2141],{"type":62,"value":2142},"ExchangeRateApiKey",{"type":62,"value":125},{"type":49,"tag":67,"props":2145,"children":2147},{"className":2146},[],[2148],{"type":62,"value":2149},"PaymentGatewaySecret",{"type":62,"value":1113},{"type":49,"tag":98,"props":2152,"children":2153},{},[2154,2159],{"type":49,"tag":58,"props":2155,"children":2156},{},[2157],{"type":62,"value":2158},"Purpose",{"type":62,"value":2160},": Why the secret is needed",{"type":49,"tag":98,"props":2162,"children":2163},{},[2164,2169,2171,2177,2179,2185],{"type":49,"tag":58,"props":2165,"children":2166},{},[2167],{"type":62,"value":2168},"Site setting name",{"type":62,"value":2170},": The name the server logic will use with ",{"type":49,"tag":67,"props":2172,"children":2174},{"className":2173},[],[2175],{"type":62,"value":2176},"Server.Sitesetting.Get()",{"type":62,"value":2178}," (e.g., ",{"type":49,"tag":67,"props":2180,"children":2182},{"className":2181},[],[2183],{"type":62,"value":2184},"ExternalApi\u002FExchangeRateApiKey",{"type":62,"value":1113},{"type":49,"tag":98,"props":2187,"children":2188},{},[2189,2194,2196,2202],{"type":49,"tag":58,"props":2190,"children":2191},{},[2192],{"type":62,"value":2193},"Environment variable schema name",{"type":62,"value":2195},": The Dataverse environment variable schema name (e.g., ",{"type":49,"tag":67,"props":2197,"children":2199},{"className":2198},[],[2200],{"type":62,"value":2201},"cr5b4_ExchangeRateApiKey",{"type":62,"value":1113},{"type":49,"tag":54,"props":2204,"children":2205},{},[2206],{"type":62,"value":2207},"These values will be used in Phase 7 to create the environment variables and site settings.",{"type":49,"tag":487,"props":2209,"children":2211},{"id":2210},"_231-key-vault-decision",[2212],{"type":62,"value":2213},"2.3.1 Key Vault Decision",{"type":49,"tag":54,"props":2215,"children":2216},{},[2217],{"type":62,"value":2218},"If secrets were identified in Phase 2.3, ask the user now whether they want to use Azure Key Vault. This decision must happen before Phase 4 so the implementation plan can show the chosen secret management approach.",{"type":49,"tag":50,"props":2220,"children":2221},{},[2222,2233],{"type":49,"tag":54,"props":2223,"children":2224},{},[2225,2226,2231],{"type":62,"value":831},{"type":49,"tag":58,"props":2227,"children":2228},{},[2229],{"type":62,"value":2230},"Gate (plan · add-server-logic:2.3.1.keyvault):",{"type":62,"value":2232}," Pick secret-storage mechanism (Key Vault vs plain env var). Choice changes the Phase 4 rendered plan and the Phase 7 implementation pipeline.",{"type":49,"tag":54,"props":2234,"children":2235},{},[2236,2240,2242,2246,2248,2252],{"type":49,"tag":58,"props":2237,"children":2238},{},[2239],{"type":62,"value":853},{"type":62,"value":2241}," Phase 2.3 identified at least one secret value.\n",{"type":49,"tag":58,"props":2243,"children":2244},{},[2245],{"type":62,"value":867},{"type":62,"value":2247}," Plain env var creation can expose secrets in solution exports; auto-picking Key Vault forces additional Azure setup.\n",{"type":49,"tag":58,"props":2249,"children":2250},{},[2251],{"type":62,"value":889},{"type":62,"value":2253}," Nothing — no env var definitions written yet.",{"type":49,"tag":54,"props":2255,"children":2256},{},[2257,2258,2263],{"type":62,"value":896},{"type":49,"tag":67,"props":2259,"children":2261},{"className":2260},[],[2262],{"type":62,"value":902},{"type":62,"value":468},{"type":49,"tag":905,"props":2265,"children":2266},{},[2267,2281],{"type":49,"tag":909,"props":2268,"children":2269},{},[2270],{"type":49,"tag":913,"props":2271,"children":2272},{},[2273,2277],{"type":49,"tag":917,"props":2274,"children":2275},{},[2276],{"type":62,"value":921},{"type":49,"tag":917,"props":2278,"children":2279},{},[2280],{"type":62,"value":926},{"type":49,"tag":928,"props":2282,"children":2283},{},[2284],{"type":49,"tag":913,"props":2285,"children":2286},{},[2287,2292],{"type":49,"tag":935,"props":2288,"children":2289},{},[2290],{"type":62,"value":2291},"This server logic requires secret values (e.g., API keys, client secrets). Azure Key Vault is the recommended way to store secrets securely. Would you like to use Azure Key Vault?",{"type":49,"tag":935,"props":2293,"children":2294},{},[2295],{"type":62,"value":2296},"Yes, use Azure Key Vault (Recommended), No, store directly as environment variable",{"type":49,"tag":54,"props":2298,"children":2299},{},[2300],{"type":62,"value":2301},"Record the user's choice — it will be shown in the HTML plan (Phase 4) and executed in Phase 7.",{"type":49,"tag":487,"props":2303,"children":2305},{"id":2304},"_24-confirm-with-user",[2306],{"type":62,"value":2307},"2.4 Confirm with User",{"type":49,"tag":54,"props":2309,"children":2310},{},[2311,2313,2318],{"type":62,"value":2312},"If the requirements are ambiguous, use ",{"type":49,"tag":67,"props":2314,"children":2316},{"className":2315},[],[2317],{"type":62,"value":902},{"type":62,"value":2319}," to clarify:",{"type":49,"tag":905,"props":2321,"children":2322},{},[2323,2337],{"type":49,"tag":909,"props":2324,"children":2325},{},[2326],{"type":49,"tag":913,"props":2327,"children":2328},{},[2329,2333],{"type":49,"tag":917,"props":2330,"children":2331},{},[2332],{"type":62,"value":921},{"type":49,"tag":917,"props":2334,"children":2335},{},[2336],{"type":62,"value":1755},{"type":49,"tag":928,"props":2338,"children":2339},{},[2340,2353,2366,2379,2392,2405],{"type":49,"tag":913,"props":2341,"children":2342},{},[2343,2348],{"type":49,"tag":935,"props":2344,"children":2345},{},[2346],{"type":62,"value":2347},"What should this server logic solution do overall?",{"type":49,"tag":935,"props":2349,"children":2350},{},[2351],{"type":62,"value":2352},"If the purpose is unclear",{"type":49,"tag":913,"props":2354,"children":2355},{},[2356,2361],{"type":49,"tag":935,"props":2357,"children":2358},{},[2359],{"type":62,"value":2360},"Should this be one server logic or multiple server logic?",{"type":49,"tag":935,"props":2362,"children":2363},{},[2364],{"type":62,"value":2365},"If the request could reasonably be modeled either way",{"type":49,"tag":913,"props":2367,"children":2368},{},[2369,2374],{"type":49,"tag":935,"props":2370,"children":2371},{},[2372],{"type":62,"value":2373},"Which HTTP methods does each server logic need?",{"type":49,"tag":935,"props":2375,"children":2376},{},[2377],{"type":62,"value":2378},"If not specified — suggest based on the use case (e.g., read-only = GET, form processing = POST)",{"type":49,"tag":913,"props":2380,"children":2381},{},[2382,2387],{"type":49,"tag":935,"props":2383,"children":2384},{},[2385],{"type":62,"value":2386},"Does each server logic need to call external APIs, Dataverse, or both?",{"type":49,"tag":935,"props":2388,"children":2389},{},[2390],{"type":62,"value":2391},"Determines which connectors to use",{"type":49,"tag":913,"props":2393,"children":2394},{},[2395,2400],{"type":49,"tag":935,"props":2396,"children":2397},{},[2398],{"type":62,"value":2399},"What should each server logic be named?",{"type":49,"tag":935,"props":2401,"children":2402},{},[2403],{"type":62,"value":2404},"Suggest URL-friendly names based on the responsibilities",{"type":49,"tag":913,"props":2406,"children":2407},{},[2408,2413],{"type":49,"tag":935,"props":2409,"children":2410},{},[2411],{"type":62,"value":2412},"Does the server logic need any secret or sensitive values (API keys, client secrets, tokens)?",{"type":49,"tag":935,"props":2414,"children":2415},{},[2416],{"type":62,"value":2417},"If the server logic calls authenticated external APIs or services",{"type":49,"tag":54,"props":2419,"children":2420},{},[2421,2425],{"type":49,"tag":58,"props":2422,"children":2423},{},[2424],{"type":62,"value":993},{"type":62,"value":2426},": Clear understanding of the overall intent, the list of server logic items to reuse\u002Fextend\u002Fcreate, their HTTP methods, SDK features needed, and any secrets required",{"type":49,"tag":281,"props":2428,"children":2429},{},[],{"type":49,"tag":87,"props":2431,"children":2433},{"id":2432},"phase-3-fetch-latest-documentation",[2434],{"type":62,"value":2435},"Phase 3: Fetch Latest Documentation",{"type":49,"tag":54,"props":2437,"children":2438},{},[2439,2443],{"type":49,"tag":58,"props":2440,"children":2441},{},[2442],{"type":62,"value":456},{"type":62,"value":2444},": Discover and read all current Server Logic documentation from Microsoft Learn before writing any code",{"type":49,"tag":54,"props":2446,"children":2447},{},[2448],{"type":62,"value":2449},"This step is critical because Server Logic is a preview feature and the SDK surface may change. The documentation on Microsoft Learn is the authoritative source.",{"type":49,"tag":54,"props":2451,"children":2452},{},[2453,2457],{"type":49,"tag":58,"props":2454,"children":2455},{},[2456],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":2459,"children":2461},{"id":2460},"_31-follow-the-documentation-reference",[2462],{"type":62,"value":2463},"3.1 Follow the Documentation Reference",{"type":49,"tag":54,"props":2465,"children":2466},{},[2467],{"type":62,"value":2468},"Use the reference document below as the source of truth for how to discover, classify, fetch, and reconcile Server Logic documentation:",{"type":49,"tag":50,"props":2470,"children":2471},{},[2472],{"type":49,"tag":54,"props":2473,"children":2474},{},[2475,2477],{"type":62,"value":2476},"Reference: ",{"type":49,"tag":67,"props":2478,"children":2480},{"className":2479},[],[2481],{"type":62,"value":2482},"${PLUGIN_ROOT}\u002Fskills\u002Fadd-server-logic\u002Freferences\u002Fserver-logic-docs.md",{"type":49,"tag":54,"props":2484,"children":2485},{},[2486],{"type":62,"value":2487},"Follow that reference to:",{"type":49,"tag":94,"props":2489,"children":2490},{},[2491,2496,2501,2506],{"type":49,"tag":98,"props":2492,"children":2493},{},[2494],{"type":62,"value":2495},"Search Microsoft Learn dynamically for all current Server Logic docs",{"type":49,"tag":98,"props":2497,"children":2498},{},[2499],{"type":62,"value":2500},"Fetch the core reference pages and any relevant scenario-specific pages",{"type":49,"tag":98,"props":2502,"children":2503},{},[2504],{"type":62,"value":2505},"Search for current code samples",{"type":49,"tag":98,"props":2507,"children":2508},{},[2509],{"type":62,"value":2510},"Reconcile the discovered documentation with the known SDK baseline in the reference",{"type":49,"tag":487,"props":2512,"children":2514},{"id":2513},"_32-extract-task-specific-notes",[2515],{"type":62,"value":2516},"3.2 Extract Task-Specific Notes",{"type":49,"tag":54,"props":2518,"children":2519},{},[2520],{"type":62,"value":2521},"From the fetched docs, extract and note the items that matter for the current task:",{"type":49,"tag":94,"props":2523,"children":2524},{},[2525,2530,2535,2540,2545,2550],{"type":49,"tag":98,"props":2526,"children":2527},{},[2528],{"type":62,"value":2529},"All SDK method signatures, parameter types, and return types",{"type":49,"tag":98,"props":2531,"children":2532},{},[2533],{"type":62,"value":2534},"Current supported HTTP methods and function signatures",{"type":49,"tag":98,"props":2536,"children":2537},{},[2538],{"type":62,"value":2539},"Site settings and their defaults",{"type":49,"tag":98,"props":2541,"children":2542},{},[2543],{"type":62,"value":2544},"Security model (web roles, table permissions, CSRF)",{"type":49,"tag":98,"props":2546,"children":2547},{},[2548],{"type":62,"value":2549},"Client-side calling patterns and response format",{"type":49,"tag":98,"props":2551,"children":2552},{},[2553],{"type":62,"value":2554},"Any new methods or breaking changes discovered in Microsoft Learn",{"type":49,"tag":54,"props":2556,"children":2557},{},[2558,2562],{"type":49,"tag":58,"props":2559,"children":2560},{},[2561],{"type":62,"value":993},{"type":62,"value":2563},": Up-to-date SDK reference verified against all relevant Microsoft Learn documentation pages",{"type":49,"tag":281,"props":2565,"children":2566},{},[],{"type":49,"tag":87,"props":2568,"children":2570},{"id":2569},"phase-4-review-implementation-plan",[2571],{"type":62,"value":2572},"Phase 4: Review Implementation Plan",{"type":49,"tag":54,"props":2574,"children":2575},{},[2576,2580],{"type":49,"tag":58,"props":2577,"children":2578},{},[2579],{"type":62,"value":456},{"type":62,"value":2581},": Present the implementation plan to the user and confirm before writing any code",{"type":49,"tag":54,"props":2583,"children":2584},{},[2585,2589],{"type":49,"tag":58,"props":2586,"children":2587},{},[2588],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":2591,"children":2593},{"id":2592},"_41-prepare-the-plan-data",[2594],{"type":62,"value":2595},"4.1 Prepare the Plan Data",{"type":49,"tag":54,"props":2597,"children":2598},{},[2599],{"type":62,"value":2600},"Build the server logic plan data and render the HTML plan before asking for approval.",{"type":49,"tag":50,"props":2602,"children":2603},{},[2604],{"type":49,"tag":54,"props":2605,"children":2606},{},[2607,2608],{"type":62,"value":2476},{"type":49,"tag":67,"props":2609,"children":2611},{"className":2610},[],[2612],{"type":62,"value":2613},"${PLUGIN_ROOT}\u002Fskills\u002Fadd-server-logic\u002Freferences\u002Fserver-logic-plan-data-format.md",{"type":49,"tag":54,"props":2615,"children":2616},{},[2617],{"type":62,"value":2618},"The rendered plan should summarize:",{"type":49,"tag":94,"props":2620,"children":2621},{},[2622,2627,2632,2637,2642,2647,2682],{"type":49,"tag":98,"props":2623,"children":2624},{},[2625],{"type":62,"value":2626},"The number of server logic items being created or reused",{"type":49,"tag":98,"props":2628,"children":2629},{},[2630],{"type":62,"value":2631},"Each endpoint name, API URL, and files to be created",{"type":49,"tag":98,"props":2633,"children":2634},{},[2635],{"type":62,"value":2636},"The functions that will be implemented and what each one does",{"type":49,"tag":98,"props":2638,"children":2639},{},[2640],{"type":62,"value":2641},"The SDK features, external services, and Dataverse tables involved for each item",{"type":49,"tag":98,"props":2643,"children":2644},{},[2645],{"type":62,"value":2646},"The web roles, security constraints, and site settings that apply to each item",{"type":49,"tag":98,"props":2648,"children":2649},{},[2650,2652,2658,2660,2666,2668,2673,2675,2681],{"type":62,"value":2651},"Any secrets or sensitive values that will be stored as environment variables (with or without Azure Key Vault). If the user chose Azure Key Vault in Phase 2.3.1, populate ",{"type":49,"tag":67,"props":2653,"children":2655},{"className":2654},[],[2656],{"type":62,"value":2657},"SECRETS_DATA",{"type":62,"value":2659}," with ",{"type":49,"tag":67,"props":2661,"children":2663},{"className":2662},[],[2664],{"type":62,"value":2665},"useKeyVault: true",{"type":62,"value":2667}," and the list of secrets — the HTML plan will render a Key Vault banner explaining the security benefits and show which secrets each server logic depends on. If no secrets are needed, set ",{"type":49,"tag":67,"props":2669,"children":2671},{"className":2670},[],[2672],{"type":62,"value":2657},{"type":62,"value":2674}," to ",{"type":49,"tag":67,"props":2676,"children":2678},{"className":2677},[],[2679],{"type":62,"value":2680},"null",{"type":62,"value":523},{"type":49,"tag":98,"props":2683,"children":2684},{},[2685],{"type":62,"value":2686},"The expected next steps after approval",{"type":49,"tag":487,"props":2688,"children":2690},{"id":2689},"_42-render-the-html-plan",[2691],{"type":62,"value":2692},"4.2 Render the HTML Plan",{"type":49,"tag":54,"props":2694,"children":2695},{},[2696],{"type":62,"value":2697},"Generate the HTML plan file from the template and open it in the user's default browser before asking for approval.",{"type":49,"tag":54,"props":2699,"children":2700},{},[2701],{"type":62,"value":2702},"When working inside a Power Pages project, write the plan to:",{"type":49,"tag":1335,"props":2704,"children":2708},{"className":2705,"code":2707,"language":62,"meta":1340},[2706],"language-text","\u003CPROJECT_ROOT>\u002Fdocs\u002Fserverlogic-plan.html\n",[2709],{"type":49,"tag":67,"props":2710,"children":2711},{"__ignoreMap":1340},[2712],{"type":62,"value":2707},{"type":49,"tag":54,"props":2714,"children":2715},{},[2716,2718,2724],{"type":62,"value":2717},"Create the ",{"type":49,"tag":67,"props":2719,"children":2721},{"className":2720},[],[2722],{"type":62,"value":2723},"docs\u002F",{"type":62,"value":2725}," folder if it does not already exist. Keep this HTML file inside the repository so it can be reviewed and committed with the rest of the server logic work.",{"type":49,"tag":54,"props":2727,"children":2728},{},[2729,2731,2736],{"type":62,"value":2730},"Do ",{"type":49,"tag":58,"props":2732,"children":2733},{},[2734],{"type":62,"value":2735},"not",{"type":62,"value":2737}," hand-author the HTML. Use the render script:",{"type":49,"tag":1335,"props":2739,"children":2741},{"className":1337,"code":2740,"language":1339,"meta":1340,"style":1340},"node \"${PLUGIN_ROOT}\u002Fscripts\u002Frender-serverlogic-plan.js\" --output \"\u003COUTPUT_PATH>\" --data \"\u003CDATA_JSON_PATH>\"\n",[2742],{"type":49,"tag":67,"props":2743,"children":2744},{"__ignoreMap":1340},[2745],{"type":49,"tag":1346,"props":2746,"children":2747},{"class":1348,"line":1349},[2748,2752,2756,2760,2764,2769,2773,2778,2782,2787,2791,2796,2800,2805],{"type":49,"tag":1346,"props":2749,"children":2750},{"style":1353},[2751],{"type":62,"value":1356},{"type":49,"tag":1346,"props":2753,"children":2754},{"style":1359},[2755],{"type":62,"value":1362},{"type":49,"tag":1346,"props":2757,"children":2758},{"style":1365},[2759],{"type":62,"value":1368},{"type":49,"tag":1346,"props":2761,"children":2762},{"style":1359},[2763],{"type":62,"value":1373},{"type":49,"tag":1346,"props":2765,"children":2766},{"style":1376},[2767],{"type":62,"value":2768},"\u002Fscripts\u002Frender-serverlogic-plan.js",{"type":49,"tag":1346,"props":2770,"children":2771},{"style":1359},[2772],{"type":62,"value":1384},{"type":49,"tag":1346,"props":2774,"children":2775},{"style":1376},[2776],{"type":62,"value":2777}," --output",{"type":49,"tag":1346,"props":2779,"children":2780},{"style":1359},[2781],{"type":62,"value":1389},{"type":49,"tag":1346,"props":2783,"children":2784},{"style":1376},[2785],{"type":62,"value":2786},"\u003COUTPUT_PATH>",{"type":49,"tag":1346,"props":2788,"children":2789},{"style":1359},[2790],{"type":62,"value":1384},{"type":49,"tag":1346,"props":2792,"children":2793},{"style":1376},[2794],{"type":62,"value":2795}," --data",{"type":49,"tag":1346,"props":2797,"children":2798},{"style":1359},[2799],{"type":62,"value":1389},{"type":49,"tag":1346,"props":2801,"children":2802},{"style":1376},[2803],{"type":62,"value":2804},"\u003CDATA_JSON_PATH>",{"type":49,"tag":1346,"props":2806,"children":2807},{"style":1359},[2808],{"type":62,"value":1399},{"type":49,"tag":54,"props":2810,"children":2811},{},[2812,2814,2820,2822,2828,2829,2835,2837,2843],{"type":62,"value":2813},"The render script refuses to overwrite existing files. Before calling it, check if the default output path (",{"type":49,"tag":67,"props":2815,"children":2817},{"className":2816},[],[2818],{"type":62,"value":2819},"\u003CPROJECT_ROOT>\u002Fdocs\u002Fserverlogic-plan.html",{"type":62,"value":2821},") already exists. If it does, choose a new descriptive filename based on context — e.g., ",{"type":49,"tag":67,"props":2823,"children":2825},{"className":2824},[],[2826],{"type":62,"value":2827},"serverlogic-plan-exchange-rate.html",{"type":62,"value":125},{"type":49,"tag":67,"props":2830,"children":2832},{"className":2831},[],[2833],{"type":62,"value":2834},"serverlogic-plan-apr-2026.html",{"type":62,"value":2836},". Pass the chosen name via ",{"type":49,"tag":67,"props":2838,"children":2840},{"className":2839},[],[2841],{"type":62,"value":2842},"--output",{"type":62,"value":523},{"type":49,"tag":487,"props":2845,"children":2847},{"id":2846},"_43-present-plan-summary",[2848],{"type":62,"value":2849},"4.3 Present Plan Summary",{"type":49,"tag":54,"props":2851,"children":2852},{},[2853,2854,2858],{"type":62,"value":2730},{"type":49,"tag":58,"props":2855,"children":2856},{},[2857],{"type":62,"value":2735},{"type":62,"value":2859}," present a second detailed plan in the CLI. The HTML file is the single detailed plan artifact.",{"type":49,"tag":54,"props":2861,"children":2862},{},[2863],{"type":62,"value":2864},"In the CLI, give only a brief summary that points the user to the HTML plan open in the browser. Keep it to:",{"type":49,"tag":94,"props":2866,"children":2867},{},[2868,2873,2878,2883,2888],{"type":49,"tag":98,"props":2869,"children":2870},{},[2871],{"type":62,"value":2872},"Total server logic count",{"type":49,"tag":98,"props":2874,"children":2875},{},[2876],{"type":62,"value":2877},"Whether the plan is creating, updating, or reusing items",{"type":49,"tag":98,"props":2879,"children":2880},{},[2881],{"type":62,"value":2882},"Whether web roles, table permissions, or site settings are involved",{"type":49,"tag":98,"props":2884,"children":2885},{},[2886],{"type":62,"value":2887},"The actual output path returned by the render script",{"type":49,"tag":98,"props":2889,"children":2890},{},[2891],{"type":62,"value":2892},"A note that the browser-opened HTML contains the full details",{"type":49,"tag":54,"props":2894,"children":2895},{},[2896],{"type":62,"value":2897},"Do not restate the per-server-logic breakdown, rationale, role assignments, or function details inline in the CLI unless the user explicitly asks for a text version. Tell the user where the detailed HTML plan file was saved, that it has been opened in the browser for review, and that the repo copy of the plan will be committed with the implementation artifacts unless the user asks to discard it.",{"type":49,"tag":487,"props":2899,"children":2901},{"id":2900},"_44-confirm-with-user",[2902],{"type":62,"value":2903},"4.4 Confirm with User",{"type":49,"tag":50,"props":2905,"children":2906},{},[2907,2932],{"type":49,"tag":54,"props":2908,"children":2909},{},[2910,2911,2916,2918,2923,2925,2930],{"type":62,"value":831},{"type":49,"tag":58,"props":2912,"children":2913},{},[2914],{"type":62,"value":2915},"Gate (plan · add-server-logic:4.4.plan-approval):",{"type":62,"value":2917}," Final sign-off on the rendered HTML plan before Phase 5 writes any ",{"type":49,"tag":67,"props":2919,"children":2921},{"className":2920},[],[2922],{"type":62,"value":357},{"type":62,"value":2924}," \u002F ",{"type":49,"tag":67,"props":2926,"children":2928},{"className":2927},[],[2929],{"type":62,"value":349},{"type":62,"value":2931}," files or Phase 7 creates env vars.",{"type":49,"tag":54,"props":2933,"children":2934},{},[2935,2939,2941,2945,2947,2951],{"type":49,"tag":58,"props":2936,"children":2937},{},[2938],{"type":62,"value":853},{"type":62,"value":2940}," Phase 4.2 rendered the HTML plan; Phase 4.3 surfaced the CLI summary.\n",{"type":49,"tag":58,"props":2942,"children":2943},{},[2944],{"type":62,"value":867},{"type":62,"value":2946}," Server logic files committed under wrong names \u002F wrong roles; env var definitions created against the wrong secret-storage mode.\n",{"type":49,"tag":58,"props":2948,"children":2949},{},[2950],{"type":62,"value":889},{"type":62,"value":891},{"type":49,"tag":54,"props":2953,"children":2954},{},[2955,2956,2961],{"type":62,"value":896},{"type":49,"tag":67,"props":2957,"children":2959},{"className":2958},[],[2960],{"type":62,"value":902},{"type":62,"value":468},{"type":49,"tag":905,"props":2963,"children":2964},{},[2965,2979],{"type":49,"tag":909,"props":2966,"children":2967},{},[2968],{"type":49,"tag":913,"props":2969,"children":2970},{},[2971,2975],{"type":49,"tag":917,"props":2972,"children":2973},{},[2974],{"type":62,"value":921},{"type":49,"tag":917,"props":2976,"children":2977},{},[2978],{"type":62,"value":926},{"type":49,"tag":928,"props":2980,"children":2981},{},[2982],{"type":49,"tag":913,"props":2983,"children":2984},{},[2985,2990],{"type":49,"tag":935,"props":2986,"children":2987},{},[2988],{"type":62,"value":2989},"Here's the implementation plan for this server logic work. Does it look correct?",{"type":49,"tag":935,"props":2991,"children":2992},{},[2993],{"type":62,"value":2994},"Approve and implement (Recommended), Request changes, Cancel",{"type":49,"tag":54,"props":2996,"children":2997},{},[2998,3003],{"type":49,"tag":58,"props":2999,"children":3000},{},[3001],{"type":62,"value":3002},"If \"Request changes\"",{"type":62,"value":3004},": Ask what needs to change, update the plan, and present again.",{"type":49,"tag":54,"props":3006,"children":3007},{},[3008,3012],{"type":49,"tag":58,"props":3009,"children":3010},{},[3011],{"type":62,"value":977},{"type":62,"value":3013},": Stop the workflow.",{"type":49,"tag":54,"props":3015,"children":3016},{},[3017,3021],{"type":49,"tag":58,"props":3018,"children":3019},{},[3020],{"type":62,"value":993},{"type":62,"value":3022},": User-approved implementation plan",{"type":49,"tag":281,"props":3024,"children":3025},{},[],{"type":49,"tag":87,"props":3027,"children":3029},{"id":3028},"phase-5-implement-server-logic",[3030],{"type":62,"value":3031},"Phase 5: Implement Server Logic",{"type":49,"tag":54,"props":3033,"children":3034},{},[3035,3039,3041,3046],{"type":49,"tag":58,"props":3036,"children":3037},{},[3038],{"type":62,"value":456},{"type":62,"value":3040},": Create each approved server logic ",{"type":49,"tag":67,"props":3042,"children":3044},{"className":3043},[],[3045],{"type":62,"value":349},{"type":62,"value":3047}," file and metadata YAML following the constraints verified in Phase 3",{"type":49,"tag":54,"props":3049,"children":3050},{},[3051,3055],{"type":49,"tag":58,"props":3052,"children":3053},{},[3054],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":3057,"children":3059},{"id":3058},"_51-create-server-logic-folder",[3060],{"type":62,"value":3061},"5.1 Create Server Logic Folder",{"type":49,"tag":54,"props":3063,"children":3064},{},[3065],{"type":62,"value":3066},"For each approved server logic item:",{"type":49,"tag":94,"props":3068,"children":3069},{},[3070,3086,3116],{"type":49,"tag":98,"props":3071,"children":3072},{},[3073,3084],{"type":49,"tag":58,"props":3074,"children":3075},{},[3076,3078],{"type":62,"value":3077},"If the approved plan says ",{"type":49,"tag":67,"props":3079,"children":3081},{"className":3080},[],[3082],{"type":62,"value":3083},"reuse",{"type":62,"value":3085},": Do not create a new folder. Reuse the existing server logic as-is and only update the surrounding integration work if needed.",{"type":49,"tag":98,"props":3087,"children":3088},{},[3089,3101,3103,3108,3109,3114],{"type":49,"tag":58,"props":3090,"children":3091},{},[3092,3093,3099],{"type":62,"value":3077},{"type":49,"tag":67,"props":3094,"children":3096},{"className":3095},[],[3097],{"type":62,"value":3098},"update",{"type":62,"value":3100}," \u002F extend",{"type":62,"value":3102},": Reuse the existing folder and update the existing ",{"type":49,"tag":67,"props":3104,"children":3106},{"className":3105},[],[3107],{"type":62,"value":349},{"type":62,"value":2924},{"type":49,"tag":67,"props":3110,"children":3112},{"className":3111},[],[3113],{"type":62,"value":357},{"type":62,"value":3115}," files rather than creating duplicates.",{"type":49,"tag":98,"props":3117,"children":3118},{},[3119,3129,3131,3136,3138,3144],{"type":49,"tag":58,"props":3120,"children":3121},{},[3122,3123],{"type":62,"value":3077},{"type":49,"tag":67,"props":3124,"children":3126},{"className":3125},[],[3127],{"type":62,"value":3128},"create",{"type":62,"value":3130},": Create the folder inside ",{"type":49,"tag":67,"props":3132,"children":3134},{"className":3133},[],[3135],{"type":62,"value":267},{"type":62,"value":3137}," (note: singular ",{"type":49,"tag":67,"props":3139,"children":3141},{"className":3140},[],[3142],{"type":62,"value":3143},"server-logic",{"type":62,"value":3145},", no trailing 's'). Ensure the folder name matches that endpoint name exactly.",{"type":49,"tag":487,"props":3147,"children":3149},{"id":3148},"_52-read-or-create-web-roles",[3150],{"type":62,"value":3151},"5.2 Read or Create Web Roles",{"type":49,"tag":54,"props":3153,"children":3154},{},[3155,3156,3161],{"type":62,"value":578},{"type":49,"tag":58,"props":3157,"children":3158},{},[3159],{"type":62,"value":3160},"Create Web Role",{"type":62,"value":3162}," skill to determine which web roles are required for the approved server logic plan and to create any missing roles before writing metadata.",{"type":49,"tag":54,"props":3164,"children":3165},{},[3166,3167,3171],{"type":62,"value":2730},{"type":49,"tag":58,"props":3168,"children":3169},{},[3170],{"type":62,"value":2735},{"type":62,"value":3172}," assume every server logic should get every available role. Instead, determine the minimum set of roles required for each server logic based on its purpose, security model, and the approved plan.",{"type":49,"tag":54,"props":3174,"children":3175},{},[3176],{"type":62,"value":3177},"Example web role file content:",{"type":49,"tag":1335,"props":3179,"children":3183},{"className":3180,"code":3181,"language":3182,"meta":1340,"style":1340},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","adx_anonymoususersrole: false\nadx_authenticatedusersrole: true\ndescription: Role for authenticated users\nid: a1b2c3d4-e5f6-7890-abcd-ef1234567890\nname: Authenticated Users\n","yaml",[3184],{"type":49,"tag":67,"props":3185,"children":3186},{"__ignoreMap":1340},[3187,3206,3224,3241,3259],{"type":49,"tag":1346,"props":3188,"children":3189},{"class":1348,"line":1349},[3190,3196,3200],{"type":49,"tag":1346,"props":3191,"children":3193},{"style":3192},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[3194],{"type":62,"value":3195},"adx_anonymoususersrole",{"type":49,"tag":1346,"props":3197,"children":3198},{"style":1359},[3199],{"type":62,"value":468},{"type":49,"tag":1346,"props":3201,"children":3203},{"style":3202},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[3204],{"type":62,"value":3205}," false\n",{"type":49,"tag":1346,"props":3207,"children":3209},{"class":1348,"line":3208},2,[3210,3215,3219],{"type":49,"tag":1346,"props":3211,"children":3212},{"style":3192},[3213],{"type":62,"value":3214},"adx_authenticatedusersrole",{"type":49,"tag":1346,"props":3216,"children":3217},{"style":1359},[3218],{"type":62,"value":468},{"type":49,"tag":1346,"props":3220,"children":3221},{"style":3202},[3222],{"type":62,"value":3223}," true\n",{"type":49,"tag":1346,"props":3225,"children":3227},{"class":1348,"line":3226},3,[3228,3232,3236],{"type":49,"tag":1346,"props":3229,"children":3230},{"style":3192},[3231],{"type":62,"value":1465},{"type":49,"tag":1346,"props":3233,"children":3234},{"style":1359},[3235],{"type":62,"value":468},{"type":49,"tag":1346,"props":3237,"children":3238},{"style":1376},[3239],{"type":62,"value":3240}," Role for authenticated users\n",{"type":49,"tag":1346,"props":3242,"children":3244},{"class":1348,"line":3243},4,[3245,3250,3254],{"type":49,"tag":1346,"props":3246,"children":3247},{"style":3192},[3248],{"type":62,"value":3249},"id",{"type":49,"tag":1346,"props":3251,"children":3252},{"style":1359},[3253],{"type":62,"value":468},{"type":49,"tag":1346,"props":3255,"children":3256},{"style":1376},[3257],{"type":62,"value":3258}," a1b2c3d4-e5f6-7890-abcd-ef1234567890\n",{"type":49,"tag":1346,"props":3260,"children":3262},{"class":1348,"line":3261},5,[3263,3267,3271],{"type":49,"tag":1346,"props":3264,"children":3265},{"style":3192},[3266],{"type":62,"value":1451},{"type":49,"tag":1346,"props":3268,"children":3269},{"style":1359},[3270],{"type":62,"value":468},{"type":49,"tag":1346,"props":3272,"children":3273},{"style":1376},[3274],{"type":62,"value":3275}," Authenticated Users\n",{"type":49,"tag":54,"props":3277,"children":3278},{},[3279,3281,3285],{"type":62,"value":3280},"In the skill workflow, explicitly invoke the ",{"type":49,"tag":58,"props":3282,"children":3283},{},[3284],{"type":62,"value":3160},{"type":62,"value":3286}," skill when:",{"type":49,"tag":94,"props":3288,"children":3289},{},[3290,3295,3300],{"type":49,"tag":98,"props":3291,"children":3292},{},[3293],{"type":62,"value":3294},"The site has no suitable existing web roles",{"type":49,"tag":98,"props":3296,"children":3297},{},[3298],{"type":62,"value":3299},"The approved plan includes proposed roles that do not exist yet",{"type":49,"tag":98,"props":3301,"children":3302},{},[3303],{"type":62,"value":3304},"The role assignments need to be refined before metadata can be created",{"type":49,"tag":54,"props":3306,"children":3307},{},[3308,3310,3315,3316,3321],{"type":62,"value":3309},"After the Create Web Role skill completes, read the resulting web role YAML files and collect the ",{"type":49,"tag":67,"props":3311,"children":3313},{"className":3312},[],[3314],{"type":62,"value":3249},{"type":62,"value":351},{"type":49,"tag":67,"props":3317,"children":3319},{"className":3318},[],[3320],{"type":62,"value":1451},{"type":62,"value":3322}," values needed for each server logic's metadata YAML.",{"type":49,"tag":487,"props":3324,"children":3326},{"id":3325},"_53-create-the-server-logic-file",[3327],{"type":62,"value":3328},"5.3 Create the Server Logic File",{"type":49,"tag":54,"props":3330,"children":3331},{},[3332,3334,3340,3342,3347,3348,3353,3354,3359],{"type":62,"value":3333},"Repeat this step for each approved server logic item. Create or update ",{"type":49,"tag":67,"props":3335,"children":3337},{"className":3336},[],[3338],{"type":62,"value":3339},"\u003CPROJECT_ROOT>\u002F.powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F\u003Cname>.js",{"type":62,"value":3341}," according to the approved plan status (",{"type":49,"tag":67,"props":3343,"children":3345},{"className":3344},[],[3346],{"type":62,"value":3128},{"type":62,"value":125},{"type":49,"tag":67,"props":3349,"children":3351},{"className":3350},[],[3352],{"type":62,"value":3098},{"type":62,"value":1512},{"type":49,"tag":67,"props":3355,"children":3357},{"className":3356},[],[3358],{"type":62,"value":3083},{"type":62,"value":3360},") and follow these mandatory patterns:",{"type":49,"tag":3362,"props":3363,"children":3365},"h4",{"id":3364},"structure-rules",[3366],{"type":62,"value":3367},"Structure Rules",{"type":49,"tag":291,"props":3369,"children":3370},{},[3371,3412,3429,3439,3464,3489,3531],{"type":49,"tag":98,"props":3372,"children":3373},{},[3374,3379,3381,3386,3387,3392,3393,3398,3399,3404,3405,3410],{"type":49,"tag":58,"props":3375,"children":3376},{},[3377],{"type":62,"value":3378},"Only top-level functions",{"type":62,"value":3380},": The file can only contain these 5 functions at the top level: ",{"type":49,"tag":67,"props":3382,"children":3384},{"className":3383},[],[3385],{"type":62,"value":156},{"type":62,"value":125},{"type":49,"tag":67,"props":3388,"children":3390},{"className":3389},[],[3391],{"type":62,"value":163},{"type":62,"value":125},{"type":49,"tag":67,"props":3394,"children":3396},{"className":3395},[],[3397],{"type":62,"value":170},{"type":62,"value":125},{"type":49,"tag":67,"props":3400,"children":3402},{"className":3401},[],[3403],{"type":62,"value":177},{"type":62,"value":125},{"type":49,"tag":67,"props":3406,"children":3408},{"className":3407},[],[3409],{"type":62,"value":184},{"type":62,"value":3411},". Only include the functions the user needs.",{"type":49,"tag":98,"props":3413,"children":3414},{},[3415,3420,3422,3427],{"type":49,"tag":58,"props":3416,"children":3417},{},[3418],{"type":62,"value":3419},"Each function returns a string",{"type":62,"value":3421},": Use ",{"type":49,"tag":67,"props":3423,"children":3425},{"className":3424},[],[3426],{"type":62,"value":210},{"type":62,"value":3428}," for objects\u002Farrays.",{"type":49,"tag":98,"props":3430,"children":3431},{},[3432,3437],{"type":49,"tag":58,"props":3433,"children":3434},{},[3435],{"type":62,"value":3436},"Each function has try\u002Fcatch",{"type":62,"value":3438},": Every function must wrap its logic in a try\u002Fcatch block.",{"type":49,"tag":98,"props":3440,"children":3441},{},[3442,3447,3448,3454,3456,3462],{"type":49,"tag":58,"props":3443,"children":3444},{},[3445],{"type":62,"value":3446},"Each function logs",{"type":62,"value":3421},{"type":49,"tag":67,"props":3449,"children":3451},{"className":3450},[],[3452],{"type":62,"value":3453},"Server.Logger.Log()",{"type":62,"value":3455}," at entry and ",{"type":49,"tag":67,"props":3457,"children":3459},{"className":3458},[],[3460],{"type":62,"value":3461},"Server.Logger.Error()",{"type":62,"value":3463}," in catch blocks.",{"type":49,"tag":98,"props":3465,"children":3466},{},[3467,3472,3474,3480,3481,3487],{"type":49,"tag":58,"props":3468,"children":3469},{},[3470],{"type":62,"value":3471},"No imports or requires",{"type":62,"value":3473},": No ",{"type":49,"tag":67,"props":3475,"children":3477},{"className":3476},[],[3478],{"type":62,"value":3479},"import",{"type":62,"value":125},{"type":49,"tag":67,"props":3482,"children":3484},{"className":3483},[],[3485],{"type":62,"value":3486},"require",{"type":62,"value":3488},", or external dependencies.",{"type":49,"tag":98,"props":3490,"children":3491},{},[3492,3497,3498,3503,3504,3509,3510,3515,3516,3522,3523,3529],{"type":49,"tag":58,"props":3493,"children":3494},{},[3495],{"type":62,"value":3496},"No browser APIs",{"type":62,"value":3473},{"type":49,"tag":67,"props":3499,"children":3501},{"className":3500},[],[3502],{"type":62,"value":123},{"type":62,"value":125},{"type":49,"tag":67,"props":3505,"children":3507},{"className":3506},[],[3508],{"type":62,"value":131},{"type":62,"value":125},{"type":49,"tag":67,"props":3511,"children":3513},{"className":3512},[],[3514],{"type":62,"value":138},{"type":62,"value":125},{"type":49,"tag":67,"props":3517,"children":3519},{"className":3518},[],[3520],{"type":62,"value":3521},"setInterval",{"type":62,"value":125},{"type":49,"tag":67,"props":3524,"children":3526},{"className":3525},[],[3527],{"type":62,"value":3528},"console.log",{"type":62,"value":3530},", or DOM APIs.",{"type":49,"tag":98,"props":3532,"children":3533},{},[3534,3539,3541,3547,3549,3555,3557,3563,3565,3570,3572,3577,3578,3583],{"type":49,"tag":58,"props":3535,"children":3536},{},[3537],{"type":62,"value":3538},"Async when needed",{"type":62,"value":3540},": Mark functions as ",{"type":49,"tag":67,"props":3542,"children":3544},{"className":3543},[],[3545],{"type":62,"value":3546},"async",{"type":62,"value":3548}," only when they use ",{"type":49,"tag":67,"props":3550,"children":3552},{"className":3551},[],[3553],{"type":62,"value":3554},"await",{"type":62,"value":3556}," (HttpClient calls). Dataverse connector methods (",{"type":49,"tag":67,"props":3558,"children":3560},{"className":3559},[],[3561],{"type":62,"value":3562},"Server.Connector.Dataverse.*",{"type":62,"value":3564},") are ",{"type":49,"tag":58,"props":3566,"children":3567},{},[3568],{"type":62,"value":3569},"synchronous",{"type":62,"value":3571}," — do NOT use ",{"type":49,"tag":67,"props":3573,"children":3575},{"className":3574},[],[3576],{"type":62,"value":3546},{"type":62,"value":876},{"type":49,"tag":67,"props":3579,"children":3581},{"className":3580},[],[3582],{"type":62,"value":3554},{"type":62,"value":3584}," with them.",{"type":49,"tag":3362,"props":3586,"children":3588},{"id":3587},"prohibited-script-patterns",[3589],{"type":62,"value":3590},"Prohibited Script Patterns",{"type":49,"tag":54,"props":3592,"children":3593},{},[3594,3596,3602],{"type":62,"value":3595},"The Power Pages server-side script validator rejects scripts containing certain patterns at runtime. Violations surface as ",{"type":49,"tag":67,"props":3597,"children":3599},{"className":3598},[],[3600],{"type":62,"value":3601},"RTSL01: Script validation failed: prohibited pattern found - Pattern: \u003Cregex>",{"type":62,"value":3603}," in diagnostics, and the function silently falls through without executing user code.",{"type":49,"tag":905,"props":3605,"children":3606},{},[3607,3628],{"type":49,"tag":909,"props":3608,"children":3609},{},[3610],{"type":49,"tag":913,"props":3611,"children":3612},{},[3613,3618,3623],{"type":49,"tag":917,"props":3614,"children":3615},{},[3616],{"type":62,"value":3617},"Pattern",{"type":49,"tag":917,"props":3619,"children":3620},{},[3621],{"type":62,"value":3622},"Regex",{"type":49,"tag":917,"props":3624,"children":3625},{},[3626],{"type":62,"value":3627},"Caveat",{"type":49,"tag":928,"props":3629,"children":3630},{},[3631],{"type":49,"tag":913,"props":3632,"children":3633},{},[3634,3647,3656],{"type":49,"tag":935,"props":3635,"children":3636},{},[3637,3639,3645],{"type":62,"value":3638},"JavaScript ",{"type":49,"tag":67,"props":3640,"children":3642},{"className":3641},[],[3643],{"type":62,"value":3644},"with",{"type":62,"value":3646}," statement",{"type":49,"tag":935,"props":3648,"children":3649},{},[3650],{"type":49,"tag":67,"props":3651,"children":3653},{"className":3652},[],[3654],{"type":62,"value":3655},"with\\s*\\(",{"type":49,"tag":935,"props":3657,"children":3658},{},[3659,3661,3667,3668,3673,3675,3681,3682,3688,3689,3695,3697,3702],{"type":62,"value":3660},"The regex matches the substring ",{"type":49,"tag":67,"props":3662,"children":3664},{"className":3663},[],[3665],{"type":62,"value":3666},"with(",{"type":62,"value":838},{"type":49,"tag":58,"props":3669,"children":3670},{},[3671],{"type":62,"value":3672},"anywhere",{"type":62,"value":3674}," in the file — including inside string literals and inside other identifiers. OData filter functions like ",{"type":49,"tag":67,"props":3676,"children":3678},{"className":3677},[],[3679],{"type":62,"value":3680},"startswith(",{"type":62,"value":125},{"type":49,"tag":67,"props":3683,"children":3685},{"className":3684},[],[3686],{"type":62,"value":3687},"endswith(",{"type":62,"value":1527},{"type":49,"tag":67,"props":3690,"children":3692},{"className":3691},[],[3693],{"type":62,"value":3694},"groupwith(",{"type":62,"value":3696}," will trip it because they end with ",{"type":49,"tag":67,"props":3698,"children":3700},{"className":3699},[],[3701],{"type":62,"value":3666},{"type":62,"value":523},{"type":49,"tag":54,"props":3704,"children":3705},{},[3706,3711,3713,3718],{"type":49,"tag":58,"props":3707,"children":3708},{},[3709],{"type":62,"value":3710},"Workaround for OData functions",{"type":62,"value":3712}," — split the literal so ",{"type":49,"tag":67,"props":3714,"children":3716},{"className":3715},[],[3717],{"type":62,"value":3666},{"type":62,"value":3719}," is not contiguous in source:",{"type":49,"tag":1335,"props":3721,"children":3724},{"className":3722,"code":3723,"language":18,"meta":1340,"style":1340},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F ❌ Triggers validator: \"startswith(\" contains the substring \"with(\"\nvar query = \"$filter=startswith(name,'INV-')\";\n\n\u002F\u002F ✅ Split the literal — server still receives \"startswith(name,...)\"\nvar query = \"$filter=startswith\" + \"(name,'INV-')\";\n",[3725],{"type":49,"tag":67,"props":3726,"children":3727},{"__ignoreMap":1340},[3728,3737,3774,3782,3790],{"type":49,"tag":1346,"props":3729,"children":3730},{"class":1348,"line":1349},[3731],{"type":49,"tag":1346,"props":3732,"children":3734},{"style":3733},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[3735],{"type":62,"value":3736},"\u002F\u002F ❌ Triggers validator: \"startswith(\" contains the substring \"with(\"\n",{"type":49,"tag":1346,"props":3738,"children":3739},{"class":1348,"line":3208},[3740,3746,3751,3756,3760,3765,3769],{"type":49,"tag":1346,"props":3741,"children":3743},{"style":3742},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[3744],{"type":62,"value":3745},"var",{"type":49,"tag":1346,"props":3747,"children":3748},{"style":1365},[3749],{"type":62,"value":3750}," query ",{"type":49,"tag":1346,"props":3752,"children":3753},{"style":1359},[3754],{"type":62,"value":3755},"=",{"type":49,"tag":1346,"props":3757,"children":3758},{"style":1359},[3759],{"type":62,"value":1389},{"type":49,"tag":1346,"props":3761,"children":3762},{"style":1376},[3763],{"type":62,"value":3764},"$filter=startswith(name,'INV-')",{"type":49,"tag":1346,"props":3766,"children":3767},{"style":1359},[3768],{"type":62,"value":1384},{"type":49,"tag":1346,"props":3770,"children":3771},{"style":1359},[3772],{"type":62,"value":3773},";\n",{"type":49,"tag":1346,"props":3775,"children":3776},{"class":1348,"line":3226},[3777],{"type":49,"tag":1346,"props":3778,"children":3779},{"emptyLinePlaceholder":42},[3780],{"type":62,"value":3781},"\n",{"type":49,"tag":1346,"props":3783,"children":3784},{"class":1348,"line":3243},[3785],{"type":49,"tag":1346,"props":3786,"children":3787},{"style":3733},[3788],{"type":62,"value":3789},"\u002F\u002F ✅ Split the literal — server still receives \"startswith(name,...)\"\n",{"type":49,"tag":1346,"props":3791,"children":3792},{"class":1348,"line":3261},[3793,3797,3801,3805,3809,3814,3818,3823,3827,3832,3836],{"type":49,"tag":1346,"props":3794,"children":3795},{"style":3742},[3796],{"type":62,"value":3745},{"type":49,"tag":1346,"props":3798,"children":3799},{"style":1365},[3800],{"type":62,"value":3750},{"type":49,"tag":1346,"props":3802,"children":3803},{"style":1359},[3804],{"type":62,"value":3755},{"type":49,"tag":1346,"props":3806,"children":3807},{"style":1359},[3808],{"type":62,"value":1389},{"type":49,"tag":1346,"props":3810,"children":3811},{"style":1376},[3812],{"type":62,"value":3813},"$filter=startswith",{"type":49,"tag":1346,"props":3815,"children":3816},{"style":1359},[3817],{"type":62,"value":1384},{"type":49,"tag":1346,"props":3819,"children":3820},{"style":1359},[3821],{"type":62,"value":3822}," +",{"type":49,"tag":1346,"props":3824,"children":3825},{"style":1359},[3826],{"type":62,"value":1389},{"type":49,"tag":1346,"props":3828,"children":3829},{"style":1376},[3830],{"type":62,"value":3831},"(name,'INV-')",{"type":49,"tag":1346,"props":3833,"children":3834},{"style":1359},[3835],{"type":62,"value":1384},{"type":49,"tag":1346,"props":3837,"children":3838},{"style":1359},[3839],{"type":62,"value":3773},{"type":49,"tag":54,"props":3841,"children":3842},{},[3843,3845,3850,3851,3856,3858,3863],{"type":62,"value":3844},"The same trick applies to ",{"type":49,"tag":67,"props":3846,"children":3848},{"className":3847},[],[3849],{"type":62,"value":3687},{"type":62,"value":125},{"type":49,"tag":67,"props":3852,"children":3854},{"className":3853},[],[3855],{"type":62,"value":3694},{"type":62,"value":3857},", and any other identifier that ends with ",{"type":49,"tag":67,"props":3859,"children":3861},{"className":3860},[],[3862],{"type":62,"value":3666},{"type":62,"value":523},{"type":49,"tag":3362,"props":3865,"children":3867},{"id":3866},"code-template",[3868],{"type":62,"value":3869},"Code Template",{"type":49,"tag":1335,"props":3871,"children":3873},{"className":3722,"code":3872,"language":18,"meta":1340,"style":1340},"\u002F\u002F Server Logic: \u003Cname>\n\u002F\u002F Purpose: \u003Cdescription>\n\u002F\u002F API URL: https:\u002F\u002F\u003Csite-url>\u002F_api\u002Fserverlogics\u002F\u003Cname>\n\nfunction get() {\n    try {\n        Server.Logger.Log(\"\u003Cname> GET called\");\n\n        \u002F\u002F Access query parameters\n        \u002F\u002F const id = Server.Context.QueryParameters[\"id\"];\n\n        \u002F\u002F Your logic here...\n\n        return JSON.stringify({\n            status: \"success\",\n            method: \"GET\",\n            data: null \u002F\u002F replace with actual data\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> GET failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            method: \"GET\",\n            message: err.message\n        });\n    }\n}\n",[3874],{"type":49,"tag":67,"props":3875,"children":3876},{"__ignoreMap":1340},[3877,3885,3893,3901,3908,3931,3945,3998,4006,4015,4024,4032,4041,4049,4081,4112,4141,4164,4181,4213,4281,4309,4338,4366,4392,4408,4417],{"type":49,"tag":1346,"props":3878,"children":3879},{"class":1348,"line":1349},[3880],{"type":49,"tag":1346,"props":3881,"children":3882},{"style":3733},[3883],{"type":62,"value":3884},"\u002F\u002F Server Logic: \u003Cname>\n",{"type":49,"tag":1346,"props":3886,"children":3887},{"class":1348,"line":3208},[3888],{"type":49,"tag":1346,"props":3889,"children":3890},{"style":3733},[3891],{"type":62,"value":3892},"\u002F\u002F Purpose: \u003Cdescription>\n",{"type":49,"tag":1346,"props":3894,"children":3895},{"class":1348,"line":3226},[3896],{"type":49,"tag":1346,"props":3897,"children":3898},{"style":3733},[3899],{"type":62,"value":3900},"\u002F\u002F API URL: https:\u002F\u002F\u003Csite-url>\u002F_api\u002Fserverlogics\u002F\u003Cname>\n",{"type":49,"tag":1346,"props":3902,"children":3903},{"class":1348,"line":3243},[3904],{"type":49,"tag":1346,"props":3905,"children":3906},{"emptyLinePlaceholder":42},[3907],{"type":62,"value":3781},{"type":49,"tag":1346,"props":3909,"children":3910},{"class":1348,"line":3261},[3911,3915,3921,3926],{"type":49,"tag":1346,"props":3912,"children":3913},{"style":3742},[3914],{"type":62,"value":1488},{"type":49,"tag":1346,"props":3916,"children":3918},{"style":3917},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[3919],{"type":62,"value":3920}," get",{"type":49,"tag":1346,"props":3922,"children":3923},{"style":1359},[3924],{"type":62,"value":3925},"()",{"type":49,"tag":1346,"props":3927,"children":3928},{"style":1359},[3929],{"type":62,"value":3930}," {\n",{"type":49,"tag":1346,"props":3932,"children":3934},{"class":1348,"line":3933},6,[3935,3941],{"type":49,"tag":1346,"props":3936,"children":3938},{"style":3937},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[3939],{"type":62,"value":3940},"    try",{"type":49,"tag":1346,"props":3942,"children":3943},{"style":1359},[3944],{"type":62,"value":3930},{"type":49,"tag":1346,"props":3946,"children":3948},{"class":1348,"line":3947},7,[3949,3954,3958,3963,3967,3972,3977,3981,3986,3990,3994],{"type":49,"tag":1346,"props":3950,"children":3951},{"style":1365},[3952],{"type":62,"value":3953},"        Server",{"type":49,"tag":1346,"props":3955,"children":3956},{"style":1359},[3957],{"type":62,"value":523},{"type":49,"tag":1346,"props":3959,"children":3960},{"style":1365},[3961],{"type":62,"value":3962},"Logger",{"type":49,"tag":1346,"props":3964,"children":3965},{"style":1359},[3966],{"type":62,"value":523},{"type":49,"tag":1346,"props":3968,"children":3969},{"style":3917},[3970],{"type":62,"value":3971},"Log",{"type":49,"tag":1346,"props":3973,"children":3974},{"style":3192},[3975],{"type":62,"value":3976},"(",{"type":49,"tag":1346,"props":3978,"children":3979},{"style":1359},[3980],{"type":62,"value":1384},{"type":49,"tag":1346,"props":3982,"children":3983},{"style":1376},[3984],{"type":62,"value":3985},"\u003Cname> GET called",{"type":49,"tag":1346,"props":3987,"children":3988},{"style":1359},[3989],{"type":62,"value":1384},{"type":49,"tag":1346,"props":3991,"children":3992},{"style":3192},[3993],{"type":62,"value":1113},{"type":49,"tag":1346,"props":3995,"children":3996},{"style":1359},[3997],{"type":62,"value":3773},{"type":49,"tag":1346,"props":3999,"children":4001},{"class":1348,"line":4000},8,[4002],{"type":49,"tag":1346,"props":4003,"children":4004},{"emptyLinePlaceholder":42},[4005],{"type":62,"value":3781},{"type":49,"tag":1346,"props":4007,"children":4009},{"class":1348,"line":4008},9,[4010],{"type":49,"tag":1346,"props":4011,"children":4012},{"style":3733},[4013],{"type":62,"value":4014},"        \u002F\u002F Access query parameters\n",{"type":49,"tag":1346,"props":4016,"children":4018},{"class":1348,"line":4017},10,[4019],{"type":49,"tag":1346,"props":4020,"children":4021},{"style":3733},[4022],{"type":62,"value":4023},"        \u002F\u002F const id = Server.Context.QueryParameters[\"id\"];\n",{"type":49,"tag":1346,"props":4025,"children":4027},{"class":1348,"line":4026},11,[4028],{"type":49,"tag":1346,"props":4029,"children":4030},{"emptyLinePlaceholder":42},[4031],{"type":62,"value":3781},{"type":49,"tag":1346,"props":4033,"children":4035},{"class":1348,"line":4034},12,[4036],{"type":49,"tag":1346,"props":4037,"children":4038},{"style":3733},[4039],{"type":62,"value":4040},"        \u002F\u002F Your logic here...\n",{"type":49,"tag":1346,"props":4042,"children":4044},{"class":1348,"line":4043},13,[4045],{"type":49,"tag":1346,"props":4046,"children":4047},{"emptyLinePlaceholder":42},[4048],{"type":62,"value":3781},{"type":49,"tag":1346,"props":4050,"children":4052},{"class":1348,"line":4051},14,[4053,4058,4063,4067,4072,4076],{"type":49,"tag":1346,"props":4054,"children":4055},{"style":3937},[4056],{"type":62,"value":4057},"        return",{"type":49,"tag":1346,"props":4059,"children":4060},{"style":1365},[4061],{"type":62,"value":4062}," JSON",{"type":49,"tag":1346,"props":4064,"children":4065},{"style":1359},[4066],{"type":62,"value":523},{"type":49,"tag":1346,"props":4068,"children":4069},{"style":3917},[4070],{"type":62,"value":4071},"stringify",{"type":49,"tag":1346,"props":4073,"children":4074},{"style":3192},[4075],{"type":62,"value":3976},{"type":49,"tag":1346,"props":4077,"children":4078},{"style":1359},[4079],{"type":62,"value":4080},"{\n",{"type":49,"tag":1346,"props":4082,"children":4084},{"class":1348,"line":4083},15,[4085,4090,4094,4098,4103,4107],{"type":49,"tag":1346,"props":4086,"children":4087},{"style":3192},[4088],{"type":62,"value":4089},"            status",{"type":49,"tag":1346,"props":4091,"children":4092},{"style":1359},[4093],{"type":62,"value":468},{"type":49,"tag":1346,"props":4095,"children":4096},{"style":1359},[4097],{"type":62,"value":1389},{"type":49,"tag":1346,"props":4099,"children":4100},{"style":1376},[4101],{"type":62,"value":4102},"success",{"type":49,"tag":1346,"props":4104,"children":4105},{"style":1359},[4106],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4108,"children":4109},{"style":1359},[4110],{"type":62,"value":4111},",\n",{"type":49,"tag":1346,"props":4113,"children":4115},{"class":1348,"line":4114},16,[4116,4121,4125,4129,4133,4137],{"type":49,"tag":1346,"props":4117,"children":4118},{"style":3192},[4119],{"type":62,"value":4120},"            method",{"type":49,"tag":1346,"props":4122,"children":4123},{"style":1359},[4124],{"type":62,"value":468},{"type":49,"tag":1346,"props":4126,"children":4127},{"style":1359},[4128],{"type":62,"value":1389},{"type":49,"tag":1346,"props":4130,"children":4131},{"style":1376},[4132],{"type":62,"value":1818},{"type":49,"tag":1346,"props":4134,"children":4135},{"style":1359},[4136],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4138,"children":4139},{"style":1359},[4140],{"type":62,"value":4111},{"type":49,"tag":1346,"props":4142,"children":4144},{"class":1348,"line":4143},17,[4145,4150,4154,4159],{"type":49,"tag":1346,"props":4146,"children":4147},{"style":3192},[4148],{"type":62,"value":4149},"            data",{"type":49,"tag":1346,"props":4151,"children":4152},{"style":1359},[4153],{"type":62,"value":468},{"type":49,"tag":1346,"props":4155,"children":4156},{"style":1359},[4157],{"type":62,"value":4158}," null",{"type":49,"tag":1346,"props":4160,"children":4161},{"style":3733},[4162],{"type":62,"value":4163}," \u002F\u002F replace with actual data\n",{"type":49,"tag":1346,"props":4165,"children":4167},{"class":1348,"line":4166},18,[4168,4173,4177],{"type":49,"tag":1346,"props":4169,"children":4170},{"style":1359},[4171],{"type":62,"value":4172},"        }",{"type":49,"tag":1346,"props":4174,"children":4175},{"style":3192},[4176],{"type":62,"value":1113},{"type":49,"tag":1346,"props":4178,"children":4179},{"style":1359},[4180],{"type":62,"value":3773},{"type":49,"tag":1346,"props":4182,"children":4184},{"class":1348,"line":4183},19,[4185,4190,4195,4199,4204,4209],{"type":49,"tag":1346,"props":4186,"children":4187},{"style":1359},[4188],{"type":62,"value":4189},"    }",{"type":49,"tag":1346,"props":4191,"children":4192},{"style":3937},[4193],{"type":62,"value":4194}," catch",{"type":49,"tag":1346,"props":4196,"children":4197},{"style":3192},[4198],{"type":62,"value":1474},{"type":49,"tag":1346,"props":4200,"children":4201},{"style":1365},[4202],{"type":62,"value":4203},"err",{"type":49,"tag":1346,"props":4205,"children":4206},{"style":3192},[4207],{"type":62,"value":4208},") ",{"type":49,"tag":1346,"props":4210,"children":4211},{"style":1359},[4212],{"type":62,"value":4080},{"type":49,"tag":1346,"props":4214,"children":4216},{"class":1348,"line":4215},20,[4217,4221,4225,4229,4233,4238,4242,4246,4251,4255,4259,4264,4268,4273,4277],{"type":49,"tag":1346,"props":4218,"children":4219},{"style":1365},[4220],{"type":62,"value":3953},{"type":49,"tag":1346,"props":4222,"children":4223},{"style":1359},[4224],{"type":62,"value":523},{"type":49,"tag":1346,"props":4226,"children":4227},{"style":1365},[4228],{"type":62,"value":3962},{"type":49,"tag":1346,"props":4230,"children":4231},{"style":1359},[4232],{"type":62,"value":523},{"type":49,"tag":1346,"props":4234,"children":4235},{"style":3917},[4236],{"type":62,"value":4237},"Error",{"type":49,"tag":1346,"props":4239,"children":4240},{"style":3192},[4241],{"type":62,"value":3976},{"type":49,"tag":1346,"props":4243,"children":4244},{"style":1359},[4245],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4247,"children":4248},{"style":1376},[4249],{"type":62,"value":4250},"\u003Cname> GET failed: ",{"type":49,"tag":1346,"props":4252,"children":4253},{"style":1359},[4254],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4256,"children":4257},{"style":1359},[4258],{"type":62,"value":3822},{"type":49,"tag":1346,"props":4260,"children":4261},{"style":1365},[4262],{"type":62,"value":4263}," err",{"type":49,"tag":1346,"props":4265,"children":4266},{"style":1359},[4267],{"type":62,"value":523},{"type":49,"tag":1346,"props":4269,"children":4270},{"style":1365},[4271],{"type":62,"value":4272},"message",{"type":49,"tag":1346,"props":4274,"children":4275},{"style":3192},[4276],{"type":62,"value":1113},{"type":49,"tag":1346,"props":4278,"children":4279},{"style":1359},[4280],{"type":62,"value":3773},{"type":49,"tag":1346,"props":4282,"children":4284},{"class":1348,"line":4283},21,[4285,4289,4293,4297,4301,4305],{"type":49,"tag":1346,"props":4286,"children":4287},{"style":3937},[4288],{"type":62,"value":4057},{"type":49,"tag":1346,"props":4290,"children":4291},{"style":1365},[4292],{"type":62,"value":4062},{"type":49,"tag":1346,"props":4294,"children":4295},{"style":1359},[4296],{"type":62,"value":523},{"type":49,"tag":1346,"props":4298,"children":4299},{"style":3917},[4300],{"type":62,"value":4071},{"type":49,"tag":1346,"props":4302,"children":4303},{"style":3192},[4304],{"type":62,"value":3976},{"type":49,"tag":1346,"props":4306,"children":4307},{"style":1359},[4308],{"type":62,"value":4080},{"type":49,"tag":1346,"props":4310,"children":4312},{"class":1348,"line":4311},22,[4313,4317,4321,4325,4330,4334],{"type":49,"tag":1346,"props":4314,"children":4315},{"style":3192},[4316],{"type":62,"value":4089},{"type":49,"tag":1346,"props":4318,"children":4319},{"style":1359},[4320],{"type":62,"value":468},{"type":49,"tag":1346,"props":4322,"children":4323},{"style":1359},[4324],{"type":62,"value":1389},{"type":49,"tag":1346,"props":4326,"children":4327},{"style":1376},[4328],{"type":62,"value":4329},"error",{"type":49,"tag":1346,"props":4331,"children":4332},{"style":1359},[4333],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4335,"children":4336},{"style":1359},[4337],{"type":62,"value":4111},{"type":49,"tag":1346,"props":4339,"children":4341},{"class":1348,"line":4340},23,[4342,4346,4350,4354,4358,4362],{"type":49,"tag":1346,"props":4343,"children":4344},{"style":3192},[4345],{"type":62,"value":4120},{"type":49,"tag":1346,"props":4347,"children":4348},{"style":1359},[4349],{"type":62,"value":468},{"type":49,"tag":1346,"props":4351,"children":4352},{"style":1359},[4353],{"type":62,"value":1389},{"type":49,"tag":1346,"props":4355,"children":4356},{"style":1376},[4357],{"type":62,"value":1818},{"type":49,"tag":1346,"props":4359,"children":4360},{"style":1359},[4361],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4363,"children":4364},{"style":1359},[4365],{"type":62,"value":4111},{"type":49,"tag":1346,"props":4367,"children":4369},{"class":1348,"line":4368},24,[4370,4375,4379,4383,4387],{"type":49,"tag":1346,"props":4371,"children":4372},{"style":3192},[4373],{"type":62,"value":4374},"            message",{"type":49,"tag":1346,"props":4376,"children":4377},{"style":1359},[4378],{"type":62,"value":468},{"type":49,"tag":1346,"props":4380,"children":4381},{"style":1365},[4382],{"type":62,"value":4263},{"type":49,"tag":1346,"props":4384,"children":4385},{"style":1359},[4386],{"type":62,"value":523},{"type":49,"tag":1346,"props":4388,"children":4389},{"style":1365},[4390],{"type":62,"value":4391},"message\n",{"type":49,"tag":1346,"props":4393,"children":4395},{"class":1348,"line":4394},25,[4396,4400,4404],{"type":49,"tag":1346,"props":4397,"children":4398},{"style":1359},[4399],{"type":62,"value":4172},{"type":49,"tag":1346,"props":4401,"children":4402},{"style":3192},[4403],{"type":62,"value":1113},{"type":49,"tag":1346,"props":4405,"children":4406},{"style":1359},[4407],{"type":62,"value":3773},{"type":49,"tag":1346,"props":4409,"children":4411},{"class":1348,"line":4410},26,[4412],{"type":49,"tag":1346,"props":4413,"children":4414},{"style":1359},[4415],{"type":62,"value":4416},"    }\n",{"type":49,"tag":1346,"props":4418,"children":4420},{"class":1348,"line":4419},27,[4421],{"type":49,"tag":1346,"props":4422,"children":4423},{"style":1359},[4424],{"type":62,"value":4425},"}\n",{"type":49,"tag":3362,"props":4427,"children":4429},{"id":4428},"validate-and-execute-template",[4430],{"type":62,"value":4431},"Validate-and-Execute Template",{"type":49,"tag":54,"props":4433,"children":4434},{},[4435],{"type":62,"value":4436},"When a server logic item is identified as validate-and-execute (see Phase 2.1.1), use this pattern. The key difference: the server logic reads the current state, validates the business rule, AND writes the result to Dataverse — all in one call. The client never writes the protected field directly.",{"type":49,"tag":1335,"props":4438,"children":4440},{"className":3722,"code":4439,"language":18,"meta":1340,"style":1340},"\u002F\u002F Server Logic: \u003Cname>\n\u002F\u002F Purpose: Validate and execute \u003Cdescribe the operation>\n\u002F\u002F Pattern: Validate-and-execute — this endpoint both validates the business rule\n\u002F\u002F          and performs the Dataverse write. The client should NOT write \u003Cprotected fields>\n\u002F\u002F          via Web API — all writes to those fields go through this endpoint.\n\u002F\u002F API URL: https:\u002F\u002F\u003Csite-url>\u002F_api\u002Fserverlogics\u002F\u003Cname>\n\nfunction post() {\n    try {\n        Server.Logger.Log(\"\u003Cname> POST called\");\n\n        const body = JSON.parse(Server.Context.Body);\n        const entityId = body.entityId;\n        const targetStatus = body.targetStatus;\n\n        \u002F\u002F 1. Read the current record from Dataverse\n        const current = Server.Connector.Dataverse.RetrieveRecord(\"\u003Ctable-name>\", entityId, \"?$select=\u003Cstatus-field>\");\n        const currentStatus = current[\"\u003Cstatus-field>\"];\n\n        \u002F\u002F 2. Validate the transition\n        const allowedTransitions = {\n            \"Draft\": [\"Submitted\"],\n            \"Submitted\": [\"Approved\", \"Rejected\"],\n            \"Approved\": [\"Fulfilled\"]\n        };\n\n        const allowed = allowedTransitions[currentStatus] || [];\n        if (!allowed.includes(targetStatus)) {\n            return JSON.stringify({\n                status: \"error\",\n                message: \"Invalid transition: \" + currentStatus + \" → \" + targetStatus + \" is not allowed\",\n                currentStatus: currentStatus,\n                targetStatus: targetStatus,\n                allowedTargets: allowed\n            });\n        }\n\n        \u002F\u002F 3. Execute the write — server performs the Dataverse update\n        const updateData = {};\n        updateData[\"\u003Cstatus-field>\"] = targetStatus;\n        Server.Connector.Dataverse.UpdateRecord(\"\u003Ctable-name>\", entityId, JSON.stringify(updateData));\n\n        Server.Logger.Log(\"\u003Cname> transition executed: \" + currentStatus + \" → \" + targetStatus);\n\n        \u002F\u002F 4. Return the result — client receives confirmation, not a validation flag\n        return JSON.stringify({\n            status: \"success\",\n            previousStatus: currentStatus,\n            newStatus: targetStatus,\n            entityId: entityId\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> POST failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            message: err.message\n        });\n    }\n}\n",[4441],{"type":49,"tag":67,"props":4442,"children":4443},{"__ignoreMap":1340},[4444,4451,4459,4467,4475,4483,4490,4497,4517,4528,4576,4583,4648,4681,4714,4721,4729,4828,4875,4882,4890,4910,4957,5018,5059,5067,5074,5122,5171,5200,5229,5309,5330,5351,5369,5386,5395,5403,5412,5434,5475,5566,5574,5655,5663,5672,5700,5728,5749,5770,5788,5804,5832,5897,5925,5953,5977,5993,6001],{"type":49,"tag":1346,"props":4445,"children":4446},{"class":1348,"line":1349},[4447],{"type":49,"tag":1346,"props":4448,"children":4449},{"style":3733},[4450],{"type":62,"value":3884},{"type":49,"tag":1346,"props":4452,"children":4453},{"class":1348,"line":3208},[4454],{"type":49,"tag":1346,"props":4455,"children":4456},{"style":3733},[4457],{"type":62,"value":4458},"\u002F\u002F Purpose: Validate and execute \u003Cdescribe the operation>\n",{"type":49,"tag":1346,"props":4460,"children":4461},{"class":1348,"line":3226},[4462],{"type":49,"tag":1346,"props":4463,"children":4464},{"style":3733},[4465],{"type":62,"value":4466},"\u002F\u002F Pattern: Validate-and-execute — this endpoint both validates the business rule\n",{"type":49,"tag":1346,"props":4468,"children":4469},{"class":1348,"line":3243},[4470],{"type":49,"tag":1346,"props":4471,"children":4472},{"style":3733},[4473],{"type":62,"value":4474},"\u002F\u002F          and performs the Dataverse write. The client should NOT write \u003Cprotected fields>\n",{"type":49,"tag":1346,"props":4476,"children":4477},{"class":1348,"line":3261},[4478],{"type":49,"tag":1346,"props":4479,"children":4480},{"style":3733},[4481],{"type":62,"value":4482},"\u002F\u002F          via Web API — all writes to those fields go through this endpoint.\n",{"type":49,"tag":1346,"props":4484,"children":4485},{"class":1348,"line":3933},[4486],{"type":49,"tag":1346,"props":4487,"children":4488},{"style":3733},[4489],{"type":62,"value":3900},{"type":49,"tag":1346,"props":4491,"children":4492},{"class":1348,"line":3947},[4493],{"type":49,"tag":1346,"props":4494,"children":4495},{"emptyLinePlaceholder":42},[4496],{"type":62,"value":3781},{"type":49,"tag":1346,"props":4498,"children":4499},{"class":1348,"line":4000},[4500,4504,4509,4513],{"type":49,"tag":1346,"props":4501,"children":4502},{"style":3742},[4503],{"type":62,"value":1488},{"type":49,"tag":1346,"props":4505,"children":4506},{"style":3917},[4507],{"type":62,"value":4508}," post",{"type":49,"tag":1346,"props":4510,"children":4511},{"style":1359},[4512],{"type":62,"value":3925},{"type":49,"tag":1346,"props":4514,"children":4515},{"style":1359},[4516],{"type":62,"value":3930},{"type":49,"tag":1346,"props":4518,"children":4519},{"class":1348,"line":4008},[4520,4524],{"type":49,"tag":1346,"props":4521,"children":4522},{"style":3937},[4523],{"type":62,"value":3940},{"type":49,"tag":1346,"props":4525,"children":4526},{"style":1359},[4527],{"type":62,"value":3930},{"type":49,"tag":1346,"props":4529,"children":4530},{"class":1348,"line":4017},[4531,4535,4539,4543,4547,4551,4555,4559,4564,4568,4572],{"type":49,"tag":1346,"props":4532,"children":4533},{"style":1365},[4534],{"type":62,"value":3953},{"type":49,"tag":1346,"props":4536,"children":4537},{"style":1359},[4538],{"type":62,"value":523},{"type":49,"tag":1346,"props":4540,"children":4541},{"style":1365},[4542],{"type":62,"value":3962},{"type":49,"tag":1346,"props":4544,"children":4545},{"style":1359},[4546],{"type":62,"value":523},{"type":49,"tag":1346,"props":4548,"children":4549},{"style":3917},[4550],{"type":62,"value":3971},{"type":49,"tag":1346,"props":4552,"children":4553},{"style":3192},[4554],{"type":62,"value":3976},{"type":49,"tag":1346,"props":4556,"children":4557},{"style":1359},[4558],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4560,"children":4561},{"style":1376},[4562],{"type":62,"value":4563},"\u003Cname> POST called",{"type":49,"tag":1346,"props":4565,"children":4566},{"style":1359},[4567],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4569,"children":4570},{"style":3192},[4571],{"type":62,"value":1113},{"type":49,"tag":1346,"props":4573,"children":4574},{"style":1359},[4575],{"type":62,"value":3773},{"type":49,"tag":1346,"props":4577,"children":4578},{"class":1348,"line":4026},[4579],{"type":49,"tag":1346,"props":4580,"children":4581},{"emptyLinePlaceholder":42},[4582],{"type":62,"value":3781},{"type":49,"tag":1346,"props":4584,"children":4585},{"class":1348,"line":4034},[4586,4591,4596,4601,4605,4609,4614,4618,4623,4627,4631,4635,4640,4644],{"type":49,"tag":1346,"props":4587,"children":4588},{"style":3742},[4589],{"type":62,"value":4590},"        const",{"type":49,"tag":1346,"props":4592,"children":4593},{"style":1365},[4594],{"type":62,"value":4595}," body",{"type":49,"tag":1346,"props":4597,"children":4598},{"style":1359},[4599],{"type":62,"value":4600}," =",{"type":49,"tag":1346,"props":4602,"children":4603},{"style":1365},[4604],{"type":62,"value":4062},{"type":49,"tag":1346,"props":4606,"children":4607},{"style":1359},[4608],{"type":62,"value":523},{"type":49,"tag":1346,"props":4610,"children":4611},{"style":3917},[4612],{"type":62,"value":4613},"parse",{"type":49,"tag":1346,"props":4615,"children":4616},{"style":3192},[4617],{"type":62,"value":3976},{"type":49,"tag":1346,"props":4619,"children":4620},{"style":1365},[4621],{"type":62,"value":4622},"Server",{"type":49,"tag":1346,"props":4624,"children":4625},{"style":1359},[4626],{"type":62,"value":523},{"type":49,"tag":1346,"props":4628,"children":4629},{"style":1365},[4630],{"type":62,"value":1755},{"type":49,"tag":1346,"props":4632,"children":4633},{"style":1359},[4634],{"type":62,"value":523},{"type":49,"tag":1346,"props":4636,"children":4637},{"style":1365},[4638],{"type":62,"value":4639},"Body",{"type":49,"tag":1346,"props":4641,"children":4642},{"style":3192},[4643],{"type":62,"value":1113},{"type":49,"tag":1346,"props":4645,"children":4646},{"style":1359},[4647],{"type":62,"value":3773},{"type":49,"tag":1346,"props":4649,"children":4650},{"class":1348,"line":4043},[4651,4655,4660,4664,4668,4672,4677],{"type":49,"tag":1346,"props":4652,"children":4653},{"style":3742},[4654],{"type":62,"value":4590},{"type":49,"tag":1346,"props":4656,"children":4657},{"style":1365},[4658],{"type":62,"value":4659}," entityId",{"type":49,"tag":1346,"props":4661,"children":4662},{"style":1359},[4663],{"type":62,"value":4600},{"type":49,"tag":1346,"props":4665,"children":4666},{"style":1365},[4667],{"type":62,"value":4595},{"type":49,"tag":1346,"props":4669,"children":4670},{"style":1359},[4671],{"type":62,"value":523},{"type":49,"tag":1346,"props":4673,"children":4674},{"style":1365},[4675],{"type":62,"value":4676},"entityId",{"type":49,"tag":1346,"props":4678,"children":4679},{"style":1359},[4680],{"type":62,"value":3773},{"type":49,"tag":1346,"props":4682,"children":4683},{"class":1348,"line":4051},[4684,4688,4693,4697,4701,4705,4710],{"type":49,"tag":1346,"props":4685,"children":4686},{"style":3742},[4687],{"type":62,"value":4590},{"type":49,"tag":1346,"props":4689,"children":4690},{"style":1365},[4691],{"type":62,"value":4692}," targetStatus",{"type":49,"tag":1346,"props":4694,"children":4695},{"style":1359},[4696],{"type":62,"value":4600},{"type":49,"tag":1346,"props":4698,"children":4699},{"style":1365},[4700],{"type":62,"value":4595},{"type":49,"tag":1346,"props":4702,"children":4703},{"style":1359},[4704],{"type":62,"value":523},{"type":49,"tag":1346,"props":4706,"children":4707},{"style":1365},[4708],{"type":62,"value":4709},"targetStatus",{"type":49,"tag":1346,"props":4711,"children":4712},{"style":1359},[4713],{"type":62,"value":3773},{"type":49,"tag":1346,"props":4715,"children":4716},{"class":1348,"line":4083},[4717],{"type":49,"tag":1346,"props":4718,"children":4719},{"emptyLinePlaceholder":42},[4720],{"type":62,"value":3781},{"type":49,"tag":1346,"props":4722,"children":4723},{"class":1348,"line":4114},[4724],{"type":49,"tag":1346,"props":4725,"children":4726},{"style":3733},[4727],{"type":62,"value":4728},"        \u002F\u002F 1. Read the current record from Dataverse\n",{"type":49,"tag":1346,"props":4730,"children":4731},{"class":1348,"line":4143},[4732,4736,4741,4745,4750,4754,4759,4763,4768,4772,4777,4781,4785,4790,4794,4799,4803,4807,4811,4816,4820,4824],{"type":49,"tag":1346,"props":4733,"children":4734},{"style":3742},[4735],{"type":62,"value":4590},{"type":49,"tag":1346,"props":4737,"children":4738},{"style":1365},[4739],{"type":62,"value":4740}," current",{"type":49,"tag":1346,"props":4742,"children":4743},{"style":1359},[4744],{"type":62,"value":4600},{"type":49,"tag":1346,"props":4746,"children":4747},{"style":1365},[4748],{"type":62,"value":4749}," Server",{"type":49,"tag":1346,"props":4751,"children":4752},{"style":1359},[4753],{"type":62,"value":523},{"type":49,"tag":1346,"props":4755,"children":4756},{"style":1365},[4757],{"type":62,"value":4758},"Connector",{"type":49,"tag":1346,"props":4760,"children":4761},{"style":1359},[4762],{"type":62,"value":523},{"type":49,"tag":1346,"props":4764,"children":4765},{"style":1365},[4766],{"type":62,"value":4767},"Dataverse",{"type":49,"tag":1346,"props":4769,"children":4770},{"style":1359},[4771],{"type":62,"value":523},{"type":49,"tag":1346,"props":4773,"children":4774},{"style":3917},[4775],{"type":62,"value":4776},"RetrieveRecord",{"type":49,"tag":1346,"props":4778,"children":4779},{"style":3192},[4780],{"type":62,"value":3976},{"type":49,"tag":1346,"props":4782,"children":4783},{"style":1359},[4784],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4786,"children":4787},{"style":1376},[4788],{"type":62,"value":4789},"\u003Ctable-name>",{"type":49,"tag":1346,"props":4791,"children":4792},{"style":1359},[4793],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4795,"children":4796},{"style":1359},[4797],{"type":62,"value":4798},",",{"type":49,"tag":1346,"props":4800,"children":4801},{"style":1365},[4802],{"type":62,"value":4659},{"type":49,"tag":1346,"props":4804,"children":4805},{"style":1359},[4806],{"type":62,"value":4798},{"type":49,"tag":1346,"props":4808,"children":4809},{"style":1359},[4810],{"type":62,"value":1389},{"type":49,"tag":1346,"props":4812,"children":4813},{"style":1376},[4814],{"type":62,"value":4815},"?$select=\u003Cstatus-field>",{"type":49,"tag":1346,"props":4817,"children":4818},{"style":1359},[4819],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4821,"children":4822},{"style":3192},[4823],{"type":62,"value":1113},{"type":49,"tag":1346,"props":4825,"children":4826},{"style":1359},[4827],{"type":62,"value":3773},{"type":49,"tag":1346,"props":4829,"children":4830},{"class":1348,"line":4166},[4831,4835,4840,4844,4848,4853,4857,4862,4866,4871],{"type":49,"tag":1346,"props":4832,"children":4833},{"style":3742},[4834],{"type":62,"value":4590},{"type":49,"tag":1346,"props":4836,"children":4837},{"style":1365},[4838],{"type":62,"value":4839}," currentStatus",{"type":49,"tag":1346,"props":4841,"children":4842},{"style":1359},[4843],{"type":62,"value":4600},{"type":49,"tag":1346,"props":4845,"children":4846},{"style":1365},[4847],{"type":62,"value":4740},{"type":49,"tag":1346,"props":4849,"children":4850},{"style":3192},[4851],{"type":62,"value":4852},"[",{"type":49,"tag":1346,"props":4854,"children":4855},{"style":1359},[4856],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4858,"children":4859},{"style":1376},[4860],{"type":62,"value":4861},"\u003Cstatus-field>",{"type":49,"tag":1346,"props":4863,"children":4864},{"style":1359},[4865],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4867,"children":4868},{"style":3192},[4869],{"type":62,"value":4870},"]",{"type":49,"tag":1346,"props":4872,"children":4873},{"style":1359},[4874],{"type":62,"value":3773},{"type":49,"tag":1346,"props":4876,"children":4877},{"class":1348,"line":4183},[4878],{"type":49,"tag":1346,"props":4879,"children":4880},{"emptyLinePlaceholder":42},[4881],{"type":62,"value":3781},{"type":49,"tag":1346,"props":4883,"children":4884},{"class":1348,"line":4215},[4885],{"type":49,"tag":1346,"props":4886,"children":4887},{"style":3733},[4888],{"type":62,"value":4889},"        \u002F\u002F 2. Validate the transition\n",{"type":49,"tag":1346,"props":4891,"children":4892},{"class":1348,"line":4283},[4893,4897,4902,4906],{"type":49,"tag":1346,"props":4894,"children":4895},{"style":3742},[4896],{"type":62,"value":4590},{"type":49,"tag":1346,"props":4898,"children":4899},{"style":1365},[4900],{"type":62,"value":4901}," allowedTransitions",{"type":49,"tag":1346,"props":4903,"children":4904},{"style":1359},[4905],{"type":62,"value":4600},{"type":49,"tag":1346,"props":4907,"children":4908},{"style":1359},[4909],{"type":62,"value":3930},{"type":49,"tag":1346,"props":4911,"children":4912},{"class":1348,"line":4311},[4913,4918,4923,4927,4931,4936,4940,4945,4949,4953],{"type":49,"tag":1346,"props":4914,"children":4915},{"style":1359},[4916],{"type":62,"value":4917},"            \"",{"type":49,"tag":1346,"props":4919,"children":4920},{"style":3192},[4921],{"type":62,"value":4922},"Draft",{"type":49,"tag":1346,"props":4924,"children":4925},{"style":1359},[4926],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4928,"children":4929},{"style":1359},[4930],{"type":62,"value":468},{"type":49,"tag":1346,"props":4932,"children":4933},{"style":3192},[4934],{"type":62,"value":4935}," [",{"type":49,"tag":1346,"props":4937,"children":4938},{"style":1359},[4939],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4941,"children":4942},{"style":1376},[4943],{"type":62,"value":4944},"Submitted",{"type":49,"tag":1346,"props":4946,"children":4947},{"style":1359},[4948],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4950,"children":4951},{"style":3192},[4952],{"type":62,"value":4870},{"type":49,"tag":1346,"props":4954,"children":4955},{"style":1359},[4956],{"type":62,"value":4111},{"type":49,"tag":1346,"props":4958,"children":4959},{"class":1348,"line":4340},[4960,4964,4968,4972,4976,4980,4984,4989,4993,4997,5001,5006,5010,5014],{"type":49,"tag":1346,"props":4961,"children":4962},{"style":1359},[4963],{"type":62,"value":4917},{"type":49,"tag":1346,"props":4965,"children":4966},{"style":3192},[4967],{"type":62,"value":4944},{"type":49,"tag":1346,"props":4969,"children":4970},{"style":1359},[4971],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4973,"children":4974},{"style":1359},[4975],{"type":62,"value":468},{"type":49,"tag":1346,"props":4977,"children":4978},{"style":3192},[4979],{"type":62,"value":4935},{"type":49,"tag":1346,"props":4981,"children":4982},{"style":1359},[4983],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4985,"children":4986},{"style":1376},[4987],{"type":62,"value":4988},"Approved",{"type":49,"tag":1346,"props":4990,"children":4991},{"style":1359},[4992],{"type":62,"value":1384},{"type":49,"tag":1346,"props":4994,"children":4995},{"style":1359},[4996],{"type":62,"value":4798},{"type":49,"tag":1346,"props":4998,"children":4999},{"style":1359},[5000],{"type":62,"value":1389},{"type":49,"tag":1346,"props":5002,"children":5003},{"style":1376},[5004],{"type":62,"value":5005},"Rejected",{"type":49,"tag":1346,"props":5007,"children":5008},{"style":1359},[5009],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5011,"children":5012},{"style":3192},[5013],{"type":62,"value":4870},{"type":49,"tag":1346,"props":5015,"children":5016},{"style":1359},[5017],{"type":62,"value":4111},{"type":49,"tag":1346,"props":5019,"children":5020},{"class":1348,"line":4368},[5021,5025,5029,5033,5037,5041,5045,5050,5054],{"type":49,"tag":1346,"props":5022,"children":5023},{"style":1359},[5024],{"type":62,"value":4917},{"type":49,"tag":1346,"props":5026,"children":5027},{"style":3192},[5028],{"type":62,"value":4988},{"type":49,"tag":1346,"props":5030,"children":5031},{"style":1359},[5032],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5034,"children":5035},{"style":1359},[5036],{"type":62,"value":468},{"type":49,"tag":1346,"props":5038,"children":5039},{"style":3192},[5040],{"type":62,"value":4935},{"type":49,"tag":1346,"props":5042,"children":5043},{"style":1359},[5044],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5046,"children":5047},{"style":1376},[5048],{"type":62,"value":5049},"Fulfilled",{"type":49,"tag":1346,"props":5051,"children":5052},{"style":1359},[5053],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5055,"children":5056},{"style":3192},[5057],{"type":62,"value":5058},"]\n",{"type":49,"tag":1346,"props":5060,"children":5061},{"class":1348,"line":4394},[5062],{"type":49,"tag":1346,"props":5063,"children":5064},{"style":1359},[5065],{"type":62,"value":5066},"        };\n",{"type":49,"tag":1346,"props":5068,"children":5069},{"class":1348,"line":4410},[5070],{"type":49,"tag":1346,"props":5071,"children":5072},{"emptyLinePlaceholder":42},[5073],{"type":62,"value":3781},{"type":49,"tag":1346,"props":5075,"children":5076},{"class":1348,"line":4419},[5077,5081,5086,5090,5094,5098,5103,5108,5113,5118],{"type":49,"tag":1346,"props":5078,"children":5079},{"style":3742},[5080],{"type":62,"value":4590},{"type":49,"tag":1346,"props":5082,"children":5083},{"style":1365},[5084],{"type":62,"value":5085}," allowed",{"type":49,"tag":1346,"props":5087,"children":5088},{"style":1359},[5089],{"type":62,"value":4600},{"type":49,"tag":1346,"props":5091,"children":5092},{"style":1365},[5093],{"type":62,"value":4901},{"type":49,"tag":1346,"props":5095,"children":5096},{"style":3192},[5097],{"type":62,"value":4852},{"type":49,"tag":1346,"props":5099,"children":5100},{"style":1365},[5101],{"type":62,"value":5102},"currentStatus",{"type":49,"tag":1346,"props":5104,"children":5105},{"style":3192},[5106],{"type":62,"value":5107},"] ",{"type":49,"tag":1346,"props":5109,"children":5110},{"style":1359},[5111],{"type":62,"value":5112},"||",{"type":49,"tag":1346,"props":5114,"children":5115},{"style":3192},[5116],{"type":62,"value":5117}," []",{"type":49,"tag":1346,"props":5119,"children":5120},{"style":1359},[5121],{"type":62,"value":3773},{"type":49,"tag":1346,"props":5123,"children":5125},{"class":1348,"line":5124},28,[5126,5131,5135,5140,5145,5149,5154,5158,5162,5167],{"type":49,"tag":1346,"props":5127,"children":5128},{"style":3937},[5129],{"type":62,"value":5130},"        if",{"type":49,"tag":1346,"props":5132,"children":5133},{"style":3192},[5134],{"type":62,"value":1474},{"type":49,"tag":1346,"props":5136,"children":5137},{"style":1359},[5138],{"type":62,"value":5139},"!",{"type":49,"tag":1346,"props":5141,"children":5142},{"style":1365},[5143],{"type":62,"value":5144},"allowed",{"type":49,"tag":1346,"props":5146,"children":5147},{"style":1359},[5148],{"type":62,"value":523},{"type":49,"tag":1346,"props":5150,"children":5151},{"style":3917},[5152],{"type":62,"value":5153},"includes",{"type":49,"tag":1346,"props":5155,"children":5156},{"style":3192},[5157],{"type":62,"value":3976},{"type":49,"tag":1346,"props":5159,"children":5160},{"style":1365},[5161],{"type":62,"value":4709},{"type":49,"tag":1346,"props":5163,"children":5164},{"style":3192},[5165],{"type":62,"value":5166},")) ",{"type":49,"tag":1346,"props":5168,"children":5169},{"style":1359},[5170],{"type":62,"value":4080},{"type":49,"tag":1346,"props":5172,"children":5174},{"class":1348,"line":5173},29,[5175,5180,5184,5188,5192,5196],{"type":49,"tag":1346,"props":5176,"children":5177},{"style":3937},[5178],{"type":62,"value":5179},"            return",{"type":49,"tag":1346,"props":5181,"children":5182},{"style":1365},[5183],{"type":62,"value":4062},{"type":49,"tag":1346,"props":5185,"children":5186},{"style":1359},[5187],{"type":62,"value":523},{"type":49,"tag":1346,"props":5189,"children":5190},{"style":3917},[5191],{"type":62,"value":4071},{"type":49,"tag":1346,"props":5193,"children":5194},{"style":3192},[5195],{"type":62,"value":3976},{"type":49,"tag":1346,"props":5197,"children":5198},{"style":1359},[5199],{"type":62,"value":4080},{"type":49,"tag":1346,"props":5201,"children":5203},{"class":1348,"line":5202},30,[5204,5209,5213,5217,5221,5225],{"type":49,"tag":1346,"props":5205,"children":5206},{"style":3192},[5207],{"type":62,"value":5208},"                status",{"type":49,"tag":1346,"props":5210,"children":5211},{"style":1359},[5212],{"type":62,"value":468},{"type":49,"tag":1346,"props":5214,"children":5215},{"style":1359},[5216],{"type":62,"value":1389},{"type":49,"tag":1346,"props":5218,"children":5219},{"style":1376},[5220],{"type":62,"value":4329},{"type":49,"tag":1346,"props":5222,"children":5223},{"style":1359},[5224],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5226,"children":5227},{"style":1359},[5228],{"type":62,"value":4111},{"type":49,"tag":1346,"props":5230,"children":5232},{"class":1348,"line":5231},31,[5233,5238,5242,5246,5251,5255,5259,5263,5267,5271,5276,5280,5284,5288,5292,5296,5301,5305],{"type":49,"tag":1346,"props":5234,"children":5235},{"style":3192},[5236],{"type":62,"value":5237},"                message",{"type":49,"tag":1346,"props":5239,"children":5240},{"style":1359},[5241],{"type":62,"value":468},{"type":49,"tag":1346,"props":5243,"children":5244},{"style":1359},[5245],{"type":62,"value":1389},{"type":49,"tag":1346,"props":5247,"children":5248},{"style":1376},[5249],{"type":62,"value":5250},"Invalid transition: ",{"type":49,"tag":1346,"props":5252,"children":5253},{"style":1359},[5254],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5256,"children":5257},{"style":1359},[5258],{"type":62,"value":3822},{"type":49,"tag":1346,"props":5260,"children":5261},{"style":1365},[5262],{"type":62,"value":4839},{"type":49,"tag":1346,"props":5264,"children":5265},{"style":1359},[5266],{"type":62,"value":3822},{"type":49,"tag":1346,"props":5268,"children":5269},{"style":1359},[5270],{"type":62,"value":1389},{"type":49,"tag":1346,"props":5272,"children":5273},{"style":1376},[5274],{"type":62,"value":5275}," → ",{"type":49,"tag":1346,"props":5277,"children":5278},{"style":1359},[5279],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5281,"children":5282},{"style":1359},[5283],{"type":62,"value":3822},{"type":49,"tag":1346,"props":5285,"children":5286},{"style":1365},[5287],{"type":62,"value":4692},{"type":49,"tag":1346,"props":5289,"children":5290},{"style":1359},[5291],{"type":62,"value":3822},{"type":49,"tag":1346,"props":5293,"children":5294},{"style":1359},[5295],{"type":62,"value":1389},{"type":49,"tag":1346,"props":5297,"children":5298},{"style":1376},[5299],{"type":62,"value":5300}," is not allowed",{"type":49,"tag":1346,"props":5302,"children":5303},{"style":1359},[5304],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5306,"children":5307},{"style":1359},[5308],{"type":62,"value":4111},{"type":49,"tag":1346,"props":5310,"children":5312},{"class":1348,"line":5311},32,[5313,5318,5322,5326],{"type":49,"tag":1346,"props":5314,"children":5315},{"style":3192},[5316],{"type":62,"value":5317},"                currentStatus",{"type":49,"tag":1346,"props":5319,"children":5320},{"style":1359},[5321],{"type":62,"value":468},{"type":49,"tag":1346,"props":5323,"children":5324},{"style":1365},[5325],{"type":62,"value":4839},{"type":49,"tag":1346,"props":5327,"children":5328},{"style":1359},[5329],{"type":62,"value":4111},{"type":49,"tag":1346,"props":5331,"children":5333},{"class":1348,"line":5332},33,[5334,5339,5343,5347],{"type":49,"tag":1346,"props":5335,"children":5336},{"style":3192},[5337],{"type":62,"value":5338},"                targetStatus",{"type":49,"tag":1346,"props":5340,"children":5341},{"style":1359},[5342],{"type":62,"value":468},{"type":49,"tag":1346,"props":5344,"children":5345},{"style":1365},[5346],{"type":62,"value":4692},{"type":49,"tag":1346,"props":5348,"children":5349},{"style":1359},[5350],{"type":62,"value":4111},{"type":49,"tag":1346,"props":5352,"children":5354},{"class":1348,"line":5353},34,[5355,5360,5364],{"type":49,"tag":1346,"props":5356,"children":5357},{"style":3192},[5358],{"type":62,"value":5359},"                allowedTargets",{"type":49,"tag":1346,"props":5361,"children":5362},{"style":1359},[5363],{"type":62,"value":468},{"type":49,"tag":1346,"props":5365,"children":5366},{"style":1365},[5367],{"type":62,"value":5368}," allowed\n",{"type":49,"tag":1346,"props":5370,"children":5372},{"class":1348,"line":5371},35,[5373,5378,5382],{"type":49,"tag":1346,"props":5374,"children":5375},{"style":1359},[5376],{"type":62,"value":5377},"            }",{"type":49,"tag":1346,"props":5379,"children":5380},{"style":3192},[5381],{"type":62,"value":1113},{"type":49,"tag":1346,"props":5383,"children":5384},{"style":1359},[5385],{"type":62,"value":3773},{"type":49,"tag":1346,"props":5387,"children":5389},{"class":1348,"line":5388},36,[5390],{"type":49,"tag":1346,"props":5391,"children":5392},{"style":1359},[5393],{"type":62,"value":5394},"        }\n",{"type":49,"tag":1346,"props":5396,"children":5398},{"class":1348,"line":5397},37,[5399],{"type":49,"tag":1346,"props":5400,"children":5401},{"emptyLinePlaceholder":42},[5402],{"type":62,"value":3781},{"type":49,"tag":1346,"props":5404,"children":5406},{"class":1348,"line":5405},38,[5407],{"type":49,"tag":1346,"props":5408,"children":5409},{"style":3733},[5410],{"type":62,"value":5411},"        \u002F\u002F 3. Execute the write — server performs the Dataverse update\n",{"type":49,"tag":1346,"props":5413,"children":5415},{"class":1348,"line":5414},39,[5416,5420,5425,5429],{"type":49,"tag":1346,"props":5417,"children":5418},{"style":3742},[5419],{"type":62,"value":4590},{"type":49,"tag":1346,"props":5421,"children":5422},{"style":1365},[5423],{"type":62,"value":5424}," updateData",{"type":49,"tag":1346,"props":5426,"children":5427},{"style":1359},[5428],{"type":62,"value":4600},{"type":49,"tag":1346,"props":5430,"children":5431},{"style":1359},[5432],{"type":62,"value":5433}," {};\n",{"type":49,"tag":1346,"props":5435,"children":5437},{"class":1348,"line":5436},40,[5438,5443,5447,5451,5455,5459,5463,5467,5471],{"type":49,"tag":1346,"props":5439,"children":5440},{"style":1365},[5441],{"type":62,"value":5442},"        updateData",{"type":49,"tag":1346,"props":5444,"children":5445},{"style":3192},[5446],{"type":62,"value":4852},{"type":49,"tag":1346,"props":5448,"children":5449},{"style":1359},[5450],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5452,"children":5453},{"style":1376},[5454],{"type":62,"value":4861},{"type":49,"tag":1346,"props":5456,"children":5457},{"style":1359},[5458],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5460,"children":5461},{"style":3192},[5462],{"type":62,"value":5107},{"type":49,"tag":1346,"props":5464,"children":5465},{"style":1359},[5466],{"type":62,"value":3755},{"type":49,"tag":1346,"props":5468,"children":5469},{"style":1365},[5470],{"type":62,"value":4692},{"type":49,"tag":1346,"props":5472,"children":5473},{"style":1359},[5474],{"type":62,"value":3773},{"type":49,"tag":1346,"props":5476,"children":5478},{"class":1348,"line":5477},41,[5479,5483,5487,5491,5495,5499,5503,5508,5512,5516,5520,5524,5528,5532,5536,5540,5544,5548,5552,5557,5562],{"type":49,"tag":1346,"props":5480,"children":5481},{"style":1365},[5482],{"type":62,"value":3953},{"type":49,"tag":1346,"props":5484,"children":5485},{"style":1359},[5486],{"type":62,"value":523},{"type":49,"tag":1346,"props":5488,"children":5489},{"style":1365},[5490],{"type":62,"value":4758},{"type":49,"tag":1346,"props":5492,"children":5493},{"style":1359},[5494],{"type":62,"value":523},{"type":49,"tag":1346,"props":5496,"children":5497},{"style":1365},[5498],{"type":62,"value":4767},{"type":49,"tag":1346,"props":5500,"children":5501},{"style":1359},[5502],{"type":62,"value":523},{"type":49,"tag":1346,"props":5504,"children":5505},{"style":3917},[5506],{"type":62,"value":5507},"UpdateRecord",{"type":49,"tag":1346,"props":5509,"children":5510},{"style":3192},[5511],{"type":62,"value":3976},{"type":49,"tag":1346,"props":5513,"children":5514},{"style":1359},[5515],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5517,"children":5518},{"style":1376},[5519],{"type":62,"value":4789},{"type":49,"tag":1346,"props":5521,"children":5522},{"style":1359},[5523],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5525,"children":5526},{"style":1359},[5527],{"type":62,"value":4798},{"type":49,"tag":1346,"props":5529,"children":5530},{"style":1365},[5531],{"type":62,"value":4659},{"type":49,"tag":1346,"props":5533,"children":5534},{"style":1359},[5535],{"type":62,"value":4798},{"type":49,"tag":1346,"props":5537,"children":5538},{"style":1365},[5539],{"type":62,"value":4062},{"type":49,"tag":1346,"props":5541,"children":5542},{"style":1359},[5543],{"type":62,"value":523},{"type":49,"tag":1346,"props":5545,"children":5546},{"style":3917},[5547],{"type":62,"value":4071},{"type":49,"tag":1346,"props":5549,"children":5550},{"style":3192},[5551],{"type":62,"value":3976},{"type":49,"tag":1346,"props":5553,"children":5554},{"style":1365},[5555],{"type":62,"value":5556},"updateData",{"type":49,"tag":1346,"props":5558,"children":5559},{"style":3192},[5560],{"type":62,"value":5561},"))",{"type":49,"tag":1346,"props":5563,"children":5564},{"style":1359},[5565],{"type":62,"value":3773},{"type":49,"tag":1346,"props":5567,"children":5569},{"class":1348,"line":5568},42,[5570],{"type":49,"tag":1346,"props":5571,"children":5572},{"emptyLinePlaceholder":42},[5573],{"type":62,"value":3781},{"type":49,"tag":1346,"props":5575,"children":5577},{"class":1348,"line":5576},43,[5578,5582,5586,5590,5594,5598,5602,5606,5611,5615,5619,5623,5627,5631,5635,5639,5643,5647,5651],{"type":49,"tag":1346,"props":5579,"children":5580},{"style":1365},[5581],{"type":62,"value":3953},{"type":49,"tag":1346,"props":5583,"children":5584},{"style":1359},[5585],{"type":62,"value":523},{"type":49,"tag":1346,"props":5587,"children":5588},{"style":1365},[5589],{"type":62,"value":3962},{"type":49,"tag":1346,"props":5591,"children":5592},{"style":1359},[5593],{"type":62,"value":523},{"type":49,"tag":1346,"props":5595,"children":5596},{"style":3917},[5597],{"type":62,"value":3971},{"type":49,"tag":1346,"props":5599,"children":5600},{"style":3192},[5601],{"type":62,"value":3976},{"type":49,"tag":1346,"props":5603,"children":5604},{"style":1359},[5605],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5607,"children":5608},{"style":1376},[5609],{"type":62,"value":5610},"\u003Cname> transition executed: ",{"type":49,"tag":1346,"props":5612,"children":5613},{"style":1359},[5614],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5616,"children":5617},{"style":1359},[5618],{"type":62,"value":3822},{"type":49,"tag":1346,"props":5620,"children":5621},{"style":1365},[5622],{"type":62,"value":4839},{"type":49,"tag":1346,"props":5624,"children":5625},{"style":1359},[5626],{"type":62,"value":3822},{"type":49,"tag":1346,"props":5628,"children":5629},{"style":1359},[5630],{"type":62,"value":1389},{"type":49,"tag":1346,"props":5632,"children":5633},{"style":1376},[5634],{"type":62,"value":5275},{"type":49,"tag":1346,"props":5636,"children":5637},{"style":1359},[5638],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5640,"children":5641},{"style":1359},[5642],{"type":62,"value":3822},{"type":49,"tag":1346,"props":5644,"children":5645},{"style":1365},[5646],{"type":62,"value":4692},{"type":49,"tag":1346,"props":5648,"children":5649},{"style":3192},[5650],{"type":62,"value":1113},{"type":49,"tag":1346,"props":5652,"children":5653},{"style":1359},[5654],{"type":62,"value":3773},{"type":49,"tag":1346,"props":5656,"children":5658},{"class":1348,"line":5657},44,[5659],{"type":49,"tag":1346,"props":5660,"children":5661},{"emptyLinePlaceholder":42},[5662],{"type":62,"value":3781},{"type":49,"tag":1346,"props":5664,"children":5666},{"class":1348,"line":5665},45,[5667],{"type":49,"tag":1346,"props":5668,"children":5669},{"style":3733},[5670],{"type":62,"value":5671},"        \u002F\u002F 4. Return the result — client receives confirmation, not a validation flag\n",{"type":49,"tag":1346,"props":5673,"children":5675},{"class":1348,"line":5674},46,[5676,5680,5684,5688,5692,5696],{"type":49,"tag":1346,"props":5677,"children":5678},{"style":3937},[5679],{"type":62,"value":4057},{"type":49,"tag":1346,"props":5681,"children":5682},{"style":1365},[5683],{"type":62,"value":4062},{"type":49,"tag":1346,"props":5685,"children":5686},{"style":1359},[5687],{"type":62,"value":523},{"type":49,"tag":1346,"props":5689,"children":5690},{"style":3917},[5691],{"type":62,"value":4071},{"type":49,"tag":1346,"props":5693,"children":5694},{"style":3192},[5695],{"type":62,"value":3976},{"type":49,"tag":1346,"props":5697,"children":5698},{"style":1359},[5699],{"type":62,"value":4080},{"type":49,"tag":1346,"props":5701,"children":5703},{"class":1348,"line":5702},47,[5704,5708,5712,5716,5720,5724],{"type":49,"tag":1346,"props":5705,"children":5706},{"style":3192},[5707],{"type":62,"value":4089},{"type":49,"tag":1346,"props":5709,"children":5710},{"style":1359},[5711],{"type":62,"value":468},{"type":49,"tag":1346,"props":5713,"children":5714},{"style":1359},[5715],{"type":62,"value":1389},{"type":49,"tag":1346,"props":5717,"children":5718},{"style":1376},[5719],{"type":62,"value":4102},{"type":49,"tag":1346,"props":5721,"children":5722},{"style":1359},[5723],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5725,"children":5726},{"style":1359},[5727],{"type":62,"value":4111},{"type":49,"tag":1346,"props":5729,"children":5731},{"class":1348,"line":5730},48,[5732,5737,5741,5745],{"type":49,"tag":1346,"props":5733,"children":5734},{"style":3192},[5735],{"type":62,"value":5736},"            previousStatus",{"type":49,"tag":1346,"props":5738,"children":5739},{"style":1359},[5740],{"type":62,"value":468},{"type":49,"tag":1346,"props":5742,"children":5743},{"style":1365},[5744],{"type":62,"value":4839},{"type":49,"tag":1346,"props":5746,"children":5747},{"style":1359},[5748],{"type":62,"value":4111},{"type":49,"tag":1346,"props":5750,"children":5752},{"class":1348,"line":5751},49,[5753,5758,5762,5766],{"type":49,"tag":1346,"props":5754,"children":5755},{"style":3192},[5756],{"type":62,"value":5757},"            newStatus",{"type":49,"tag":1346,"props":5759,"children":5760},{"style":1359},[5761],{"type":62,"value":468},{"type":49,"tag":1346,"props":5763,"children":5764},{"style":1365},[5765],{"type":62,"value":4692},{"type":49,"tag":1346,"props":5767,"children":5768},{"style":1359},[5769],{"type":62,"value":4111},{"type":49,"tag":1346,"props":5771,"children":5773},{"class":1348,"line":5772},50,[5774,5779,5783],{"type":49,"tag":1346,"props":5775,"children":5776},{"style":3192},[5777],{"type":62,"value":5778},"            entityId",{"type":49,"tag":1346,"props":5780,"children":5781},{"style":1359},[5782],{"type":62,"value":468},{"type":49,"tag":1346,"props":5784,"children":5785},{"style":1365},[5786],{"type":62,"value":5787}," entityId\n",{"type":49,"tag":1346,"props":5789,"children":5791},{"class":1348,"line":5790},51,[5792,5796,5800],{"type":49,"tag":1346,"props":5793,"children":5794},{"style":1359},[5795],{"type":62,"value":4172},{"type":49,"tag":1346,"props":5797,"children":5798},{"style":3192},[5799],{"type":62,"value":1113},{"type":49,"tag":1346,"props":5801,"children":5802},{"style":1359},[5803],{"type":62,"value":3773},{"type":49,"tag":1346,"props":5805,"children":5807},{"class":1348,"line":5806},52,[5808,5812,5816,5820,5824,5828],{"type":49,"tag":1346,"props":5809,"children":5810},{"style":1359},[5811],{"type":62,"value":4189},{"type":49,"tag":1346,"props":5813,"children":5814},{"style":3937},[5815],{"type":62,"value":4194},{"type":49,"tag":1346,"props":5817,"children":5818},{"style":3192},[5819],{"type":62,"value":1474},{"type":49,"tag":1346,"props":5821,"children":5822},{"style":1365},[5823],{"type":62,"value":4203},{"type":49,"tag":1346,"props":5825,"children":5826},{"style":3192},[5827],{"type":62,"value":4208},{"type":49,"tag":1346,"props":5829,"children":5830},{"style":1359},[5831],{"type":62,"value":4080},{"type":49,"tag":1346,"props":5833,"children":5835},{"class":1348,"line":5834},53,[5836,5840,5844,5848,5852,5856,5860,5864,5869,5873,5877,5881,5885,5889,5893],{"type":49,"tag":1346,"props":5837,"children":5838},{"style":1365},[5839],{"type":62,"value":3953},{"type":49,"tag":1346,"props":5841,"children":5842},{"style":1359},[5843],{"type":62,"value":523},{"type":49,"tag":1346,"props":5845,"children":5846},{"style":1365},[5847],{"type":62,"value":3962},{"type":49,"tag":1346,"props":5849,"children":5850},{"style":1359},[5851],{"type":62,"value":523},{"type":49,"tag":1346,"props":5853,"children":5854},{"style":3917},[5855],{"type":62,"value":4237},{"type":49,"tag":1346,"props":5857,"children":5858},{"style":3192},[5859],{"type":62,"value":3976},{"type":49,"tag":1346,"props":5861,"children":5862},{"style":1359},[5863],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5865,"children":5866},{"style":1376},[5867],{"type":62,"value":5868},"\u003Cname> POST failed: ",{"type":49,"tag":1346,"props":5870,"children":5871},{"style":1359},[5872],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5874,"children":5875},{"style":1359},[5876],{"type":62,"value":3822},{"type":49,"tag":1346,"props":5878,"children":5879},{"style":1365},[5880],{"type":62,"value":4263},{"type":49,"tag":1346,"props":5882,"children":5883},{"style":1359},[5884],{"type":62,"value":523},{"type":49,"tag":1346,"props":5886,"children":5887},{"style":1365},[5888],{"type":62,"value":4272},{"type":49,"tag":1346,"props":5890,"children":5891},{"style":3192},[5892],{"type":62,"value":1113},{"type":49,"tag":1346,"props":5894,"children":5895},{"style":1359},[5896],{"type":62,"value":3773},{"type":49,"tag":1346,"props":5898,"children":5900},{"class":1348,"line":5899},54,[5901,5905,5909,5913,5917,5921],{"type":49,"tag":1346,"props":5902,"children":5903},{"style":3937},[5904],{"type":62,"value":4057},{"type":49,"tag":1346,"props":5906,"children":5907},{"style":1365},[5908],{"type":62,"value":4062},{"type":49,"tag":1346,"props":5910,"children":5911},{"style":1359},[5912],{"type":62,"value":523},{"type":49,"tag":1346,"props":5914,"children":5915},{"style":3917},[5916],{"type":62,"value":4071},{"type":49,"tag":1346,"props":5918,"children":5919},{"style":3192},[5920],{"type":62,"value":3976},{"type":49,"tag":1346,"props":5922,"children":5923},{"style":1359},[5924],{"type":62,"value":4080},{"type":49,"tag":1346,"props":5926,"children":5928},{"class":1348,"line":5927},55,[5929,5933,5937,5941,5945,5949],{"type":49,"tag":1346,"props":5930,"children":5931},{"style":3192},[5932],{"type":62,"value":4089},{"type":49,"tag":1346,"props":5934,"children":5935},{"style":1359},[5936],{"type":62,"value":468},{"type":49,"tag":1346,"props":5938,"children":5939},{"style":1359},[5940],{"type":62,"value":1389},{"type":49,"tag":1346,"props":5942,"children":5943},{"style":1376},[5944],{"type":62,"value":4329},{"type":49,"tag":1346,"props":5946,"children":5947},{"style":1359},[5948],{"type":62,"value":1384},{"type":49,"tag":1346,"props":5950,"children":5951},{"style":1359},[5952],{"type":62,"value":4111},{"type":49,"tag":1346,"props":5954,"children":5956},{"class":1348,"line":5955},56,[5957,5961,5965,5969,5973],{"type":49,"tag":1346,"props":5958,"children":5959},{"style":3192},[5960],{"type":62,"value":4374},{"type":49,"tag":1346,"props":5962,"children":5963},{"style":1359},[5964],{"type":62,"value":468},{"type":49,"tag":1346,"props":5966,"children":5967},{"style":1365},[5968],{"type":62,"value":4263},{"type":49,"tag":1346,"props":5970,"children":5971},{"style":1359},[5972],{"type":62,"value":523},{"type":49,"tag":1346,"props":5974,"children":5975},{"style":1365},[5976],{"type":62,"value":4391},{"type":49,"tag":1346,"props":5978,"children":5980},{"class":1348,"line":5979},57,[5981,5985,5989],{"type":49,"tag":1346,"props":5982,"children":5983},{"style":1359},[5984],{"type":62,"value":4172},{"type":49,"tag":1346,"props":5986,"children":5987},{"style":3192},[5988],{"type":62,"value":1113},{"type":49,"tag":1346,"props":5990,"children":5991},{"style":1359},[5992],{"type":62,"value":3773},{"type":49,"tag":1346,"props":5994,"children":5996},{"class":1348,"line":5995},58,[5997],{"type":49,"tag":1346,"props":5998,"children":5999},{"style":1359},[6000],{"type":62,"value":4416},{"type":49,"tag":1346,"props":6002,"children":6004},{"class":1348,"line":6003},59,[6005],{"type":49,"tag":1346,"props":6006,"children":6007},{"style":1359},[6008],{"type":62,"value":4425},{"type":49,"tag":54,"props":6010,"children":6011},{},[6012],{"type":49,"tag":58,"props":6013,"children":6014},{},[6015],{"type":62,"value":6016},"Key differences from the basic template:",{"type":49,"tag":291,"props":6018,"children":6019},{},[6020,6025,6030,6041,6053],{"type":49,"tag":98,"props":6021,"children":6022},{},[6023],{"type":62,"value":6024},"The server logic reads the current state from Dataverse (not trusting the client's view)",{"type":49,"tag":98,"props":6026,"children":6027},{},[6028],{"type":62,"value":6029},"It validates the business rule server-side",{"type":49,"tag":98,"props":6031,"children":6032},{},[6033,6035],{"type":62,"value":6034},"It writes the result to Dataverse via ",{"type":49,"tag":67,"props":6036,"children":6038},{"className":6037},[],[6039],{"type":62,"value":6040},"Server.Connector.Dataverse.UpdateRecord",{"type":49,"tag":98,"props":6042,"children":6043},{},[6044,6046,6051],{"type":62,"value":6045},"It returns a success\u002Ffailure result — NOT a ",{"type":49,"tag":67,"props":6047,"children":6049},{"className":6048},[],[6050],{"type":62,"value":1312},{"type":62,"value":6052}," flag for the client to act on",{"type":49,"tag":98,"props":6054,"children":6055},{},[6056],{"type":62,"value":6057},"The client calls this one endpoint — it does NOT make a separate Web API PATCH call",{"type":49,"tag":3362,"props":6059,"children":6061},{"id":6060},"custom-action-wrapping-template",[6062],{"type":62,"value":6063},"Custom Action Wrapping Template",{"type":49,"tag":54,"props":6065,"children":6066},{},[6067,6069,6075,6077,6083],{"type":62,"value":6068},"When a server logic item wraps a Dataverse custom action (mapped in Phase 2.1.2), use this pattern with ",{"type":49,"tag":67,"props":6070,"children":6072},{"className":6071},[],[6073],{"type":62,"value":6074},"Server.Connector.Dataverse.InvokeCustomApi",{"type":62,"value":6076},". The server logic acts as a portal-friendly wrapper, exposing the custom action through a ",{"type":49,"tag":67,"props":6078,"children":6080},{"className":6079},[],[6081],{"type":62,"value":6082},"\u002F_api\u002Fserverlogics\u002F\u003Cname>",{"type":62,"value":6084}," endpoint with proper web role authorization.",{"type":49,"tag":54,"props":6086,"children":6087},{},[6088],{"type":49,"tag":58,"props":6089,"children":6090},{},[6091],{"type":62,"value":6092},"Unbound action:",{"type":49,"tag":1335,"props":6094,"children":6096},{"className":3722,"code":6095,"language":18,"meta":1340,"style":1340},"\u002F\u002F Server Logic: \u003Cname>\n\u002F\u002F Purpose: Wraps Dataverse custom action \"\u003Ccustom-action-name>\" for portal consumption\n\u002F\u002F Custom Action: \u003Ccustom-action-name> (unbound, action)\n\u002F\u002F API URL: https:\u002F\u002F\u003Csite-url>\u002F_api\u002Fserverlogics\u002F\u003Cname>\n\nfunction post() {\n    try {\n        Server.Logger.Log(\"\u003Cname> POST called — invoking custom action \u003Ccustom-action-name>\");\n\n        const body = JSON.parse(Server.Context.Body);\n\n        \u002F\u002F Build the request payload matching the custom action's input parameters\n        const payload = JSON.stringify({\n            \u002F\u002F \"\u003CParameterName>\": body.\u003CclientFieldName>\n        });\n\n        const result = Server.Connector.Dataverse.InvokeCustomApi(\n            \"POST\",\n            \"\u003Ccustom-action-name>\",\n            payload\n        );\n\n        Server.Logger.Log(\"\u003Cname> custom action completed successfully\");\n\n        return JSON.stringify({\n            status: \"success\",\n            data: result\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> POST failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            message: err.message\n        });\n    }\n}\n",[6097],{"type":49,"tag":67,"props":6098,"children":6099},{"__ignoreMap":1340},[6100,6107,6115,6123,6130,6137,6156,6167,6215,6222,6281,6288,6296,6332,6340,6355,6362,6411,6430,6450,6458,6470,6477,6525,6532,6559,6586,6602,6617,6644,6707,6734,6761,6784,6799,6806],{"type":49,"tag":1346,"props":6101,"children":6102},{"class":1348,"line":1349},[6103],{"type":49,"tag":1346,"props":6104,"children":6105},{"style":3733},[6106],{"type":62,"value":3884},{"type":49,"tag":1346,"props":6108,"children":6109},{"class":1348,"line":3208},[6110],{"type":49,"tag":1346,"props":6111,"children":6112},{"style":3733},[6113],{"type":62,"value":6114},"\u002F\u002F Purpose: Wraps Dataverse custom action \"\u003Ccustom-action-name>\" for portal consumption\n",{"type":49,"tag":1346,"props":6116,"children":6117},{"class":1348,"line":3226},[6118],{"type":49,"tag":1346,"props":6119,"children":6120},{"style":3733},[6121],{"type":62,"value":6122},"\u002F\u002F Custom Action: \u003Ccustom-action-name> (unbound, action)\n",{"type":49,"tag":1346,"props":6124,"children":6125},{"class":1348,"line":3243},[6126],{"type":49,"tag":1346,"props":6127,"children":6128},{"style":3733},[6129],{"type":62,"value":3900},{"type":49,"tag":1346,"props":6131,"children":6132},{"class":1348,"line":3261},[6133],{"type":49,"tag":1346,"props":6134,"children":6135},{"emptyLinePlaceholder":42},[6136],{"type":62,"value":3781},{"type":49,"tag":1346,"props":6138,"children":6139},{"class":1348,"line":3933},[6140,6144,6148,6152],{"type":49,"tag":1346,"props":6141,"children":6142},{"style":3742},[6143],{"type":62,"value":1488},{"type":49,"tag":1346,"props":6145,"children":6146},{"style":3917},[6147],{"type":62,"value":4508},{"type":49,"tag":1346,"props":6149,"children":6150},{"style":1359},[6151],{"type":62,"value":3925},{"type":49,"tag":1346,"props":6153,"children":6154},{"style":1359},[6155],{"type":62,"value":3930},{"type":49,"tag":1346,"props":6157,"children":6158},{"class":1348,"line":3947},[6159,6163],{"type":49,"tag":1346,"props":6160,"children":6161},{"style":3937},[6162],{"type":62,"value":3940},{"type":49,"tag":1346,"props":6164,"children":6165},{"style":1359},[6166],{"type":62,"value":3930},{"type":49,"tag":1346,"props":6168,"children":6169},{"class":1348,"line":4000},[6170,6174,6178,6182,6186,6190,6194,6198,6203,6207,6211],{"type":49,"tag":1346,"props":6171,"children":6172},{"style":1365},[6173],{"type":62,"value":3953},{"type":49,"tag":1346,"props":6175,"children":6176},{"style":1359},[6177],{"type":62,"value":523},{"type":49,"tag":1346,"props":6179,"children":6180},{"style":1365},[6181],{"type":62,"value":3962},{"type":49,"tag":1346,"props":6183,"children":6184},{"style":1359},[6185],{"type":62,"value":523},{"type":49,"tag":1346,"props":6187,"children":6188},{"style":3917},[6189],{"type":62,"value":3971},{"type":49,"tag":1346,"props":6191,"children":6192},{"style":3192},[6193],{"type":62,"value":3976},{"type":49,"tag":1346,"props":6195,"children":6196},{"style":1359},[6197],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6199,"children":6200},{"style":1376},[6201],{"type":62,"value":6202},"\u003Cname> POST called — invoking custom action \u003Ccustom-action-name>",{"type":49,"tag":1346,"props":6204,"children":6205},{"style":1359},[6206],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6208,"children":6209},{"style":3192},[6210],{"type":62,"value":1113},{"type":49,"tag":1346,"props":6212,"children":6213},{"style":1359},[6214],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6216,"children":6217},{"class":1348,"line":4008},[6218],{"type":49,"tag":1346,"props":6219,"children":6220},{"emptyLinePlaceholder":42},[6221],{"type":62,"value":3781},{"type":49,"tag":1346,"props":6223,"children":6224},{"class":1348,"line":4017},[6225,6229,6233,6237,6241,6245,6249,6253,6257,6261,6265,6269,6273,6277],{"type":49,"tag":1346,"props":6226,"children":6227},{"style":3742},[6228],{"type":62,"value":4590},{"type":49,"tag":1346,"props":6230,"children":6231},{"style":1365},[6232],{"type":62,"value":4595},{"type":49,"tag":1346,"props":6234,"children":6235},{"style":1359},[6236],{"type":62,"value":4600},{"type":49,"tag":1346,"props":6238,"children":6239},{"style":1365},[6240],{"type":62,"value":4062},{"type":49,"tag":1346,"props":6242,"children":6243},{"style":1359},[6244],{"type":62,"value":523},{"type":49,"tag":1346,"props":6246,"children":6247},{"style":3917},[6248],{"type":62,"value":4613},{"type":49,"tag":1346,"props":6250,"children":6251},{"style":3192},[6252],{"type":62,"value":3976},{"type":49,"tag":1346,"props":6254,"children":6255},{"style":1365},[6256],{"type":62,"value":4622},{"type":49,"tag":1346,"props":6258,"children":6259},{"style":1359},[6260],{"type":62,"value":523},{"type":49,"tag":1346,"props":6262,"children":6263},{"style":1365},[6264],{"type":62,"value":1755},{"type":49,"tag":1346,"props":6266,"children":6267},{"style":1359},[6268],{"type":62,"value":523},{"type":49,"tag":1346,"props":6270,"children":6271},{"style":1365},[6272],{"type":62,"value":4639},{"type":49,"tag":1346,"props":6274,"children":6275},{"style":3192},[6276],{"type":62,"value":1113},{"type":49,"tag":1346,"props":6278,"children":6279},{"style":1359},[6280],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6282,"children":6283},{"class":1348,"line":4026},[6284],{"type":49,"tag":1346,"props":6285,"children":6286},{"emptyLinePlaceholder":42},[6287],{"type":62,"value":3781},{"type":49,"tag":1346,"props":6289,"children":6290},{"class":1348,"line":4034},[6291],{"type":49,"tag":1346,"props":6292,"children":6293},{"style":3733},[6294],{"type":62,"value":6295},"        \u002F\u002F Build the request payload matching the custom action's input parameters\n",{"type":49,"tag":1346,"props":6297,"children":6298},{"class":1348,"line":4043},[6299,6303,6308,6312,6316,6320,6324,6328],{"type":49,"tag":1346,"props":6300,"children":6301},{"style":3742},[6302],{"type":62,"value":4590},{"type":49,"tag":1346,"props":6304,"children":6305},{"style":1365},[6306],{"type":62,"value":6307}," payload",{"type":49,"tag":1346,"props":6309,"children":6310},{"style":1359},[6311],{"type":62,"value":4600},{"type":49,"tag":1346,"props":6313,"children":6314},{"style":1365},[6315],{"type":62,"value":4062},{"type":49,"tag":1346,"props":6317,"children":6318},{"style":1359},[6319],{"type":62,"value":523},{"type":49,"tag":1346,"props":6321,"children":6322},{"style":3917},[6323],{"type":62,"value":4071},{"type":49,"tag":1346,"props":6325,"children":6326},{"style":3192},[6327],{"type":62,"value":3976},{"type":49,"tag":1346,"props":6329,"children":6330},{"style":1359},[6331],{"type":62,"value":4080},{"type":49,"tag":1346,"props":6333,"children":6334},{"class":1348,"line":4051},[6335],{"type":49,"tag":1346,"props":6336,"children":6337},{"style":3733},[6338],{"type":62,"value":6339},"            \u002F\u002F \"\u003CParameterName>\": body.\u003CclientFieldName>\n",{"type":49,"tag":1346,"props":6341,"children":6342},{"class":1348,"line":4083},[6343,6347,6351],{"type":49,"tag":1346,"props":6344,"children":6345},{"style":1359},[6346],{"type":62,"value":4172},{"type":49,"tag":1346,"props":6348,"children":6349},{"style":3192},[6350],{"type":62,"value":1113},{"type":49,"tag":1346,"props":6352,"children":6353},{"style":1359},[6354],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6356,"children":6357},{"class":1348,"line":4114},[6358],{"type":49,"tag":1346,"props":6359,"children":6360},{"emptyLinePlaceholder":42},[6361],{"type":62,"value":3781},{"type":49,"tag":1346,"props":6363,"children":6364},{"class":1348,"line":4143},[6365,6369,6374,6378,6382,6386,6390,6394,6398,6402,6406],{"type":49,"tag":1346,"props":6366,"children":6367},{"style":3742},[6368],{"type":62,"value":4590},{"type":49,"tag":1346,"props":6370,"children":6371},{"style":1365},[6372],{"type":62,"value":6373}," result",{"type":49,"tag":1346,"props":6375,"children":6376},{"style":1359},[6377],{"type":62,"value":4600},{"type":49,"tag":1346,"props":6379,"children":6380},{"style":1365},[6381],{"type":62,"value":4749},{"type":49,"tag":1346,"props":6383,"children":6384},{"style":1359},[6385],{"type":62,"value":523},{"type":49,"tag":1346,"props":6387,"children":6388},{"style":1365},[6389],{"type":62,"value":4758},{"type":49,"tag":1346,"props":6391,"children":6392},{"style":1359},[6393],{"type":62,"value":523},{"type":49,"tag":1346,"props":6395,"children":6396},{"style":1365},[6397],{"type":62,"value":4767},{"type":49,"tag":1346,"props":6399,"children":6400},{"style":1359},[6401],{"type":62,"value":523},{"type":49,"tag":1346,"props":6403,"children":6404},{"style":3917},[6405],{"type":62,"value":1805},{"type":49,"tag":1346,"props":6407,"children":6408},{"style":3192},[6409],{"type":62,"value":6410},"(\n",{"type":49,"tag":1346,"props":6412,"children":6413},{"class":1348,"line":4166},[6414,6418,6422,6426],{"type":49,"tag":1346,"props":6415,"children":6416},{"style":1359},[6417],{"type":62,"value":4917},{"type":49,"tag":1346,"props":6419,"children":6420},{"style":1376},[6421],{"type":62,"value":1826},{"type":49,"tag":1346,"props":6423,"children":6424},{"style":1359},[6425],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6427,"children":6428},{"style":1359},[6429],{"type":62,"value":4111},{"type":49,"tag":1346,"props":6431,"children":6432},{"class":1348,"line":4183},[6433,6437,6442,6446],{"type":49,"tag":1346,"props":6434,"children":6435},{"style":1359},[6436],{"type":62,"value":4917},{"type":49,"tag":1346,"props":6438,"children":6439},{"style":1376},[6440],{"type":62,"value":6441},"\u003Ccustom-action-name>",{"type":49,"tag":1346,"props":6443,"children":6444},{"style":1359},[6445],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6447,"children":6448},{"style":1359},[6449],{"type":62,"value":4111},{"type":49,"tag":1346,"props":6451,"children":6452},{"class":1348,"line":4215},[6453],{"type":49,"tag":1346,"props":6454,"children":6455},{"style":1365},[6456],{"type":62,"value":6457},"            payload\n",{"type":49,"tag":1346,"props":6459,"children":6460},{"class":1348,"line":4283},[6461,6466],{"type":49,"tag":1346,"props":6462,"children":6463},{"style":3192},[6464],{"type":62,"value":6465},"        )",{"type":49,"tag":1346,"props":6467,"children":6468},{"style":1359},[6469],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6471,"children":6472},{"class":1348,"line":4311},[6473],{"type":49,"tag":1346,"props":6474,"children":6475},{"emptyLinePlaceholder":42},[6476],{"type":62,"value":3781},{"type":49,"tag":1346,"props":6478,"children":6479},{"class":1348,"line":4340},[6480,6484,6488,6492,6496,6500,6504,6508,6513,6517,6521],{"type":49,"tag":1346,"props":6481,"children":6482},{"style":1365},[6483],{"type":62,"value":3953},{"type":49,"tag":1346,"props":6485,"children":6486},{"style":1359},[6487],{"type":62,"value":523},{"type":49,"tag":1346,"props":6489,"children":6490},{"style":1365},[6491],{"type":62,"value":3962},{"type":49,"tag":1346,"props":6493,"children":6494},{"style":1359},[6495],{"type":62,"value":523},{"type":49,"tag":1346,"props":6497,"children":6498},{"style":3917},[6499],{"type":62,"value":3971},{"type":49,"tag":1346,"props":6501,"children":6502},{"style":3192},[6503],{"type":62,"value":3976},{"type":49,"tag":1346,"props":6505,"children":6506},{"style":1359},[6507],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6509,"children":6510},{"style":1376},[6511],{"type":62,"value":6512},"\u003Cname> custom action completed successfully",{"type":49,"tag":1346,"props":6514,"children":6515},{"style":1359},[6516],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6518,"children":6519},{"style":3192},[6520],{"type":62,"value":1113},{"type":49,"tag":1346,"props":6522,"children":6523},{"style":1359},[6524],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6526,"children":6527},{"class":1348,"line":4368},[6528],{"type":49,"tag":1346,"props":6529,"children":6530},{"emptyLinePlaceholder":42},[6531],{"type":62,"value":3781},{"type":49,"tag":1346,"props":6533,"children":6534},{"class":1348,"line":4394},[6535,6539,6543,6547,6551,6555],{"type":49,"tag":1346,"props":6536,"children":6537},{"style":3937},[6538],{"type":62,"value":4057},{"type":49,"tag":1346,"props":6540,"children":6541},{"style":1365},[6542],{"type":62,"value":4062},{"type":49,"tag":1346,"props":6544,"children":6545},{"style":1359},[6546],{"type":62,"value":523},{"type":49,"tag":1346,"props":6548,"children":6549},{"style":3917},[6550],{"type":62,"value":4071},{"type":49,"tag":1346,"props":6552,"children":6553},{"style":3192},[6554],{"type":62,"value":3976},{"type":49,"tag":1346,"props":6556,"children":6557},{"style":1359},[6558],{"type":62,"value":4080},{"type":49,"tag":1346,"props":6560,"children":6561},{"class":1348,"line":4410},[6562,6566,6570,6574,6578,6582],{"type":49,"tag":1346,"props":6563,"children":6564},{"style":3192},[6565],{"type":62,"value":4089},{"type":49,"tag":1346,"props":6567,"children":6568},{"style":1359},[6569],{"type":62,"value":468},{"type":49,"tag":1346,"props":6571,"children":6572},{"style":1359},[6573],{"type":62,"value":1389},{"type":49,"tag":1346,"props":6575,"children":6576},{"style":1376},[6577],{"type":62,"value":4102},{"type":49,"tag":1346,"props":6579,"children":6580},{"style":1359},[6581],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6583,"children":6584},{"style":1359},[6585],{"type":62,"value":4111},{"type":49,"tag":1346,"props":6587,"children":6588},{"class":1348,"line":4419},[6589,6593,6597],{"type":49,"tag":1346,"props":6590,"children":6591},{"style":3192},[6592],{"type":62,"value":4149},{"type":49,"tag":1346,"props":6594,"children":6595},{"style":1359},[6596],{"type":62,"value":468},{"type":49,"tag":1346,"props":6598,"children":6599},{"style":1365},[6600],{"type":62,"value":6601}," result\n",{"type":49,"tag":1346,"props":6603,"children":6604},{"class":1348,"line":5124},[6605,6609,6613],{"type":49,"tag":1346,"props":6606,"children":6607},{"style":1359},[6608],{"type":62,"value":4172},{"type":49,"tag":1346,"props":6610,"children":6611},{"style":3192},[6612],{"type":62,"value":1113},{"type":49,"tag":1346,"props":6614,"children":6615},{"style":1359},[6616],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6618,"children":6619},{"class":1348,"line":5173},[6620,6624,6628,6632,6636,6640],{"type":49,"tag":1346,"props":6621,"children":6622},{"style":1359},[6623],{"type":62,"value":4189},{"type":49,"tag":1346,"props":6625,"children":6626},{"style":3937},[6627],{"type":62,"value":4194},{"type":49,"tag":1346,"props":6629,"children":6630},{"style":3192},[6631],{"type":62,"value":1474},{"type":49,"tag":1346,"props":6633,"children":6634},{"style":1365},[6635],{"type":62,"value":4203},{"type":49,"tag":1346,"props":6637,"children":6638},{"style":3192},[6639],{"type":62,"value":4208},{"type":49,"tag":1346,"props":6641,"children":6642},{"style":1359},[6643],{"type":62,"value":4080},{"type":49,"tag":1346,"props":6645,"children":6646},{"class":1348,"line":5202},[6647,6651,6655,6659,6663,6667,6671,6675,6679,6683,6687,6691,6695,6699,6703],{"type":49,"tag":1346,"props":6648,"children":6649},{"style":1365},[6650],{"type":62,"value":3953},{"type":49,"tag":1346,"props":6652,"children":6653},{"style":1359},[6654],{"type":62,"value":523},{"type":49,"tag":1346,"props":6656,"children":6657},{"style":1365},[6658],{"type":62,"value":3962},{"type":49,"tag":1346,"props":6660,"children":6661},{"style":1359},[6662],{"type":62,"value":523},{"type":49,"tag":1346,"props":6664,"children":6665},{"style":3917},[6666],{"type":62,"value":4237},{"type":49,"tag":1346,"props":6668,"children":6669},{"style":3192},[6670],{"type":62,"value":3976},{"type":49,"tag":1346,"props":6672,"children":6673},{"style":1359},[6674],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6676,"children":6677},{"style":1376},[6678],{"type":62,"value":5868},{"type":49,"tag":1346,"props":6680,"children":6681},{"style":1359},[6682],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6684,"children":6685},{"style":1359},[6686],{"type":62,"value":3822},{"type":49,"tag":1346,"props":6688,"children":6689},{"style":1365},[6690],{"type":62,"value":4263},{"type":49,"tag":1346,"props":6692,"children":6693},{"style":1359},[6694],{"type":62,"value":523},{"type":49,"tag":1346,"props":6696,"children":6697},{"style":1365},[6698],{"type":62,"value":4272},{"type":49,"tag":1346,"props":6700,"children":6701},{"style":3192},[6702],{"type":62,"value":1113},{"type":49,"tag":1346,"props":6704,"children":6705},{"style":1359},[6706],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6708,"children":6709},{"class":1348,"line":5231},[6710,6714,6718,6722,6726,6730],{"type":49,"tag":1346,"props":6711,"children":6712},{"style":3937},[6713],{"type":62,"value":4057},{"type":49,"tag":1346,"props":6715,"children":6716},{"style":1365},[6717],{"type":62,"value":4062},{"type":49,"tag":1346,"props":6719,"children":6720},{"style":1359},[6721],{"type":62,"value":523},{"type":49,"tag":1346,"props":6723,"children":6724},{"style":3917},[6725],{"type":62,"value":4071},{"type":49,"tag":1346,"props":6727,"children":6728},{"style":3192},[6729],{"type":62,"value":3976},{"type":49,"tag":1346,"props":6731,"children":6732},{"style":1359},[6733],{"type":62,"value":4080},{"type":49,"tag":1346,"props":6735,"children":6736},{"class":1348,"line":5311},[6737,6741,6745,6749,6753,6757],{"type":49,"tag":1346,"props":6738,"children":6739},{"style":3192},[6740],{"type":62,"value":4089},{"type":49,"tag":1346,"props":6742,"children":6743},{"style":1359},[6744],{"type":62,"value":468},{"type":49,"tag":1346,"props":6746,"children":6747},{"style":1359},[6748],{"type":62,"value":1389},{"type":49,"tag":1346,"props":6750,"children":6751},{"style":1376},[6752],{"type":62,"value":4329},{"type":49,"tag":1346,"props":6754,"children":6755},{"style":1359},[6756],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6758,"children":6759},{"style":1359},[6760],{"type":62,"value":4111},{"type":49,"tag":1346,"props":6762,"children":6763},{"class":1348,"line":5332},[6764,6768,6772,6776,6780],{"type":49,"tag":1346,"props":6765,"children":6766},{"style":3192},[6767],{"type":62,"value":4374},{"type":49,"tag":1346,"props":6769,"children":6770},{"style":1359},[6771],{"type":62,"value":468},{"type":49,"tag":1346,"props":6773,"children":6774},{"style":1365},[6775],{"type":62,"value":4263},{"type":49,"tag":1346,"props":6777,"children":6778},{"style":1359},[6779],{"type":62,"value":523},{"type":49,"tag":1346,"props":6781,"children":6782},{"style":1365},[6783],{"type":62,"value":4391},{"type":49,"tag":1346,"props":6785,"children":6786},{"class":1348,"line":5353},[6787,6791,6795],{"type":49,"tag":1346,"props":6788,"children":6789},{"style":1359},[6790],{"type":62,"value":4172},{"type":49,"tag":1346,"props":6792,"children":6793},{"style":3192},[6794],{"type":62,"value":1113},{"type":49,"tag":1346,"props":6796,"children":6797},{"style":1359},[6798],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6800,"children":6801},{"class":1348,"line":5371},[6802],{"type":49,"tag":1346,"props":6803,"children":6804},{"style":1359},[6805],{"type":62,"value":4416},{"type":49,"tag":1346,"props":6807,"children":6808},{"class":1348,"line":5388},[6809],{"type":49,"tag":1346,"props":6810,"children":6811},{"style":1359},[6812],{"type":62,"value":4425},{"type":49,"tag":54,"props":6814,"children":6815},{},[6816],{"type":49,"tag":58,"props":6817,"children":6818},{},[6819],{"type":62,"value":6820},"Entity-bound action:",{"type":49,"tag":1335,"props":6822,"children":6824},{"className":3722,"code":6823,"language":18,"meta":1340,"style":1340},"function post() {\n    try {\n        Server.Logger.Log(\"\u003Cname> POST called — invoking bound action \u003Ccustom-action-name>\");\n\n        const body = JSON.parse(Server.Context.Body);\n        const entityId = body.entityId;\n\n        const payload = JSON.stringify({\n            \u002F\u002F \"\u003CParameterName>\": body.\u003CclientFieldName>\n        });\n\n        \u002F\u002F Include the entity set and record ID, followed by the fully qualified action name\n        const result = Server.Connector.Dataverse.InvokeCustomApi(\n            \"POST\",\n            \"\u003Centity-set-name>(\" + entityId + \")\u002FMicrosoft.Dynamics.CRM.\u003Ccustom-action-name>\",\n            payload\n        );\n\n        Server.Logger.Log(\"\u003Cname> bound action completed for entity \" + entityId);\n\n        return JSON.stringify({\n            status: \"success\",\n            data: result,\n            entityId: entityId\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> POST failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            message: err.message\n        });\n    }\n}\n",[6825],{"type":49,"tag":67,"props":6826,"children":6827},{"__ignoreMap":1340},[6828,6847,6858,6906,6913,6972,7003,7010,7045,7052,7067,7074,7082,7129,7148,7193,7200,7211,7218,7274,7281,7308,7335,7354,7369,7384,7411,7474,7501,7528,7551,7566,7573],{"type":49,"tag":1346,"props":6829,"children":6830},{"class":1348,"line":1349},[6831,6835,6839,6843],{"type":49,"tag":1346,"props":6832,"children":6833},{"style":3742},[6834],{"type":62,"value":1488},{"type":49,"tag":1346,"props":6836,"children":6837},{"style":3917},[6838],{"type":62,"value":4508},{"type":49,"tag":1346,"props":6840,"children":6841},{"style":1359},[6842],{"type":62,"value":3925},{"type":49,"tag":1346,"props":6844,"children":6845},{"style":1359},[6846],{"type":62,"value":3930},{"type":49,"tag":1346,"props":6848,"children":6849},{"class":1348,"line":3208},[6850,6854],{"type":49,"tag":1346,"props":6851,"children":6852},{"style":3937},[6853],{"type":62,"value":3940},{"type":49,"tag":1346,"props":6855,"children":6856},{"style":1359},[6857],{"type":62,"value":3930},{"type":49,"tag":1346,"props":6859,"children":6860},{"class":1348,"line":3226},[6861,6865,6869,6873,6877,6881,6885,6889,6894,6898,6902],{"type":49,"tag":1346,"props":6862,"children":6863},{"style":1365},[6864],{"type":62,"value":3953},{"type":49,"tag":1346,"props":6866,"children":6867},{"style":1359},[6868],{"type":62,"value":523},{"type":49,"tag":1346,"props":6870,"children":6871},{"style":1365},[6872],{"type":62,"value":3962},{"type":49,"tag":1346,"props":6874,"children":6875},{"style":1359},[6876],{"type":62,"value":523},{"type":49,"tag":1346,"props":6878,"children":6879},{"style":3917},[6880],{"type":62,"value":3971},{"type":49,"tag":1346,"props":6882,"children":6883},{"style":3192},[6884],{"type":62,"value":3976},{"type":49,"tag":1346,"props":6886,"children":6887},{"style":1359},[6888],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6890,"children":6891},{"style":1376},[6892],{"type":62,"value":6893},"\u003Cname> POST called — invoking bound action \u003Ccustom-action-name>",{"type":49,"tag":1346,"props":6895,"children":6896},{"style":1359},[6897],{"type":62,"value":1384},{"type":49,"tag":1346,"props":6899,"children":6900},{"style":3192},[6901],{"type":62,"value":1113},{"type":49,"tag":1346,"props":6903,"children":6904},{"style":1359},[6905],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6907,"children":6908},{"class":1348,"line":3243},[6909],{"type":49,"tag":1346,"props":6910,"children":6911},{"emptyLinePlaceholder":42},[6912],{"type":62,"value":3781},{"type":49,"tag":1346,"props":6914,"children":6915},{"class":1348,"line":3261},[6916,6920,6924,6928,6932,6936,6940,6944,6948,6952,6956,6960,6964,6968],{"type":49,"tag":1346,"props":6917,"children":6918},{"style":3742},[6919],{"type":62,"value":4590},{"type":49,"tag":1346,"props":6921,"children":6922},{"style":1365},[6923],{"type":62,"value":4595},{"type":49,"tag":1346,"props":6925,"children":6926},{"style":1359},[6927],{"type":62,"value":4600},{"type":49,"tag":1346,"props":6929,"children":6930},{"style":1365},[6931],{"type":62,"value":4062},{"type":49,"tag":1346,"props":6933,"children":6934},{"style":1359},[6935],{"type":62,"value":523},{"type":49,"tag":1346,"props":6937,"children":6938},{"style":3917},[6939],{"type":62,"value":4613},{"type":49,"tag":1346,"props":6941,"children":6942},{"style":3192},[6943],{"type":62,"value":3976},{"type":49,"tag":1346,"props":6945,"children":6946},{"style":1365},[6947],{"type":62,"value":4622},{"type":49,"tag":1346,"props":6949,"children":6950},{"style":1359},[6951],{"type":62,"value":523},{"type":49,"tag":1346,"props":6953,"children":6954},{"style":1365},[6955],{"type":62,"value":1755},{"type":49,"tag":1346,"props":6957,"children":6958},{"style":1359},[6959],{"type":62,"value":523},{"type":49,"tag":1346,"props":6961,"children":6962},{"style":1365},[6963],{"type":62,"value":4639},{"type":49,"tag":1346,"props":6965,"children":6966},{"style":3192},[6967],{"type":62,"value":1113},{"type":49,"tag":1346,"props":6969,"children":6970},{"style":1359},[6971],{"type":62,"value":3773},{"type":49,"tag":1346,"props":6973,"children":6974},{"class":1348,"line":3933},[6975,6979,6983,6987,6991,6995,6999],{"type":49,"tag":1346,"props":6976,"children":6977},{"style":3742},[6978],{"type":62,"value":4590},{"type":49,"tag":1346,"props":6980,"children":6981},{"style":1365},[6982],{"type":62,"value":4659},{"type":49,"tag":1346,"props":6984,"children":6985},{"style":1359},[6986],{"type":62,"value":4600},{"type":49,"tag":1346,"props":6988,"children":6989},{"style":1365},[6990],{"type":62,"value":4595},{"type":49,"tag":1346,"props":6992,"children":6993},{"style":1359},[6994],{"type":62,"value":523},{"type":49,"tag":1346,"props":6996,"children":6997},{"style":1365},[6998],{"type":62,"value":4676},{"type":49,"tag":1346,"props":7000,"children":7001},{"style":1359},[7002],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7004,"children":7005},{"class":1348,"line":3947},[7006],{"type":49,"tag":1346,"props":7007,"children":7008},{"emptyLinePlaceholder":42},[7009],{"type":62,"value":3781},{"type":49,"tag":1346,"props":7011,"children":7012},{"class":1348,"line":4000},[7013,7017,7021,7025,7029,7033,7037,7041],{"type":49,"tag":1346,"props":7014,"children":7015},{"style":3742},[7016],{"type":62,"value":4590},{"type":49,"tag":1346,"props":7018,"children":7019},{"style":1365},[7020],{"type":62,"value":6307},{"type":49,"tag":1346,"props":7022,"children":7023},{"style":1359},[7024],{"type":62,"value":4600},{"type":49,"tag":1346,"props":7026,"children":7027},{"style":1365},[7028],{"type":62,"value":4062},{"type":49,"tag":1346,"props":7030,"children":7031},{"style":1359},[7032],{"type":62,"value":523},{"type":49,"tag":1346,"props":7034,"children":7035},{"style":3917},[7036],{"type":62,"value":4071},{"type":49,"tag":1346,"props":7038,"children":7039},{"style":3192},[7040],{"type":62,"value":3976},{"type":49,"tag":1346,"props":7042,"children":7043},{"style":1359},[7044],{"type":62,"value":4080},{"type":49,"tag":1346,"props":7046,"children":7047},{"class":1348,"line":4008},[7048],{"type":49,"tag":1346,"props":7049,"children":7050},{"style":3733},[7051],{"type":62,"value":6339},{"type":49,"tag":1346,"props":7053,"children":7054},{"class":1348,"line":4017},[7055,7059,7063],{"type":49,"tag":1346,"props":7056,"children":7057},{"style":1359},[7058],{"type":62,"value":4172},{"type":49,"tag":1346,"props":7060,"children":7061},{"style":3192},[7062],{"type":62,"value":1113},{"type":49,"tag":1346,"props":7064,"children":7065},{"style":1359},[7066],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7068,"children":7069},{"class":1348,"line":4026},[7070],{"type":49,"tag":1346,"props":7071,"children":7072},{"emptyLinePlaceholder":42},[7073],{"type":62,"value":3781},{"type":49,"tag":1346,"props":7075,"children":7076},{"class":1348,"line":4034},[7077],{"type":49,"tag":1346,"props":7078,"children":7079},{"style":3733},[7080],{"type":62,"value":7081},"        \u002F\u002F Include the entity set and record ID, followed by the fully qualified action name\n",{"type":49,"tag":1346,"props":7083,"children":7084},{"class":1348,"line":4043},[7085,7089,7093,7097,7101,7105,7109,7113,7117,7121,7125],{"type":49,"tag":1346,"props":7086,"children":7087},{"style":3742},[7088],{"type":62,"value":4590},{"type":49,"tag":1346,"props":7090,"children":7091},{"style":1365},[7092],{"type":62,"value":6373},{"type":49,"tag":1346,"props":7094,"children":7095},{"style":1359},[7096],{"type":62,"value":4600},{"type":49,"tag":1346,"props":7098,"children":7099},{"style":1365},[7100],{"type":62,"value":4749},{"type":49,"tag":1346,"props":7102,"children":7103},{"style":1359},[7104],{"type":62,"value":523},{"type":49,"tag":1346,"props":7106,"children":7107},{"style":1365},[7108],{"type":62,"value":4758},{"type":49,"tag":1346,"props":7110,"children":7111},{"style":1359},[7112],{"type":62,"value":523},{"type":49,"tag":1346,"props":7114,"children":7115},{"style":1365},[7116],{"type":62,"value":4767},{"type":49,"tag":1346,"props":7118,"children":7119},{"style":1359},[7120],{"type":62,"value":523},{"type":49,"tag":1346,"props":7122,"children":7123},{"style":3917},[7124],{"type":62,"value":1805},{"type":49,"tag":1346,"props":7126,"children":7127},{"style":3192},[7128],{"type":62,"value":6410},{"type":49,"tag":1346,"props":7130,"children":7131},{"class":1348,"line":4051},[7132,7136,7140,7144],{"type":49,"tag":1346,"props":7133,"children":7134},{"style":1359},[7135],{"type":62,"value":4917},{"type":49,"tag":1346,"props":7137,"children":7138},{"style":1376},[7139],{"type":62,"value":1826},{"type":49,"tag":1346,"props":7141,"children":7142},{"style":1359},[7143],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7145,"children":7146},{"style":1359},[7147],{"type":62,"value":4111},{"type":49,"tag":1346,"props":7149,"children":7150},{"class":1348,"line":4083},[7151,7155,7160,7164,7168,7172,7176,7180,7185,7189],{"type":49,"tag":1346,"props":7152,"children":7153},{"style":1359},[7154],{"type":62,"value":4917},{"type":49,"tag":1346,"props":7156,"children":7157},{"style":1376},[7158],{"type":62,"value":7159},"\u003Centity-set-name>(",{"type":49,"tag":1346,"props":7161,"children":7162},{"style":1359},[7163],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7165,"children":7166},{"style":1359},[7167],{"type":62,"value":3822},{"type":49,"tag":1346,"props":7169,"children":7170},{"style":1365},[7171],{"type":62,"value":4659},{"type":49,"tag":1346,"props":7173,"children":7174},{"style":1359},[7175],{"type":62,"value":3822},{"type":49,"tag":1346,"props":7177,"children":7178},{"style":1359},[7179],{"type":62,"value":1389},{"type":49,"tag":1346,"props":7181,"children":7182},{"style":1376},[7183],{"type":62,"value":7184},")\u002FMicrosoft.Dynamics.CRM.\u003Ccustom-action-name>",{"type":49,"tag":1346,"props":7186,"children":7187},{"style":1359},[7188],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7190,"children":7191},{"style":1359},[7192],{"type":62,"value":4111},{"type":49,"tag":1346,"props":7194,"children":7195},{"class":1348,"line":4114},[7196],{"type":49,"tag":1346,"props":7197,"children":7198},{"style":1365},[7199],{"type":62,"value":6457},{"type":49,"tag":1346,"props":7201,"children":7202},{"class":1348,"line":4143},[7203,7207],{"type":49,"tag":1346,"props":7204,"children":7205},{"style":3192},[7206],{"type":62,"value":6465},{"type":49,"tag":1346,"props":7208,"children":7209},{"style":1359},[7210],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7212,"children":7213},{"class":1348,"line":4166},[7214],{"type":49,"tag":1346,"props":7215,"children":7216},{"emptyLinePlaceholder":42},[7217],{"type":62,"value":3781},{"type":49,"tag":1346,"props":7219,"children":7220},{"class":1348,"line":4183},[7221,7225,7229,7233,7237,7241,7245,7249,7254,7258,7262,7266,7270],{"type":49,"tag":1346,"props":7222,"children":7223},{"style":1365},[7224],{"type":62,"value":3953},{"type":49,"tag":1346,"props":7226,"children":7227},{"style":1359},[7228],{"type":62,"value":523},{"type":49,"tag":1346,"props":7230,"children":7231},{"style":1365},[7232],{"type":62,"value":3962},{"type":49,"tag":1346,"props":7234,"children":7235},{"style":1359},[7236],{"type":62,"value":523},{"type":49,"tag":1346,"props":7238,"children":7239},{"style":3917},[7240],{"type":62,"value":3971},{"type":49,"tag":1346,"props":7242,"children":7243},{"style":3192},[7244],{"type":62,"value":3976},{"type":49,"tag":1346,"props":7246,"children":7247},{"style":1359},[7248],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7250,"children":7251},{"style":1376},[7252],{"type":62,"value":7253},"\u003Cname> bound action completed for entity ",{"type":49,"tag":1346,"props":7255,"children":7256},{"style":1359},[7257],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7259,"children":7260},{"style":1359},[7261],{"type":62,"value":3822},{"type":49,"tag":1346,"props":7263,"children":7264},{"style":1365},[7265],{"type":62,"value":4659},{"type":49,"tag":1346,"props":7267,"children":7268},{"style":3192},[7269],{"type":62,"value":1113},{"type":49,"tag":1346,"props":7271,"children":7272},{"style":1359},[7273],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7275,"children":7276},{"class":1348,"line":4215},[7277],{"type":49,"tag":1346,"props":7278,"children":7279},{"emptyLinePlaceholder":42},[7280],{"type":62,"value":3781},{"type":49,"tag":1346,"props":7282,"children":7283},{"class":1348,"line":4283},[7284,7288,7292,7296,7300,7304],{"type":49,"tag":1346,"props":7285,"children":7286},{"style":3937},[7287],{"type":62,"value":4057},{"type":49,"tag":1346,"props":7289,"children":7290},{"style":1365},[7291],{"type":62,"value":4062},{"type":49,"tag":1346,"props":7293,"children":7294},{"style":1359},[7295],{"type":62,"value":523},{"type":49,"tag":1346,"props":7297,"children":7298},{"style":3917},[7299],{"type":62,"value":4071},{"type":49,"tag":1346,"props":7301,"children":7302},{"style":3192},[7303],{"type":62,"value":3976},{"type":49,"tag":1346,"props":7305,"children":7306},{"style":1359},[7307],{"type":62,"value":4080},{"type":49,"tag":1346,"props":7309,"children":7310},{"class":1348,"line":4311},[7311,7315,7319,7323,7327,7331],{"type":49,"tag":1346,"props":7312,"children":7313},{"style":3192},[7314],{"type":62,"value":4089},{"type":49,"tag":1346,"props":7316,"children":7317},{"style":1359},[7318],{"type":62,"value":468},{"type":49,"tag":1346,"props":7320,"children":7321},{"style":1359},[7322],{"type":62,"value":1389},{"type":49,"tag":1346,"props":7324,"children":7325},{"style":1376},[7326],{"type":62,"value":4102},{"type":49,"tag":1346,"props":7328,"children":7329},{"style":1359},[7330],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7332,"children":7333},{"style":1359},[7334],{"type":62,"value":4111},{"type":49,"tag":1346,"props":7336,"children":7337},{"class":1348,"line":4340},[7338,7342,7346,7350],{"type":49,"tag":1346,"props":7339,"children":7340},{"style":3192},[7341],{"type":62,"value":4149},{"type":49,"tag":1346,"props":7343,"children":7344},{"style":1359},[7345],{"type":62,"value":468},{"type":49,"tag":1346,"props":7347,"children":7348},{"style":1365},[7349],{"type":62,"value":6373},{"type":49,"tag":1346,"props":7351,"children":7352},{"style":1359},[7353],{"type":62,"value":4111},{"type":49,"tag":1346,"props":7355,"children":7356},{"class":1348,"line":4368},[7357,7361,7365],{"type":49,"tag":1346,"props":7358,"children":7359},{"style":3192},[7360],{"type":62,"value":5778},{"type":49,"tag":1346,"props":7362,"children":7363},{"style":1359},[7364],{"type":62,"value":468},{"type":49,"tag":1346,"props":7366,"children":7367},{"style":1365},[7368],{"type":62,"value":5787},{"type":49,"tag":1346,"props":7370,"children":7371},{"class":1348,"line":4394},[7372,7376,7380],{"type":49,"tag":1346,"props":7373,"children":7374},{"style":1359},[7375],{"type":62,"value":4172},{"type":49,"tag":1346,"props":7377,"children":7378},{"style":3192},[7379],{"type":62,"value":1113},{"type":49,"tag":1346,"props":7381,"children":7382},{"style":1359},[7383],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7385,"children":7386},{"class":1348,"line":4410},[7387,7391,7395,7399,7403,7407],{"type":49,"tag":1346,"props":7388,"children":7389},{"style":1359},[7390],{"type":62,"value":4189},{"type":49,"tag":1346,"props":7392,"children":7393},{"style":3937},[7394],{"type":62,"value":4194},{"type":49,"tag":1346,"props":7396,"children":7397},{"style":3192},[7398],{"type":62,"value":1474},{"type":49,"tag":1346,"props":7400,"children":7401},{"style":1365},[7402],{"type":62,"value":4203},{"type":49,"tag":1346,"props":7404,"children":7405},{"style":3192},[7406],{"type":62,"value":4208},{"type":49,"tag":1346,"props":7408,"children":7409},{"style":1359},[7410],{"type":62,"value":4080},{"type":49,"tag":1346,"props":7412,"children":7413},{"class":1348,"line":4419},[7414,7418,7422,7426,7430,7434,7438,7442,7446,7450,7454,7458,7462,7466,7470],{"type":49,"tag":1346,"props":7415,"children":7416},{"style":1365},[7417],{"type":62,"value":3953},{"type":49,"tag":1346,"props":7419,"children":7420},{"style":1359},[7421],{"type":62,"value":523},{"type":49,"tag":1346,"props":7423,"children":7424},{"style":1365},[7425],{"type":62,"value":3962},{"type":49,"tag":1346,"props":7427,"children":7428},{"style":1359},[7429],{"type":62,"value":523},{"type":49,"tag":1346,"props":7431,"children":7432},{"style":3917},[7433],{"type":62,"value":4237},{"type":49,"tag":1346,"props":7435,"children":7436},{"style":3192},[7437],{"type":62,"value":3976},{"type":49,"tag":1346,"props":7439,"children":7440},{"style":1359},[7441],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7443,"children":7444},{"style":1376},[7445],{"type":62,"value":5868},{"type":49,"tag":1346,"props":7447,"children":7448},{"style":1359},[7449],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7451,"children":7452},{"style":1359},[7453],{"type":62,"value":3822},{"type":49,"tag":1346,"props":7455,"children":7456},{"style":1365},[7457],{"type":62,"value":4263},{"type":49,"tag":1346,"props":7459,"children":7460},{"style":1359},[7461],{"type":62,"value":523},{"type":49,"tag":1346,"props":7463,"children":7464},{"style":1365},[7465],{"type":62,"value":4272},{"type":49,"tag":1346,"props":7467,"children":7468},{"style":3192},[7469],{"type":62,"value":1113},{"type":49,"tag":1346,"props":7471,"children":7472},{"style":1359},[7473],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7475,"children":7476},{"class":1348,"line":5124},[7477,7481,7485,7489,7493,7497],{"type":49,"tag":1346,"props":7478,"children":7479},{"style":3937},[7480],{"type":62,"value":4057},{"type":49,"tag":1346,"props":7482,"children":7483},{"style":1365},[7484],{"type":62,"value":4062},{"type":49,"tag":1346,"props":7486,"children":7487},{"style":1359},[7488],{"type":62,"value":523},{"type":49,"tag":1346,"props":7490,"children":7491},{"style":3917},[7492],{"type":62,"value":4071},{"type":49,"tag":1346,"props":7494,"children":7495},{"style":3192},[7496],{"type":62,"value":3976},{"type":49,"tag":1346,"props":7498,"children":7499},{"style":1359},[7500],{"type":62,"value":4080},{"type":49,"tag":1346,"props":7502,"children":7503},{"class":1348,"line":5173},[7504,7508,7512,7516,7520,7524],{"type":49,"tag":1346,"props":7505,"children":7506},{"style":3192},[7507],{"type":62,"value":4089},{"type":49,"tag":1346,"props":7509,"children":7510},{"style":1359},[7511],{"type":62,"value":468},{"type":49,"tag":1346,"props":7513,"children":7514},{"style":1359},[7515],{"type":62,"value":1389},{"type":49,"tag":1346,"props":7517,"children":7518},{"style":1376},[7519],{"type":62,"value":4329},{"type":49,"tag":1346,"props":7521,"children":7522},{"style":1359},[7523],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7525,"children":7526},{"style":1359},[7527],{"type":62,"value":4111},{"type":49,"tag":1346,"props":7529,"children":7530},{"class":1348,"line":5202},[7531,7535,7539,7543,7547],{"type":49,"tag":1346,"props":7532,"children":7533},{"style":3192},[7534],{"type":62,"value":4374},{"type":49,"tag":1346,"props":7536,"children":7537},{"style":1359},[7538],{"type":62,"value":468},{"type":49,"tag":1346,"props":7540,"children":7541},{"style":1365},[7542],{"type":62,"value":4263},{"type":49,"tag":1346,"props":7544,"children":7545},{"style":1359},[7546],{"type":62,"value":523},{"type":49,"tag":1346,"props":7548,"children":7549},{"style":1365},[7550],{"type":62,"value":4391},{"type":49,"tag":1346,"props":7552,"children":7553},{"class":1348,"line":5231},[7554,7558,7562],{"type":49,"tag":1346,"props":7555,"children":7556},{"style":1359},[7557],{"type":62,"value":4172},{"type":49,"tag":1346,"props":7559,"children":7560},{"style":3192},[7561],{"type":62,"value":1113},{"type":49,"tag":1346,"props":7563,"children":7564},{"style":1359},[7565],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7567,"children":7568},{"class":1348,"line":5311},[7569],{"type":49,"tag":1346,"props":7570,"children":7571},{"style":1359},[7572],{"type":62,"value":4416},{"type":49,"tag":1346,"props":7574,"children":7575},{"class":1348,"line":5332},[7576],{"type":49,"tag":1346,"props":7577,"children":7578},{"style":1359},[7579],{"type":62,"value":4425},{"type":49,"tag":54,"props":7581,"children":7582},{},[7583],{"type":49,"tag":58,"props":7584,"children":7585},{},[7586],{"type":62,"value":7587},"Unbound function (read-only, GET):",{"type":49,"tag":1335,"props":7589,"children":7591},{"className":3722,"code":7590,"language":18,"meta":1340,"style":1340},"function get() {\n    try {\n        Server.Logger.Log(\"\u003Cname> GET called — invoking custom function \u003Ccustom-function-name>\");\n\n        \u002F\u002F Pass parameters as query string for functions\n        const param1 = Server.Context.QueryParameters[\"param1\"];\n        const queryString = \"\u003Ccustom-function-name>(Param1='\" + param1 + \"')\";\n\n        const result = Server.Connector.Dataverse.InvokeCustomApi(\n            \"GET\",\n            queryString,\n            null\n        );\n\n        Server.Logger.Log(\"\u003Cname> custom function completed successfully\");\n\n        return JSON.stringify({\n            status: \"success\",\n            data: result\n        });\n    } catch (err) {\n        Server.Logger.Error(\"\u003Cname> GET failed: \" + err.message);\n        return JSON.stringify({\n            status: \"error\",\n            message: err.message\n        });\n    }\n}\n",[7592],{"type":49,"tag":67,"props":7593,"children":7594},{"__ignoreMap":1340},[7595,7614,7625,7673,7680,7688,7750,7808,7815,7862,7881,7893,7901,7912,7919,7967,7974,8001,8028,8043,8058,8085,8148,8175,8202,8225,8240,8247],{"type":49,"tag":1346,"props":7596,"children":7597},{"class":1348,"line":1349},[7598,7602,7606,7610],{"type":49,"tag":1346,"props":7599,"children":7600},{"style":3742},[7601],{"type":62,"value":1488},{"type":49,"tag":1346,"props":7603,"children":7604},{"style":3917},[7605],{"type":62,"value":3920},{"type":49,"tag":1346,"props":7607,"children":7608},{"style":1359},[7609],{"type":62,"value":3925},{"type":49,"tag":1346,"props":7611,"children":7612},{"style":1359},[7613],{"type":62,"value":3930},{"type":49,"tag":1346,"props":7615,"children":7616},{"class":1348,"line":3208},[7617,7621],{"type":49,"tag":1346,"props":7618,"children":7619},{"style":3937},[7620],{"type":62,"value":3940},{"type":49,"tag":1346,"props":7622,"children":7623},{"style":1359},[7624],{"type":62,"value":3930},{"type":49,"tag":1346,"props":7626,"children":7627},{"class":1348,"line":3226},[7628,7632,7636,7640,7644,7648,7652,7656,7661,7665,7669],{"type":49,"tag":1346,"props":7629,"children":7630},{"style":1365},[7631],{"type":62,"value":3953},{"type":49,"tag":1346,"props":7633,"children":7634},{"style":1359},[7635],{"type":62,"value":523},{"type":49,"tag":1346,"props":7637,"children":7638},{"style":1365},[7639],{"type":62,"value":3962},{"type":49,"tag":1346,"props":7641,"children":7642},{"style":1359},[7643],{"type":62,"value":523},{"type":49,"tag":1346,"props":7645,"children":7646},{"style":3917},[7647],{"type":62,"value":3971},{"type":49,"tag":1346,"props":7649,"children":7650},{"style":3192},[7651],{"type":62,"value":3976},{"type":49,"tag":1346,"props":7653,"children":7654},{"style":1359},[7655],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7657,"children":7658},{"style":1376},[7659],{"type":62,"value":7660},"\u003Cname> GET called — invoking custom function \u003Ccustom-function-name>",{"type":49,"tag":1346,"props":7662,"children":7663},{"style":1359},[7664],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7666,"children":7667},{"style":3192},[7668],{"type":62,"value":1113},{"type":49,"tag":1346,"props":7670,"children":7671},{"style":1359},[7672],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7674,"children":7675},{"class":1348,"line":3243},[7676],{"type":49,"tag":1346,"props":7677,"children":7678},{"emptyLinePlaceholder":42},[7679],{"type":62,"value":3781},{"type":49,"tag":1346,"props":7681,"children":7682},{"class":1348,"line":3261},[7683],{"type":49,"tag":1346,"props":7684,"children":7685},{"style":3733},[7686],{"type":62,"value":7687},"        \u002F\u002F Pass parameters as query string for functions\n",{"type":49,"tag":1346,"props":7689,"children":7690},{"class":1348,"line":3933},[7691,7695,7700,7704,7708,7712,7716,7720,7725,7729,7733,7738,7742,7746],{"type":49,"tag":1346,"props":7692,"children":7693},{"style":3742},[7694],{"type":62,"value":4590},{"type":49,"tag":1346,"props":7696,"children":7697},{"style":1365},[7698],{"type":62,"value":7699}," param1",{"type":49,"tag":1346,"props":7701,"children":7702},{"style":1359},[7703],{"type":62,"value":4600},{"type":49,"tag":1346,"props":7705,"children":7706},{"style":1365},[7707],{"type":62,"value":4749},{"type":49,"tag":1346,"props":7709,"children":7710},{"style":1359},[7711],{"type":62,"value":523},{"type":49,"tag":1346,"props":7713,"children":7714},{"style":1365},[7715],{"type":62,"value":1755},{"type":49,"tag":1346,"props":7717,"children":7718},{"style":1359},[7719],{"type":62,"value":523},{"type":49,"tag":1346,"props":7721,"children":7722},{"style":1365},[7723],{"type":62,"value":7724},"QueryParameters",{"type":49,"tag":1346,"props":7726,"children":7727},{"style":3192},[7728],{"type":62,"value":4852},{"type":49,"tag":1346,"props":7730,"children":7731},{"style":1359},[7732],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7734,"children":7735},{"style":1376},[7736],{"type":62,"value":7737},"param1",{"type":49,"tag":1346,"props":7739,"children":7740},{"style":1359},[7741],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7743,"children":7744},{"style":3192},[7745],{"type":62,"value":4870},{"type":49,"tag":1346,"props":7747,"children":7748},{"style":1359},[7749],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7751,"children":7752},{"class":1348,"line":3947},[7753,7757,7762,7766,7770,7775,7779,7783,7787,7791,7795,7800,7804],{"type":49,"tag":1346,"props":7754,"children":7755},{"style":3742},[7756],{"type":62,"value":4590},{"type":49,"tag":1346,"props":7758,"children":7759},{"style":1365},[7760],{"type":62,"value":7761}," queryString",{"type":49,"tag":1346,"props":7763,"children":7764},{"style":1359},[7765],{"type":62,"value":4600},{"type":49,"tag":1346,"props":7767,"children":7768},{"style":1359},[7769],{"type":62,"value":1389},{"type":49,"tag":1346,"props":7771,"children":7772},{"style":1376},[7773],{"type":62,"value":7774},"\u003Ccustom-function-name>(Param1='",{"type":49,"tag":1346,"props":7776,"children":7777},{"style":1359},[7778],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7780,"children":7781},{"style":1359},[7782],{"type":62,"value":3822},{"type":49,"tag":1346,"props":7784,"children":7785},{"style":1365},[7786],{"type":62,"value":7699},{"type":49,"tag":1346,"props":7788,"children":7789},{"style":1359},[7790],{"type":62,"value":3822},{"type":49,"tag":1346,"props":7792,"children":7793},{"style":1359},[7794],{"type":62,"value":1389},{"type":49,"tag":1346,"props":7796,"children":7797},{"style":1376},[7798],{"type":62,"value":7799},"')",{"type":49,"tag":1346,"props":7801,"children":7802},{"style":1359},[7803],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7805,"children":7806},{"style":1359},[7807],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7809,"children":7810},{"class":1348,"line":4000},[7811],{"type":49,"tag":1346,"props":7812,"children":7813},{"emptyLinePlaceholder":42},[7814],{"type":62,"value":3781},{"type":49,"tag":1346,"props":7816,"children":7817},{"class":1348,"line":4008},[7818,7822,7826,7830,7834,7838,7842,7846,7850,7854,7858],{"type":49,"tag":1346,"props":7819,"children":7820},{"style":3742},[7821],{"type":62,"value":4590},{"type":49,"tag":1346,"props":7823,"children":7824},{"style":1365},[7825],{"type":62,"value":6373},{"type":49,"tag":1346,"props":7827,"children":7828},{"style":1359},[7829],{"type":62,"value":4600},{"type":49,"tag":1346,"props":7831,"children":7832},{"style":1365},[7833],{"type":62,"value":4749},{"type":49,"tag":1346,"props":7835,"children":7836},{"style":1359},[7837],{"type":62,"value":523},{"type":49,"tag":1346,"props":7839,"children":7840},{"style":1365},[7841],{"type":62,"value":4758},{"type":49,"tag":1346,"props":7843,"children":7844},{"style":1359},[7845],{"type":62,"value":523},{"type":49,"tag":1346,"props":7847,"children":7848},{"style":1365},[7849],{"type":62,"value":4767},{"type":49,"tag":1346,"props":7851,"children":7852},{"style":1359},[7853],{"type":62,"value":523},{"type":49,"tag":1346,"props":7855,"children":7856},{"style":3917},[7857],{"type":62,"value":1805},{"type":49,"tag":1346,"props":7859,"children":7860},{"style":3192},[7861],{"type":62,"value":6410},{"type":49,"tag":1346,"props":7863,"children":7864},{"class":1348,"line":4017},[7865,7869,7873,7877],{"type":49,"tag":1346,"props":7866,"children":7867},{"style":1359},[7868],{"type":62,"value":4917},{"type":49,"tag":1346,"props":7870,"children":7871},{"style":1376},[7872],{"type":62,"value":1818},{"type":49,"tag":1346,"props":7874,"children":7875},{"style":1359},[7876],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7878,"children":7879},{"style":1359},[7880],{"type":62,"value":4111},{"type":49,"tag":1346,"props":7882,"children":7883},{"class":1348,"line":4026},[7884,7889],{"type":49,"tag":1346,"props":7885,"children":7886},{"style":1365},[7887],{"type":62,"value":7888},"            queryString",{"type":49,"tag":1346,"props":7890,"children":7891},{"style":1359},[7892],{"type":62,"value":4111},{"type":49,"tag":1346,"props":7894,"children":7895},{"class":1348,"line":4034},[7896],{"type":49,"tag":1346,"props":7897,"children":7898},{"style":1359},[7899],{"type":62,"value":7900},"            null\n",{"type":49,"tag":1346,"props":7902,"children":7903},{"class":1348,"line":4043},[7904,7908],{"type":49,"tag":1346,"props":7905,"children":7906},{"style":3192},[7907],{"type":62,"value":6465},{"type":49,"tag":1346,"props":7909,"children":7910},{"style":1359},[7911],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7913,"children":7914},{"class":1348,"line":4051},[7915],{"type":49,"tag":1346,"props":7916,"children":7917},{"emptyLinePlaceholder":42},[7918],{"type":62,"value":3781},{"type":49,"tag":1346,"props":7920,"children":7921},{"class":1348,"line":4083},[7922,7926,7930,7934,7938,7942,7946,7950,7955,7959,7963],{"type":49,"tag":1346,"props":7923,"children":7924},{"style":1365},[7925],{"type":62,"value":3953},{"type":49,"tag":1346,"props":7927,"children":7928},{"style":1359},[7929],{"type":62,"value":523},{"type":49,"tag":1346,"props":7931,"children":7932},{"style":1365},[7933],{"type":62,"value":3962},{"type":49,"tag":1346,"props":7935,"children":7936},{"style":1359},[7937],{"type":62,"value":523},{"type":49,"tag":1346,"props":7939,"children":7940},{"style":3917},[7941],{"type":62,"value":3971},{"type":49,"tag":1346,"props":7943,"children":7944},{"style":3192},[7945],{"type":62,"value":3976},{"type":49,"tag":1346,"props":7947,"children":7948},{"style":1359},[7949],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7951,"children":7952},{"style":1376},[7953],{"type":62,"value":7954},"\u003Cname> custom function completed successfully",{"type":49,"tag":1346,"props":7956,"children":7957},{"style":1359},[7958],{"type":62,"value":1384},{"type":49,"tag":1346,"props":7960,"children":7961},{"style":3192},[7962],{"type":62,"value":1113},{"type":49,"tag":1346,"props":7964,"children":7965},{"style":1359},[7966],{"type":62,"value":3773},{"type":49,"tag":1346,"props":7968,"children":7969},{"class":1348,"line":4114},[7970],{"type":49,"tag":1346,"props":7971,"children":7972},{"emptyLinePlaceholder":42},[7973],{"type":62,"value":3781},{"type":49,"tag":1346,"props":7975,"children":7976},{"class":1348,"line":4143},[7977,7981,7985,7989,7993,7997],{"type":49,"tag":1346,"props":7978,"children":7979},{"style":3937},[7980],{"type":62,"value":4057},{"type":49,"tag":1346,"props":7982,"children":7983},{"style":1365},[7984],{"type":62,"value":4062},{"type":49,"tag":1346,"props":7986,"children":7987},{"style":1359},[7988],{"type":62,"value":523},{"type":49,"tag":1346,"props":7990,"children":7991},{"style":3917},[7992],{"type":62,"value":4071},{"type":49,"tag":1346,"props":7994,"children":7995},{"style":3192},[7996],{"type":62,"value":3976},{"type":49,"tag":1346,"props":7998,"children":7999},{"style":1359},[8000],{"type":62,"value":4080},{"type":49,"tag":1346,"props":8002,"children":8003},{"class":1348,"line":4166},[8004,8008,8012,8016,8020,8024],{"type":49,"tag":1346,"props":8005,"children":8006},{"style":3192},[8007],{"type":62,"value":4089},{"type":49,"tag":1346,"props":8009,"children":8010},{"style":1359},[8011],{"type":62,"value":468},{"type":49,"tag":1346,"props":8013,"children":8014},{"style":1359},[8015],{"type":62,"value":1389},{"type":49,"tag":1346,"props":8017,"children":8018},{"style":1376},[8019],{"type":62,"value":4102},{"type":49,"tag":1346,"props":8021,"children":8022},{"style":1359},[8023],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8025,"children":8026},{"style":1359},[8027],{"type":62,"value":4111},{"type":49,"tag":1346,"props":8029,"children":8030},{"class":1348,"line":4183},[8031,8035,8039],{"type":49,"tag":1346,"props":8032,"children":8033},{"style":3192},[8034],{"type":62,"value":4149},{"type":49,"tag":1346,"props":8036,"children":8037},{"style":1359},[8038],{"type":62,"value":468},{"type":49,"tag":1346,"props":8040,"children":8041},{"style":1365},[8042],{"type":62,"value":6601},{"type":49,"tag":1346,"props":8044,"children":8045},{"class":1348,"line":4215},[8046,8050,8054],{"type":49,"tag":1346,"props":8047,"children":8048},{"style":1359},[8049],{"type":62,"value":4172},{"type":49,"tag":1346,"props":8051,"children":8052},{"style":3192},[8053],{"type":62,"value":1113},{"type":49,"tag":1346,"props":8055,"children":8056},{"style":1359},[8057],{"type":62,"value":3773},{"type":49,"tag":1346,"props":8059,"children":8060},{"class":1348,"line":4283},[8061,8065,8069,8073,8077,8081],{"type":49,"tag":1346,"props":8062,"children":8063},{"style":1359},[8064],{"type":62,"value":4189},{"type":49,"tag":1346,"props":8066,"children":8067},{"style":3937},[8068],{"type":62,"value":4194},{"type":49,"tag":1346,"props":8070,"children":8071},{"style":3192},[8072],{"type":62,"value":1474},{"type":49,"tag":1346,"props":8074,"children":8075},{"style":1365},[8076],{"type":62,"value":4203},{"type":49,"tag":1346,"props":8078,"children":8079},{"style":3192},[8080],{"type":62,"value":4208},{"type":49,"tag":1346,"props":8082,"children":8083},{"style":1359},[8084],{"type":62,"value":4080},{"type":49,"tag":1346,"props":8086,"children":8087},{"class":1348,"line":4311},[8088,8092,8096,8100,8104,8108,8112,8116,8120,8124,8128,8132,8136,8140,8144],{"type":49,"tag":1346,"props":8089,"children":8090},{"style":1365},[8091],{"type":62,"value":3953},{"type":49,"tag":1346,"props":8093,"children":8094},{"style":1359},[8095],{"type":62,"value":523},{"type":49,"tag":1346,"props":8097,"children":8098},{"style":1365},[8099],{"type":62,"value":3962},{"type":49,"tag":1346,"props":8101,"children":8102},{"style":1359},[8103],{"type":62,"value":523},{"type":49,"tag":1346,"props":8105,"children":8106},{"style":3917},[8107],{"type":62,"value":4237},{"type":49,"tag":1346,"props":8109,"children":8110},{"style":3192},[8111],{"type":62,"value":3976},{"type":49,"tag":1346,"props":8113,"children":8114},{"style":1359},[8115],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8117,"children":8118},{"style":1376},[8119],{"type":62,"value":4250},{"type":49,"tag":1346,"props":8121,"children":8122},{"style":1359},[8123],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8125,"children":8126},{"style":1359},[8127],{"type":62,"value":3822},{"type":49,"tag":1346,"props":8129,"children":8130},{"style":1365},[8131],{"type":62,"value":4263},{"type":49,"tag":1346,"props":8133,"children":8134},{"style":1359},[8135],{"type":62,"value":523},{"type":49,"tag":1346,"props":8137,"children":8138},{"style":1365},[8139],{"type":62,"value":4272},{"type":49,"tag":1346,"props":8141,"children":8142},{"style":3192},[8143],{"type":62,"value":1113},{"type":49,"tag":1346,"props":8145,"children":8146},{"style":1359},[8147],{"type":62,"value":3773},{"type":49,"tag":1346,"props":8149,"children":8150},{"class":1348,"line":4340},[8151,8155,8159,8163,8167,8171],{"type":49,"tag":1346,"props":8152,"children":8153},{"style":3937},[8154],{"type":62,"value":4057},{"type":49,"tag":1346,"props":8156,"children":8157},{"style":1365},[8158],{"type":62,"value":4062},{"type":49,"tag":1346,"props":8160,"children":8161},{"style":1359},[8162],{"type":62,"value":523},{"type":49,"tag":1346,"props":8164,"children":8165},{"style":3917},[8166],{"type":62,"value":4071},{"type":49,"tag":1346,"props":8168,"children":8169},{"style":3192},[8170],{"type":62,"value":3976},{"type":49,"tag":1346,"props":8172,"children":8173},{"style":1359},[8174],{"type":62,"value":4080},{"type":49,"tag":1346,"props":8176,"children":8177},{"class":1348,"line":4368},[8178,8182,8186,8190,8194,8198],{"type":49,"tag":1346,"props":8179,"children":8180},{"style":3192},[8181],{"type":62,"value":4089},{"type":49,"tag":1346,"props":8183,"children":8184},{"style":1359},[8185],{"type":62,"value":468},{"type":49,"tag":1346,"props":8187,"children":8188},{"style":1359},[8189],{"type":62,"value":1389},{"type":49,"tag":1346,"props":8191,"children":8192},{"style":1376},[8193],{"type":62,"value":4329},{"type":49,"tag":1346,"props":8195,"children":8196},{"style":1359},[8197],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8199,"children":8200},{"style":1359},[8201],{"type":62,"value":4111},{"type":49,"tag":1346,"props":8203,"children":8204},{"class":1348,"line":4394},[8205,8209,8213,8217,8221],{"type":49,"tag":1346,"props":8206,"children":8207},{"style":3192},[8208],{"type":62,"value":4374},{"type":49,"tag":1346,"props":8210,"children":8211},{"style":1359},[8212],{"type":62,"value":468},{"type":49,"tag":1346,"props":8214,"children":8215},{"style":1365},[8216],{"type":62,"value":4263},{"type":49,"tag":1346,"props":8218,"children":8219},{"style":1359},[8220],{"type":62,"value":523},{"type":49,"tag":1346,"props":8222,"children":8223},{"style":1365},[8224],{"type":62,"value":4391},{"type":49,"tag":1346,"props":8226,"children":8227},{"class":1348,"line":4410},[8228,8232,8236],{"type":49,"tag":1346,"props":8229,"children":8230},{"style":1359},[8231],{"type":62,"value":4172},{"type":49,"tag":1346,"props":8233,"children":8234},{"style":3192},[8235],{"type":62,"value":1113},{"type":49,"tag":1346,"props":8237,"children":8238},{"style":1359},[8239],{"type":62,"value":3773},{"type":49,"tag":1346,"props":8241,"children":8242},{"class":1348,"line":4419},[8243],{"type":49,"tag":1346,"props":8244,"children":8245},{"style":1359},[8246],{"type":62,"value":4416},{"type":49,"tag":1346,"props":8248,"children":8249},{"class":1348,"line":5124},[8250],{"type":49,"tag":1346,"props":8251,"children":8252},{"style":1359},[8253],{"type":62,"value":4425},{"type":49,"tag":54,"props":8255,"children":8256},{},[8257],{"type":49,"tag":58,"props":8258,"children":8259},{},[8260],{"type":62,"value":8261},"Key points:",{"type":49,"tag":94,"props":8263,"children":8264},{},[8265,8275,8291,8308,8325,8351,8356],{"type":49,"tag":98,"props":8266,"children":8267},{},[8268,8273],{"type":49,"tag":58,"props":8269,"children":8270},{},[8271],{"type":62,"value":8272},"Unbound actions",{"type":62,"value":8274},": Use the action name as the URL, pass parameters as JSON body",{"type":49,"tag":98,"props":8276,"children":8277},{},[8278,8283,8285],{"type":49,"tag":58,"props":8279,"children":8280},{},[8281],{"type":62,"value":8282},"Entity-bound actions",{"type":62,"value":8284},": Include the entity set and record ID in the URL path, followed by ",{"type":49,"tag":67,"props":8286,"children":8288},{"className":8287},[],[8289],{"type":62,"value":8290},"Microsoft.Dynamics.CRM.\u003Caction-name>",{"type":49,"tag":98,"props":8292,"children":8293},{},[8294,8299,8300,8306],{"type":49,"tag":58,"props":8295,"children":8296},{},[8297],{"type":62,"value":8298},"Functions (GET)",{"type":62,"value":3421},{"type":49,"tag":67,"props":8301,"children":8303},{"className":8302},[],[8304],{"type":62,"value":8305},"\"GET\"",{"type":62,"value":8307}," as the HTTP method and pass parameters inline in the URL using OData function call syntax",{"type":49,"tag":98,"props":8309,"children":8310},{},[8311,8316,8317,8323],{"type":49,"tag":58,"props":8312,"children":8313},{},[8314],{"type":62,"value":8315},"Actions (POST)",{"type":62,"value":3421},{"type":49,"tag":67,"props":8318,"children":8320},{"className":8319},[],[8321],{"type":62,"value":8322},"\"POST\"",{"type":62,"value":8324}," as the HTTP method and pass parameters as JSON body payload",{"type":49,"tag":98,"props":8326,"children":8327},{},[8328,8333,8335,8339,8340,8345,8346],{"type":49,"tag":67,"props":8329,"children":8331},{"className":8330},[],[8332],{"type":62,"value":1805},{"type":62,"value":8334}," is ",{"type":49,"tag":58,"props":8336,"children":8337},{},[8338],{"type":62,"value":3569},{"type":62,"value":3571},{"type":49,"tag":67,"props":8341,"children":8343},{"className":8342},[],[8344],{"type":62,"value":3546},{"type":62,"value":876},{"type":49,"tag":67,"props":8347,"children":8349},{"className":8348},[],[8350],{"type":62,"value":3554},{"type":49,"tag":98,"props":8352,"children":8353},{},[8354],{"type":62,"value":8355},"The server logic can add additional validation, transformation, or logging around the custom action call — it doesn't have to be a pass-through",{"type":49,"tag":98,"props":8357,"children":8358},{},[8359],{"type":62,"value":8360},"When Custom API response properties are known (from Phase 2.1.2), map them to the response object for clarity",{"type":49,"tag":3362,"props":8362,"children":8364},{"id":8363},"dataverse-response-shape-critical-for-frontend-integration",[8365],{"type":62,"value":8366},"Dataverse Response Shape (Critical for Frontend Integration)",{"type":49,"tag":54,"props":8368,"children":8369},{},[8370,8372,8377,8379,8384,8386,8391,8393,8399,8401,8406,8408,8413,8415,8420],{"type":62,"value":8371},"When a function returns the result of a ",{"type":49,"tag":67,"props":8373,"children":8375},{"className":8374},[],[8376],{"type":62,"value":3562},{"type":62,"value":8378}," method, the client sees a double-wrapped payload — the most common cause of broken frontend integrations. Before writing the function, pick one of three response shapes and record the choice for Phase 9: ",{"type":49,"tag":58,"props":8380,"children":8381},{},[8382],{"type":62,"value":8383},"Approach A — raw passthrough",{"type":62,"value":8385}," (return the connector result as-is), ",{"type":49,"tag":58,"props":8387,"children":8388},{},[8389],{"type":62,"value":8390},"Approach B — envelope that wraps the connector result",{"type":62,"value":8392}," (return ",{"type":49,"tag":67,"props":8394,"children":8396},{"className":8395},[],[8397],{"type":62,"value":8398},"{ status, data: result }",{"type":62,"value":8400}," without unwrapping ",{"type":49,"tag":67,"props":8402,"children":8404},{"className":8403},[],[8405],{"type":62,"value":4639},{"type":62,"value":8407},"), or ",{"type":49,"tag":58,"props":8409,"children":8410},{},[8411],{"type":62,"value":8412},"Approach C — fully normalized",{"type":62,"value":8414}," (parse ",{"type":49,"tag":67,"props":8416,"children":8418},{"className":8417},[],[8419],{"type":62,"value":4639},{"type":62,"value":8421}," server-side and return a feature-specific shape — recommended for non-generic endpoints).",{"type":49,"tag":54,"props":8423,"children":8424},{},[8425,8427,8433,8435,8441,8442,8448],{"type":62,"value":8426},"See ",{"type":49,"tag":67,"props":8428,"children":8430},{"className":8429},[],[8431],{"type":62,"value":8432},"${PLUGIN_ROOT}\u002Fskills\u002Fadd-server-logic\u002Freferences\u002Ffrontend-integration-reference.md",{"type":62,"value":8434}," → \"Dataverse Connector Response Format\" for the double-wrapping explanation, the ",{"type":49,"tag":67,"props":8436,"children":8438},{"className":8437},[],[8439],{"type":62,"value":8440},"CreateRecord",{"type":62,"value":2924},{"type":49,"tag":67,"props":8443,"children":8445},{"className":8444},[],[8446],{"type":62,"value":8447},"entityid",{"type":62,"value":8449}," header behavior, and server- and client-side examples for each shape.",{"type":49,"tag":3362,"props":8451,"children":8453},{"id":8452},"referencing-secrets-in-code",[8454],{"type":62,"value":8455},"Referencing Secrets in Code",{"type":49,"tag":54,"props":8457,"children":8458},{},[8459,8461,8466],{"type":62,"value":8460},"When the server logic needs a secret value identified in Phase 2.3, ",{"type":49,"tag":58,"props":8462,"children":8463},{},[8464],{"type":62,"value":8465},"never hardcode the value",{"type":62,"value":8467},". Instead, read it at runtime from a site setting backed by an environment variable:",{"type":49,"tag":1335,"props":8469,"children":8471},{"className":3722,"code":8470,"language":18,"meta":1340,"style":1340},"const apiKey = Server.Sitesetting.Get(\"ExternalApi\u002FExchangeRateApiKey\");\n",[8472],{"type":49,"tag":67,"props":8473,"children":8474},{"__ignoreMap":1340},[8475],{"type":49,"tag":1346,"props":8476,"children":8477},{"class":1348,"line":1349},[8478,8483,8488,8492,8496,8500,8505,8509,8514,8518,8522,8526,8530,8534],{"type":49,"tag":1346,"props":8479,"children":8480},{"style":3742},[8481],{"type":62,"value":8482},"const",{"type":49,"tag":1346,"props":8484,"children":8485},{"style":1365},[8486],{"type":62,"value":8487}," apiKey ",{"type":49,"tag":1346,"props":8489,"children":8490},{"style":1359},[8491],{"type":62,"value":3755},{"type":49,"tag":1346,"props":8493,"children":8494},{"style":1365},[8495],{"type":62,"value":4749},{"type":49,"tag":1346,"props":8497,"children":8498},{"style":1359},[8499],{"type":62,"value":523},{"type":49,"tag":1346,"props":8501,"children":8502},{"style":1365},[8503],{"type":62,"value":8504},"Sitesetting",{"type":49,"tag":1346,"props":8506,"children":8507},{"style":1359},[8508],{"type":62,"value":523},{"type":49,"tag":1346,"props":8510,"children":8511},{"style":3917},[8512],{"type":62,"value":8513},"Get",{"type":49,"tag":1346,"props":8515,"children":8516},{"style":1365},[8517],{"type":62,"value":3976},{"type":49,"tag":1346,"props":8519,"children":8520},{"style":1359},[8521],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8523,"children":8524},{"style":1376},[8525],{"type":62,"value":2184},{"type":49,"tag":1346,"props":8527,"children":8528},{"style":1359},[8529],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8531,"children":8532},{"style":1365},[8533],{"type":62,"value":1113},{"type":49,"tag":1346,"props":8535,"children":8536},{"style":1359},[8537],{"type":62,"value":3773},{"type":49,"tag":54,"props":8539,"children":8540},{},[8541],{"type":62,"value":8542},"Use the site setting name planned in Phase 2.3. The actual environment variable and site setting YAML will be created in Phase 7.",{"type":49,"tag":3362,"props":8544,"children":8546},{"id":8545},"sdk-usage-guidance",[8547],{"type":62,"value":8548},"SDK Usage Guidance",{"type":49,"tag":54,"props":8550,"children":8551},{},[8552,8553,8557],{"type":62,"value":2730},{"type":49,"tag":58,"props":8554,"children":8555},{},[8556],{"type":62,"value":2735},{"type":62,"value":8558}," duplicate Microsoft Learn SDK usage patterns inline in this skill. Use the documentation fetched in Phase 3 as the source of truth for connector methods, signatures, and supported patterns, then apply only the task-specific notes that were captured in the approved plan.",{"type":49,"tag":487,"props":8560,"children":8562},{"id":8561},"_54-create-the-metadata-yaml",[8563],{"type":62,"value":8564},"5.4 Create the Metadata YAML",{"type":49,"tag":54,"props":8566,"children":8567},{},[8568,8570,8575,8577,8595],{"type":62,"value":8569},"For each approved server logic item where the plan status is ",{"type":49,"tag":67,"props":8571,"children":8573},{"className":8572},[],[8574],{"type":62,"value":3128},{"type":62,"value":8576},", generate the metadata file with the deterministic writer script instead of hand-authoring the YAML. The script generates the UUID, writes the fields in the correct order, and returns the created file path as JSON. ",{"type":49,"tag":58,"props":8578,"children":8579},{},[8580,8582,8587,8588,8593],{"type":62,"value":8581},"Skip this step for ",{"type":49,"tag":67,"props":8583,"children":8585},{"className":8584},[],[8586],{"type":62,"value":3098},{"type":62,"value":2924},{"type":49,"tag":67,"props":8589,"children":8591},{"className":8590},[],[8592],{"type":62,"value":3083},{"type":62,"value":8594}," items",{"type":62,"value":8596}," — the YAML already exists and should be updated manually if needed.",{"type":49,"tag":1335,"props":8598,"children":8600},{"className":1337,"code":8599,"language":1339,"meta":1340,"style":1340},"node \"${PLUGIN_ROOT}\u002Fskills\u002Fadd-server-logic\u002Fscripts\u002Fcreate-serverlogic-metadata.js\" --projectRoot \"\u003CPROJECT_ROOT>\" --name \"\u003Cname>\" --displayName \"\u003Chuman-readable display name>\" --description \"\u003Cdescription of what this server logic does>\" --webRoleIds \"\u003Cuuid1,uuid2,uuid3>\"\n",[8601],{"type":49,"tag":67,"props":8602,"children":8603},{"__ignoreMap":1340},[8604],{"type":49,"tag":1346,"props":8605,"children":8606},{"class":1348,"line":1349},[8607,8611,8615,8619,8623,8628,8632,8637,8641,8646,8650,8655,8659,8664,8668,8673,8677,8682,8686,8691,8695,8700,8704,8709,8713,8718],{"type":49,"tag":1346,"props":8608,"children":8609},{"style":1353},[8610],{"type":62,"value":1356},{"type":49,"tag":1346,"props":8612,"children":8613},{"style":1359},[8614],{"type":62,"value":1362},{"type":49,"tag":1346,"props":8616,"children":8617},{"style":1365},[8618],{"type":62,"value":1368},{"type":49,"tag":1346,"props":8620,"children":8621},{"style":1359},[8622],{"type":62,"value":1373},{"type":49,"tag":1346,"props":8624,"children":8625},{"style":1376},[8626],{"type":62,"value":8627},"\u002Fskills\u002Fadd-server-logic\u002Fscripts\u002Fcreate-serverlogic-metadata.js",{"type":49,"tag":1346,"props":8629,"children":8630},{"style":1359},[8631],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8633,"children":8634},{"style":1376},[8635],{"type":62,"value":8636}," --projectRoot",{"type":49,"tag":1346,"props":8638,"children":8639},{"style":1359},[8640],{"type":62,"value":1389},{"type":49,"tag":1346,"props":8642,"children":8643},{"style":1376},[8644],{"type":62,"value":8645},"\u003CPROJECT_ROOT>",{"type":49,"tag":1346,"props":8647,"children":8648},{"style":1359},[8649],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8651,"children":8652},{"style":1376},[8653],{"type":62,"value":8654}," --name",{"type":49,"tag":1346,"props":8656,"children":8657},{"style":1359},[8658],{"type":62,"value":1389},{"type":49,"tag":1346,"props":8660,"children":8661},{"style":1376},[8662],{"type":62,"value":8663},"\u003Cname>",{"type":49,"tag":1346,"props":8665,"children":8666},{"style":1359},[8667],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8669,"children":8670},{"style":1376},[8671],{"type":62,"value":8672}," --displayName",{"type":49,"tag":1346,"props":8674,"children":8675},{"style":1359},[8676],{"type":62,"value":1389},{"type":49,"tag":1346,"props":8678,"children":8679},{"style":1376},[8680],{"type":62,"value":8681},"\u003Chuman-readable display name>",{"type":49,"tag":1346,"props":8683,"children":8684},{"style":1359},[8685],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8687,"children":8688},{"style":1376},[8689],{"type":62,"value":8690}," --description",{"type":49,"tag":1346,"props":8692,"children":8693},{"style":1359},[8694],{"type":62,"value":1389},{"type":49,"tag":1346,"props":8696,"children":8697},{"style":1376},[8698],{"type":62,"value":8699},"\u003Cdescription of what this server logic does>",{"type":49,"tag":1346,"props":8701,"children":8702},{"style":1359},[8703],{"type":62,"value":1384},{"type":49,"tag":1346,"props":8705,"children":8706},{"style":1376},[8707],{"type":62,"value":8708}," --webRoleIds",{"type":49,"tag":1346,"props":8710,"children":8711},{"style":1359},[8712],{"type":62,"value":1389},{"type":49,"tag":1346,"props":8714,"children":8715},{"style":1376},[8716],{"type":62,"value":8717},"\u003Cuuid1,uuid2,uuid3>",{"type":49,"tag":1346,"props":8719,"children":8720},{"style":1359},[8721],{"type":62,"value":1399},{"type":49,"tag":54,"props":8723,"children":8724},{},[8725,8727,8733],{"type":62,"value":8726},"The generated ",{"type":49,"tag":67,"props":8728,"children":8730},{"className":8729},[],[8731],{"type":62,"value":8732},"\u003CPROJECT_ROOT>\u002F.powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F\u003Cname>.serverlogic.yml",{"type":62,"value":8734}," file has this structure:",{"type":49,"tag":1335,"props":8736,"children":8738},{"className":3180,"code":8737,"language":3182,"meta":1340,"style":1340},"adx_serverlogic_adx_webrole:\n  - \u003Cweb-role-guid-1>\n  - \u003Cweb-role-guid-2>\n  - \u003Cweb-role-guid-3>\ndescription: \u003Cdescription of what this server logic does>\ndisplay_name: \u003Chuman-readable display name>\nid: \u003Cgenerated-uuid>\nname: \u003Cname>\n",[8739],{"type":49,"tag":67,"props":8740,"children":8741},{"__ignoreMap":1340},[8742,8755,8768,8780,8792,8808,8825,8841],{"type":49,"tag":1346,"props":8743,"children":8744},{"class":1348,"line":1349},[8745,8750],{"type":49,"tag":1346,"props":8746,"children":8747},{"style":3192},[8748],{"type":62,"value":8749},"adx_serverlogic_adx_webrole",{"type":49,"tag":1346,"props":8751,"children":8752},{"style":1359},[8753],{"type":62,"value":8754},":\n",{"type":49,"tag":1346,"props":8756,"children":8757},{"class":1348,"line":3208},[8758,8763],{"type":49,"tag":1346,"props":8759,"children":8760},{"style":1359},[8761],{"type":62,"value":8762},"  -",{"type":49,"tag":1346,"props":8764,"children":8765},{"style":1376},[8766],{"type":62,"value":8767}," \u003Cweb-role-guid-1>\n",{"type":49,"tag":1346,"props":8769,"children":8770},{"class":1348,"line":3226},[8771,8775],{"type":49,"tag":1346,"props":8772,"children":8773},{"style":1359},[8774],{"type":62,"value":8762},{"type":49,"tag":1346,"props":8776,"children":8777},{"style":1376},[8778],{"type":62,"value":8779}," \u003Cweb-role-guid-2>\n",{"type":49,"tag":1346,"props":8781,"children":8782},{"class":1348,"line":3243},[8783,8787],{"type":49,"tag":1346,"props":8784,"children":8785},{"style":1359},[8786],{"type":62,"value":8762},{"type":49,"tag":1346,"props":8788,"children":8789},{"style":1376},[8790],{"type":62,"value":8791}," \u003Cweb-role-guid-3>\n",{"type":49,"tag":1346,"props":8793,"children":8794},{"class":1348,"line":3261},[8795,8799,8803],{"type":49,"tag":1346,"props":8796,"children":8797},{"style":3192},[8798],{"type":62,"value":1465},{"type":49,"tag":1346,"props":8800,"children":8801},{"style":1359},[8802],{"type":62,"value":468},{"type":49,"tag":1346,"props":8804,"children":8805},{"style":1376},[8806],{"type":62,"value":8807}," \u003Cdescription of what this server logic does>\n",{"type":49,"tag":1346,"props":8809,"children":8810},{"class":1348,"line":3933},[8811,8816,8820],{"type":49,"tag":1346,"props":8812,"children":8813},{"style":3192},[8814],{"type":62,"value":8815},"display_name",{"type":49,"tag":1346,"props":8817,"children":8818},{"style":1359},[8819],{"type":62,"value":468},{"type":49,"tag":1346,"props":8821,"children":8822},{"style":1376},[8823],{"type":62,"value":8824}," \u003Chuman-readable display name>\n",{"type":49,"tag":1346,"props":8826,"children":8827},{"class":1348,"line":3947},[8828,8832,8836],{"type":49,"tag":1346,"props":8829,"children":8830},{"style":3192},[8831],{"type":62,"value":3249},{"type":49,"tag":1346,"props":8833,"children":8834},{"style":1359},[8835],{"type":62,"value":468},{"type":49,"tag":1346,"props":8837,"children":8838},{"style":1376},[8839],{"type":62,"value":8840}," \u003Cgenerated-uuid>\n",{"type":49,"tag":1346,"props":8842,"children":8843},{"class":1348,"line":4000},[8844,8848,8852],{"type":49,"tag":1346,"props":8845,"children":8846},{"style":3192},[8847],{"type":62,"value":1451},{"type":49,"tag":1346,"props":8849,"children":8850},{"style":1359},[8851],{"type":62,"value":468},{"type":49,"tag":1346,"props":8853,"children":8854},{"style":1376},[8855],{"type":62,"value":8856}," \u003Cname>\n",{"type":49,"tag":54,"props":8858,"children":8859},{},[8860],{"type":49,"tag":58,"props":8861,"children":8862},{},[8863],{"type":62,"value":8864},"Critical requirements:",{"type":49,"tag":94,"props":8866,"children":8867},{},[8868,8891,8904,8931,8944],{"type":49,"tag":98,"props":8869,"children":8870},{},[8871,8881,8883,8889],{"type":49,"tag":58,"props":8872,"children":8873},{},[8874,8879],{"type":49,"tag":67,"props":8875,"children":8877},{"className":8876},[],[8878],{"type":62,"value":3249},{"type":62,"value":8880}," field is mandatory",{"type":62,"value":8882}," — The script generates a new UUID (v4). PAC CLI crashes with ",{"type":49,"tag":67,"props":8884,"children":8886},{"className":8885},[],[8887],{"type":62,"value":8888},"Expected Guid for primary key 'id'",{"type":62,"value":8890}," if this is missing.",{"type":49,"tag":98,"props":8892,"children":8893},{},[8894,8902],{"type":49,"tag":58,"props":8895,"children":8896},{},[8897],{"type":49,"tag":67,"props":8898,"children":8900},{"className":8899},[],[8901],{"type":62,"value":8749},{"type":62,"value":8903}," — Array of web role GUIDs from step 5.2. Include only the roles required for that server logic item.",{"type":49,"tag":98,"props":8905,"children":8906},{},[8907,8915,8917,8922,8924,8929],{"type":49,"tag":58,"props":8908,"children":8909},{},[8910],{"type":49,"tag":67,"props":8911,"children":8913},{"className":8912},[],[8914],{"type":62,"value":1451},{"type":62,"value":8916}," — Must match the folder name and ",{"type":49,"tag":67,"props":8918,"children":8920},{"className":8919},[],[8921],{"type":62,"value":349},{"type":62,"value":8923}," file name (the URL-friendly name used in ",{"type":49,"tag":67,"props":8925,"children":8927},{"className":8926},[],[8928],{"type":62,"value":6082},{"type":62,"value":8930},").",{"type":49,"tag":98,"props":8932,"children":8933},{},[8934,8942],{"type":49,"tag":58,"props":8935,"children":8936},{},[8937],{"type":49,"tag":67,"props":8938,"children":8940},{"className":8939},[],[8941],{"type":62,"value":8815},{"type":62,"value":8943}," — Human-readable name (e.g., \"Exchange Rate API\", \"Order Processor\").",{"type":49,"tag":98,"props":8945,"children":8946},{},[8947,8952,8954,8959,8960,8965,8966,8971,8972,8977,8978,8983],{"type":49,"tag":58,"props":8948,"children":8949},{},[8950],{"type":62,"value":8951},"Alphabetical field ordering",{"type":62,"value":8953}," — Fields must be sorted alphabetically: ",{"type":49,"tag":67,"props":8955,"children":8957},{"className":8956},[],[8958],{"type":62,"value":8749},{"type":62,"value":125},{"type":49,"tag":67,"props":8961,"children":8963},{"className":8962},[],[8964],{"type":62,"value":1465},{"type":62,"value":125},{"type":49,"tag":67,"props":8967,"children":8969},{"className":8968},[],[8970],{"type":62,"value":8815},{"type":62,"value":125},{"type":49,"tag":67,"props":8973,"children":8975},{"className":8974},[],[8976],{"type":62,"value":3249},{"type":62,"value":125},{"type":49,"tag":67,"props":8979,"children":8981},{"className":8980},[],[8982],{"type":62,"value":1451},{"type":62,"value":523},{"type":49,"tag":487,"props":8985,"children":8987},{"id":8986},"_55-validate-the-code",[8988],{"type":62,"value":8989},"5.5 Validate the Code",{"type":49,"tag":54,"props":8991,"children":8992},{},[8993],{"type":62,"value":8994},"Before saving, verify the code against these constraints:",{"type":49,"tag":905,"props":8996,"children":8997},{},[8998,9014],{"type":49,"tag":909,"props":8999,"children":9000},{},[9001],{"type":49,"tag":913,"props":9002,"children":9003},{},[9004,9009],{"type":49,"tag":917,"props":9005,"children":9006},{},[9007],{"type":62,"value":9008},"Constraint",{"type":49,"tag":917,"props":9010,"children":9011},{},[9012],{"type":62,"value":9013},"Check",{"type":49,"tag":928,"props":9015,"children":9016},{},[9017,9030,9043,9056,9069,9100,9148,9173],{"type":49,"tag":913,"props":9018,"children":9019},{},[9020,9025],{"type":49,"tag":935,"props":9021,"children":9022},{},[9023],{"type":62,"value":9024},"Only allowed top-level functions",{"type":49,"tag":935,"props":9026,"children":9027},{},[9028],{"type":62,"value":9029},"No functions other than get, post, put, patch, del",{"type":49,"tag":913,"props":9031,"children":9032},{},[9033,9038],{"type":49,"tag":935,"props":9034,"children":9035},{},[9036],{"type":62,"value":9037},"Every function returns a string",{"type":49,"tag":935,"props":9039,"children":9040},{},[9041],{"type":62,"value":9042},"All code paths return a string (including catch blocks)",{"type":49,"tag":913,"props":9044,"children":9045},{},[9046,9051],{"type":49,"tag":935,"props":9047,"children":9048},{},[9049],{"type":62,"value":9050},"try\u002Fcatch in every function",{"type":49,"tag":935,"props":9052,"children":9053},{},[9054],{"type":62,"value":9055},"Every function body is wrapped in try\u002Fcatch",{"type":49,"tag":913,"props":9057,"children":9058},{},[9059,9064],{"type":49,"tag":935,"props":9060,"children":9061},{},[9062],{"type":62,"value":9063},"Server.Logger in every function",{"type":49,"tag":935,"props":9065,"children":9066},{},[9067],{"type":62,"value":9068},"Log at entry, Error in catch",{"type":49,"tag":913,"props":9070,"children":9071},{},[9072,9077],{"type":49,"tag":935,"props":9073,"children":9074},{},[9075],{"type":62,"value":9076},"No external dependencies",{"type":49,"tag":935,"props":9078,"children":9079},{},[9080,9082,9087,9088,9093,9094],{"type":62,"value":9081},"No ",{"type":49,"tag":67,"props":9083,"children":9085},{"className":9084},[],[9086],{"type":62,"value":3479},{"type":62,"value":125},{"type":49,"tag":67,"props":9089,"children":9091},{"className":9090},[],[9092],{"type":62,"value":3486},{"type":62,"value":125},{"type":49,"tag":67,"props":9095,"children":9097},{"className":9096},[],[9098],{"type":62,"value":9099},"module.exports",{"type":49,"tag":913,"props":9101,"children":9102},{},[9103,9107],{"type":49,"tag":935,"props":9104,"children":9105},{},[9106],{"type":62,"value":3496},{"type":49,"tag":935,"props":9108,"children":9109},{},[9110,9111,9116,9117,9122,9123,9128,9129,9134,9135,9141,9142],{"type":62,"value":9081},{"type":49,"tag":67,"props":9112,"children":9114},{"className":9113},[],[9115],{"type":62,"value":123},{"type":62,"value":125},{"type":49,"tag":67,"props":9118,"children":9120},{"className":9119},[],[9121],{"type":62,"value":131},{"type":62,"value":125},{"type":49,"tag":67,"props":9124,"children":9126},{"className":9125},[],[9127],{"type":62,"value":138},{"type":62,"value":125},{"type":49,"tag":67,"props":9130,"children":9132},{"className":9131},[],[9133],{"type":62,"value":3528},{"type":62,"value":125},{"type":49,"tag":67,"props":9136,"children":9138},{"className":9137},[],[9139],{"type":62,"value":9140},"document",{"type":62,"value":125},{"type":49,"tag":67,"props":9143,"children":9145},{"className":9144},[],[9146],{"type":62,"value":9147},"window",{"type":49,"tag":913,"props":9149,"children":9150},{},[9151,9156],{"type":49,"tag":935,"props":9152,"children":9153},{},[9154],{"type":62,"value":9155},"Async only when needed",{"type":49,"tag":935,"props":9157,"children":9158},{},[9159,9161,9166,9168],{"type":62,"value":9160},"Only functions using ",{"type":49,"tag":67,"props":9162,"children":9164},{"className":9163},[],[9165],{"type":62,"value":3554},{"type":62,"value":9167}," are marked ",{"type":49,"tag":67,"props":9169,"children":9171},{"className":9170},[],[9172],{"type":62,"value":3546},{"type":49,"tag":913,"props":9174,"children":9175},{},[9176,9181],{"type":49,"tag":935,"props":9177,"children":9178},{},[9179],{"type":62,"value":9180},"ECMAScript 2023 compliant",{"type":49,"tag":935,"props":9182,"children":9183},{},[9184],{"type":62,"value":9185},"Standard JS features only (optional chaining, nullish coalescing, etc. are fine)",{"type":49,"tag":487,"props":9187,"children":9189},{"id":9188},"_56-git-commit",[9190],{"type":62,"value":9191},"5.6 Git Commit",{"type":49,"tag":54,"props":9193,"children":9194},{},[9195],{"type":62,"value":9196},"After creating the approved server logic files, do a git commit for the server logic changes.",{"type":49,"tag":54,"props":9198,"children":9199},{},[9200],{"type":62,"value":9201},"If the HTML plan was generated inside the project, include it in the same commit (use the actual output path from the render script's JSON response).",{"type":49,"tag":54,"props":9203,"children":9204},{},[9205,9209,9211,9216,9217,9222],{"type":49,"tag":58,"props":9206,"children":9207},{},[9208],{"type":62,"value":993},{"type":62,"value":9210},": Server logic ",{"type":49,"tag":67,"props":9212,"children":9214},{"className":9213},[],[9215],{"type":62,"value":349},{"type":62,"value":351},{"type":49,"tag":67,"props":9218,"children":9220},{"className":9219},[],[9221],{"type":62,"value":357},{"type":62,"value":9223}," files created, validated, and committed",{"type":49,"tag":281,"props":9225,"children":9226},{},[],{"type":49,"tag":87,"props":9228,"children":9230},{"id":9229},"phase-6-configure-table-permissions-conditional",[9231],{"type":62,"value":9232},"Phase 6: Configure Table Permissions (Conditional)",{"type":49,"tag":54,"props":9234,"children":9235},{},[9236,9240,9242,9247],{"type":49,"tag":58,"props":9237,"children":9238},{},[9239],{"type":62,"value":456},{"type":62,"value":9241},": Set up table permissions for Dataverse tables accessed by ",{"type":49,"tag":67,"props":9243,"children":9245},{"className":9244},[],[9246],{"type":62,"value":1904},{"type":62,"value":9248}," in the server logic code",{"type":49,"tag":54,"props":9250,"children":9251},{},[9252,9263,9265,9270],{"type":49,"tag":58,"props":9253,"children":9254},{},[9255,9257,9262],{"type":62,"value":9256},"This phase only runs when the server logic uses ",{"type":49,"tag":67,"props":9258,"children":9260},{"className":9259},[],[9261],{"type":62,"value":1904},{"type":62,"value":523},{"type":62,"value":9264}," If the server logic only uses ",{"type":49,"tag":67,"props":9266,"children":9268},{"className":9267},[],[9269],{"type":62,"value":1887},{"type":62,"value":9271}," (external APIs) or doesn't access Dataverse at all, skip this phase entirely and proceed to Phase 7.",{"type":49,"tag":54,"props":9273,"children":9274},{},[9275,9280,9282,9287],{"type":49,"tag":67,"props":9276,"children":9278},{"className":9277},[],[9279],{"type":62,"value":1904},{"type":62,"value":9281}," does ",{"type":49,"tag":58,"props":9283,"children":9284},{},[9285],{"type":62,"value":9286},"NOT",{"type":62,"value":9288}," bypass table permissions — it respects them. Without table permissions configured, the Dataverse connector silently returns 0 records instead of the actual data. This is a common source of confusion.",{"type":49,"tag":54,"props":9290,"children":9291},{},[9292,9296],{"type":49,"tag":58,"props":9293,"children":9294},{},[9295],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":9298,"children":9300},{"id":9299},"_61-detect-dataverse-tables-and-required-privileges",[9301],{"type":62,"value":9302},"6.1 Detect Dataverse Tables and Required Privileges",{"type":49,"tag":54,"props":9304,"children":9305},{},[9306,9308,9313],{"type":62,"value":9307},"Parse the server logic ",{"type":49,"tag":67,"props":9309,"children":9311},{"className":9310},[],[9312],{"type":62,"value":349},{"type":62,"value":9314}," file created in Phase 5 to identify which Dataverse tables are accessed and what CRUD operations are performed:",{"type":49,"tag":905,"props":9316,"children":9317},{},[9318,9334],{"type":49,"tag":909,"props":9319,"children":9320},{},[9321],{"type":49,"tag":913,"props":9322,"children":9323},{},[9324,9329],{"type":49,"tag":917,"props":9325,"children":9326},{},[9327],{"type":62,"value":9328},"Dataverse SDK Method",{"type":49,"tag":917,"props":9330,"children":9331},{},[9332],{"type":62,"value":9333},"Required Table Permission",{"type":49,"tag":928,"props":9335,"children":9336},{},[9337,9354,9370,9387,9404],{"type":49,"tag":913,"props":9338,"children":9339},{},[9340,9349],{"type":49,"tag":935,"props":9341,"children":9342},{},[9343],{"type":49,"tag":67,"props":9344,"children":9346},{"className":9345},[],[9347],{"type":62,"value":9348},"RetrieveMultipleRecords(\"tablename\", ...)",{"type":49,"tag":935,"props":9350,"children":9351},{},[9352],{"type":62,"value":9353},"Read",{"type":49,"tag":913,"props":9355,"children":9356},{},[9357,9366],{"type":49,"tag":935,"props":9358,"children":9359},{},[9360],{"type":49,"tag":67,"props":9361,"children":9363},{"className":9362},[],[9364],{"type":62,"value":9365},"RetrieveRecord(\"tablename\", ...)",{"type":49,"tag":935,"props":9367,"children":9368},{},[9369],{"type":62,"value":9353},{"type":49,"tag":913,"props":9371,"children":9372},{},[9373,9382],{"type":49,"tag":935,"props":9374,"children":9375},{},[9376],{"type":49,"tag":67,"props":9377,"children":9379},{"className":9378},[],[9380],{"type":62,"value":9381},"CreateRecord(\"tablename\", ...)",{"type":49,"tag":935,"props":9383,"children":9384},{},[9385],{"type":62,"value":9386},"Create",{"type":49,"tag":913,"props":9388,"children":9389},{},[9390,9399],{"type":49,"tag":935,"props":9391,"children":9392},{},[9393],{"type":49,"tag":67,"props":9394,"children":9396},{"className":9395},[],[9397],{"type":62,"value":9398},"UpdateRecord(\"tablename\", ...)",{"type":49,"tag":935,"props":9400,"children":9401},{},[9402],{"type":62,"value":9403},"Write",{"type":49,"tag":913,"props":9405,"children":9406},{},[9407,9416],{"type":49,"tag":935,"props":9408,"children":9409},{},[9410],{"type":49,"tag":67,"props":9411,"children":9413},{"className":9412},[],[9414],{"type":62,"value":9415},"DeleteRecord(\"tablename\", ...)",{"type":49,"tag":935,"props":9417,"children":9418},{},[9419],{"type":62,"value":9420},"Delete",{"type":49,"tag":54,"props":9422,"children":9423},{},[9424],{"type":62,"value":9425},"Extract the entity set name (first argument) from each method call. Build a mapping:",{"type":49,"tag":905,"props":9427,"children":9428},{},[9429,9457],{"type":49,"tag":909,"props":9430,"children":9431},{},[9432],{"type":49,"tag":913,"props":9433,"children":9434},{},[9435,9440,9445,9449,9453],{"type":49,"tag":917,"props":9436,"children":9437},{},[9438],{"type":62,"value":9439},"Table (entity set name)",{"type":49,"tag":917,"props":9441,"children":9443},{"align":9442},"center",[9444],{"type":62,"value":9353},{"type":49,"tag":917,"props":9446,"children":9447},{"align":9442},[9448],{"type":62,"value":9386},{"type":49,"tag":917,"props":9450,"children":9451},{"align":9442},[9452],{"type":62,"value":9403},{"type":49,"tag":917,"props":9454,"children":9455},{"align":9442},[9456],{"type":62,"value":9420},{"type":49,"tag":928,"props":9458,"children":9459},{},[9460,9489],{"type":49,"tag":913,"props":9461,"children":9462},{},[9463,9472,9476,9481,9485],{"type":49,"tag":935,"props":9464,"children":9465},{},[9466],{"type":49,"tag":67,"props":9467,"children":9469},{"className":9468},[],[9470],{"type":62,"value":9471},"accounts",{"type":49,"tag":935,"props":9473,"children":9474},{"align":9442},[9475],{"type":62,"value":1724},{"type":49,"tag":935,"props":9477,"children":9478},{"align":9442},[9479],{"type":62,"value":9480},"—",{"type":49,"tag":935,"props":9482,"children":9483},{"align":9442},[9484],{"type":62,"value":9480},{"type":49,"tag":935,"props":9486,"children":9487},{"align":9442},[9488],{"type":62,"value":9480},{"type":49,"tag":913,"props":9490,"children":9491},{},[9492,9501,9505,9509,9513],{"type":49,"tag":935,"props":9493,"children":9494},{},[9495],{"type":49,"tag":67,"props":9496,"children":9498},{"className":9497},[],[9499],{"type":62,"value":9500},"contacts",{"type":49,"tag":935,"props":9502,"children":9503},{"align":9442},[9504],{"type":62,"value":1724},{"type":49,"tag":935,"props":9506,"children":9507},{"align":9442},[9508],{"type":62,"value":1724},{"type":49,"tag":935,"props":9510,"children":9511},{"align":9442},[9512],{"type":62,"value":9480},{"type":49,"tag":935,"props":9514,"children":9515},{"align":9442},[9516],{"type":62,"value":9480},{"type":49,"tag":487,"props":9518,"children":9520},{"id":9519},"_62-use-the-table-permissions-architect",[9521],{"type":62,"value":9522},"6.2 Use the Table Permissions Architect",{"type":49,"tag":54,"props":9524,"children":9525},{},[9526,9528,9533,9535,9541,9543,9549],{"type":62,"value":9527},"When any approved server logic item uses ",{"type":49,"tag":67,"props":9529,"children":9531},{"className":9530},[],[9532],{"type":62,"value":1904},{"type":62,"value":9534},", invoke the ",{"type":49,"tag":67,"props":9536,"children":9538},{"className":9537},[],[9539],{"type":62,"value":9540},"table-permissions-architect",{"type":62,"value":9542}," agent at ",{"type":49,"tag":67,"props":9544,"children":9546},{"className":9545},[],[9547],{"type":62,"value":9548},"${PLUGIN_ROOT}\u002Fagents\u002Ftable-permissions-architect.md",{"type":62,"value":9550}," to determine and create the required table permissions.",{"type":49,"tag":54,"props":9552,"children":9553},{},[9554],{"type":49,"tag":58,"props":9555,"children":9556},{},[9557],{"type":62,"value":9558},"Prompt:",{"type":49,"tag":50,"props":9560,"children":9561},{},[9562,9567,9575,9580,9634],{"type":49,"tag":54,"props":9563,"children":9564},{},[9565],{"type":62,"value":9566},"\"Analyze this Power Pages code site and propose table permissions for Dataverse tables accessed by the approved server logic plan. The following tables need permissions:",{"type":49,"tag":54,"props":9568,"children":9569},{},[9570],{"type":49,"tag":1346,"props":9571,"children":9572},{},[9573],{"type":62,"value":9574},"list each table with required CRUD privileges from step 6.1, grouped by server logic item",{"type":49,"tag":54,"props":9576,"children":9577},{},[9578],{"type":62,"value":9579},"Context:",{"type":49,"tag":94,"props":9581,"children":9582},{},[9583,9595,9614,9624],{"type":49,"tag":98,"props":9584,"children":9585},{},[9586,9588,9593],{"type":62,"value":9587},"These permissions are needed because the server logic uses ",{"type":49,"tag":67,"props":9589,"children":9591},{"className":9590},[],[9592],{"type":62,"value":1904},{"type":62,"value":9594},", which respects table permissions — without them, the connector silently returns 0 records.",{"type":49,"tag":98,"props":9596,"children":9597},{},[9598,9600,9605,9607,9612],{"type":62,"value":9599},"The scope should typically be ",{"type":49,"tag":58,"props":9601,"children":9602},{},[9603],{"type":62,"value":9604},"Global",{"type":62,"value":9606}," for server logic that fetches all records, unless the server logic filters by the current user (in which case use ",{"type":49,"tag":58,"props":9608,"children":9609},{},[9610],{"type":62,"value":9611},"Contact",{"type":62,"value":9613}," scope).",{"type":49,"tag":98,"props":9615,"children":9616},{},[9617,9619],{"type":62,"value":9618},"The web roles assigned to these server logic items are: ",{"type":49,"tag":1346,"props":9620,"children":9621},{},[9622],{"type":62,"value":9623},"list web role names and GUIDs from Phase 5.2",{"type":49,"tag":98,"props":9625,"children":9626},{},[9627,9629],{"type":62,"value":9628},"Project root: ",{"type":49,"tag":1346,"props":9630,"children":9631},{},[9632],{"type":62,"value":9633},"path",{"type":49,"tag":54,"props":9635,"children":9636},{},[9637],{"type":62,"value":9638},"Check for existing table permissions and web roles. If new web roles are needed, create them using the create-web-role.js script. Propose a plan, then after approval create the table permission YAML files using the deterministic scripts.\"",{"type":49,"tag":54,"props":9640,"children":9641},{},[9642],{"type":62,"value":9643},"The agent will:",{"type":49,"tag":291,"props":9645,"children":9646},{},[9647,9652,9665,9670,9675],{"type":49,"tag":98,"props":9648,"children":9649},{},[9650],{"type":62,"value":9651},"Discover existing table permissions and web roles",{"type":49,"tag":98,"props":9653,"children":9654},{},[9655,9657,9663],{"type":62,"value":9656},"Create any missing web roles via ",{"type":49,"tag":67,"props":9658,"children":9660},{"className":9659},[],[9661],{"type":62,"value":9662},"create-web-role.js",{"type":62,"value":9664}," if needed",{"type":49,"tag":98,"props":9666,"children":9667},{},[9668],{"type":62,"value":9669},"Propose a table permissions plan (with HTML visualization)",{"type":49,"tag":98,"props":9671,"children":9672},{},[9673],{"type":62,"value":9674},"Present the plan via plan mode for user approval",{"type":49,"tag":98,"props":9676,"children":9677},{},[9678,9680,9686,9688],{"type":62,"value":9679},"After approval, create table permission YAML files in ",{"type":49,"tag":67,"props":9681,"children":9683},{"className":9682},[],[9684],{"type":62,"value":9685},".powerpages-site\u002Ftable-permissions\u002F",{"type":62,"value":9687}," using ",{"type":49,"tag":67,"props":9689,"children":9691},{"className":9690},[],[9692],{"type":62,"value":9693},"create-table-permission.js",{"type":49,"tag":487,"props":9695,"children":9697},{"id":9696},"_63-git-commit",[9698],{"type":62,"value":9699},"6.3 Git Commit",{"type":49,"tag":54,"props":9701,"children":9702},{},[9703],{"type":62,"value":9704},"After table permissions (and any new web roles) are created, do a git commit for the table permissions changes.",{"type":49,"tag":54,"props":9706,"children":9707},{},[9708,9712],{"type":49,"tag":58,"props":9709,"children":9710},{},[9711],{"type":62,"value":993},{"type":62,"value":9713},": Table permissions (and web roles if created) configured for all Dataverse tables accessed by the server logic",{"type":49,"tag":281,"props":9715,"children":9716},{},[],{"type":49,"tag":87,"props":9718,"children":9720},{"id":9719},"phase-7-manage-secrets-environment-variables",[9721],{"type":62,"value":9722},"Phase 7: Manage Secrets & Environment Variables",{"type":49,"tag":54,"props":9724,"children":9725},{},[9726,9730],{"type":49,"tag":58,"props":9727,"children":9728},{},[9729],{"type":62,"value":456},{"type":62,"value":9731},": Securely store any secret values (API keys, client secrets, connection strings) required by the server logic as environment variables in Dataverse, optionally backed by Azure Key Vault",{"type":49,"tag":54,"props":9733,"children":9734},{},[9735,9740],{"type":49,"tag":58,"props":9736,"children":9737},{},[9738],{"type":62,"value":9739},"This phase only runs when the server logic requires secret or sensitive configuration values",{"type":62,"value":9741}," (identified in Phase 2.3). If no secrets are needed, skip this phase and proceed to Phase 8.",{"type":49,"tag":54,"props":9743,"children":9744},{},[9745,9749],{"type":49,"tag":58,"props":9746,"children":9747},{},[9748],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":9751,"children":9753},{"id":9752},"_71-recall-key-vault-decision",[9754],{"type":62,"value":9755},"7.1 Recall Key Vault Decision",{"type":49,"tag":54,"props":9757,"children":9758},{},[9759,9761,9765],{"type":62,"value":9760},"The user already chose whether to use Azure Key Vault in Phase 2.3.1 (before the plan was presented). Use that decision here — do ",{"type":49,"tag":58,"props":9762,"children":9763},{},[9764],{"type":62,"value":2735},{"type":62,"value":9766}," re-ask.",{"type":49,"tag":487,"props":9768,"children":9770},{"id":9769},"_72a-azure-key-vault-path",[9771],{"type":62,"value":9772},"7.2a Azure Key Vault Path",{"type":49,"tag":54,"props":9774,"children":9775},{},[9776],{"type":62,"value":9777},"If the user chose Azure Key Vault in Phase 2.3.1:",{"type":49,"tag":54,"props":9779,"children":9780},{},[9781],{"type":49,"tag":58,"props":9782,"children":9783},{},[9784],{"type":62,"value":9785},"Step 1 — List available Key Vaults:",{"type":49,"tag":1335,"props":9787,"children":9789},{"className":1337,"code":9788,"language":1339,"meta":1340,"style":1340},"node \"${PLUGIN_ROOT}\u002Fscripts\u002Flist-azure-keyvaults.js\"\n",[9790],{"type":49,"tag":67,"props":9791,"children":9792},{"__ignoreMap":1340},[9793],{"type":49,"tag":1346,"props":9794,"children":9795},{"class":1348,"line":1349},[9796,9800,9804,9808,9812,9817],{"type":49,"tag":1346,"props":9797,"children":9798},{"style":1353},[9799],{"type":62,"value":1356},{"type":49,"tag":1346,"props":9801,"children":9802},{"style":1359},[9803],{"type":62,"value":1362},{"type":49,"tag":1346,"props":9805,"children":9806},{"style":1365},[9807],{"type":62,"value":1368},{"type":49,"tag":1346,"props":9809,"children":9810},{"style":1359},[9811],{"type":62,"value":1373},{"type":49,"tag":1346,"props":9813,"children":9814},{"style":1376},[9815],{"type":62,"value":9816},"\u002Fscripts\u002Flist-azure-keyvaults.js",{"type":49,"tag":1346,"props":9818,"children":9819},{"style":1359},[9820],{"type":62,"value":1399},{"type":49,"tag":54,"props":9822,"children":9823},{},[9824,9826,9831,9832,9838,9839,9845],{"type":62,"value":9825},"The script outputs a JSON array of Key Vaults (",{"type":49,"tag":67,"props":9827,"children":9829},{"className":9828},[],[9830],{"type":62,"value":1451},{"type":62,"value":125},{"type":49,"tag":67,"props":9833,"children":9835},{"className":9834},[],[9836],{"type":62,"value":9837},"resourceGroup",{"type":62,"value":125},{"type":49,"tag":67,"props":9840,"children":9842},{"className":9841},[],[9843],{"type":62,"value":9844},"location",{"type":62,"value":9846},") from the user's Azure subscription.",{"type":49,"tag":54,"props":9848,"children":9849},{},[9850],{"type":49,"tag":58,"props":9851,"children":9852},{},[9853],{"type":62,"value":9854},"Step 2 — Select or create a Key Vault:",{"type":49,"tag":54,"props":9856,"children":9857},{},[9858],{"type":62,"value":9859},"If Key Vaults were found, present the list and ask which one to use:",{"type":49,"tag":54,"props":9861,"children":9862},{},[9863,9864,9869],{"type":62,"value":896},{"type":49,"tag":67,"props":9865,"children":9867},{"className":9866},[],[9868],{"type":62,"value":902},{"type":62,"value":468},{"type":49,"tag":905,"props":9871,"children":9872},{},[9873,9887],{"type":49,"tag":909,"props":9874,"children":9875},{},[9876],{"type":49,"tag":913,"props":9877,"children":9878},{},[9879,9883],{"type":49,"tag":917,"props":9880,"children":9881},{},[9882],{"type":62,"value":921},{"type":49,"tag":917,"props":9884,"children":9885},{},[9886],{"type":62,"value":1755},{"type":49,"tag":928,"props":9888,"children":9889},{},[9890],{"type":49,"tag":913,"props":9891,"children":9892},{},[9893,9898],{"type":49,"tag":935,"props":9894,"children":9895},{},[9896],{"type":62,"value":9897},"Which Azure Key Vault would you like to use for storing secrets?",{"type":49,"tag":935,"props":9899,"children":9900},{},[9901],{"type":62,"value":9902},"Present the names from the script output",{"type":49,"tag":54,"props":9904,"children":9905},{},[9906,9908,9913],{"type":62,"value":9907},"If ",{"type":49,"tag":58,"props":9909,"children":9910},{},[9911],{"type":62,"value":9912},"no Key Vaults are found",{"type":62,"value":9914},", ask the user how to proceed:",{"type":49,"tag":50,"props":9916,"children":9917},{},[9918,9929],{"type":49,"tag":54,"props":9919,"children":9920},{},[9921,9922,9927],{"type":62,"value":831},{"type":49,"tag":58,"props":9923,"children":9924},{},[9925],{"type":62,"value":9926},"Gate (plan · add-server-logic:7.2a.no-vaults):",{"type":62,"value":9928}," No Key Vaults found in the user's subscription — create one or fall back to plain env vars. Branches the secret-storage flow.",{"type":49,"tag":54,"props":9930,"children":9931},{},[9932,9936,9938,9944,9946,9950,9952,9956],{"type":49,"tag":58,"props":9933,"children":9934},{},[9935],{"type":62,"value":853},{"type":62,"value":9937}," Phase 2.3.1 chose Key Vault but ",{"type":49,"tag":67,"props":9939,"children":9941},{"className":9940},[],[9942],{"type":62,"value":9943},"list-azure-keyvaults.js",{"type":62,"value":9945}," returned an empty list.\n",{"type":49,"tag":58,"props":9947,"children":9948},{},[9949],{"type":62,"value":867},{"type":62,"value":9951}," Auto-creating a Key Vault provisions Azure resources without explicit consent; auto-falling-back stores secrets as plain env vars after the user explicitly opted in to Key Vault.\n",{"type":49,"tag":58,"props":9953,"children":9954},{},[9955],{"type":62,"value":889},{"type":62,"value":9957}," Nothing — no Azure or Dataverse writes yet.",{"type":49,"tag":54,"props":9959,"children":9960},{},[9961,9962,9967],{"type":62,"value":896},{"type":49,"tag":67,"props":9963,"children":9965},{"className":9964},[],[9966],{"type":62,"value":902},{"type":62,"value":468},{"type":49,"tag":905,"props":9969,"children":9970},{},[9971,9985],{"type":49,"tag":909,"props":9972,"children":9973},{},[9974],{"type":49,"tag":913,"props":9975,"children":9976},{},[9977,9981],{"type":49,"tag":917,"props":9978,"children":9979},{},[9980],{"type":62,"value":921},{"type":49,"tag":917,"props":9982,"children":9983},{},[9984],{"type":62,"value":926},{"type":49,"tag":928,"props":9986,"children":9987},{},[9988],{"type":49,"tag":913,"props":9989,"children":9990},{},[9991,9996],{"type":49,"tag":935,"props":9992,"children":9993},{},[9994],{"type":62,"value":9995},"No Azure Key Vaults were found in your subscription. Would you like to create one, or fall back to storing secrets directly as environment variables?",{"type":49,"tag":935,"props":9997,"children":9998},{},[9999],{"type":62,"value":10000},"Create a new Key Vault (Recommended), Store directly as environment variable",{"type":49,"tag":54,"props":10002,"children":10003},{},[10004,10009],{"type":49,"tag":58,"props":10005,"children":10006},{},[10007],{"type":62,"value":10008},"If \"Create a new Key Vault\"",{"type":62,"value":10010},": Ask for a vault name, resource group, and location, then create it:",{"type":49,"tag":54,"props":10012,"children":10013},{},[10014,10015,10020],{"type":62,"value":896},{"type":49,"tag":67,"props":10016,"children":10018},{"className":10017},[],[10019],{"type":62,"value":902},{"type":62,"value":468},{"type":49,"tag":905,"props":10022,"children":10023},{},[10024,10038],{"type":49,"tag":909,"props":10025,"children":10026},{},[10027],{"type":49,"tag":913,"props":10028,"children":10029},{},[10030,10034],{"type":49,"tag":917,"props":10031,"children":10032},{},[10033],{"type":62,"value":921},{"type":49,"tag":917,"props":10035,"children":10036},{},[10037],{"type":62,"value":1755},{"type":49,"tag":928,"props":10039,"children":10040},{},[10041],{"type":49,"tag":913,"props":10042,"children":10043},{},[10044,10049],{"type":49,"tag":935,"props":10045,"children":10046},{},[10047],{"type":62,"value":10048},"What name, resource group, and Azure region would you like for the new Key Vault?",{"type":49,"tag":935,"props":10050,"children":10051},{},[10052],{"type":62,"value":10053},"Vault names must be 3-24 characters, globally unique, start with a letter, and contain only alphanumerics and hyphens. Suggest a name based on the project\u002Fsite name.",{"type":49,"tag":1335,"props":10055,"children":10057},{"className":1337,"code":10056,"language":1339,"meta":1340,"style":1340},"node \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-azure-keyvault.js\" \\\n  --name \"\u003Cvault-name>\" \\\n  --resourceGroup \"\u003Cresource-group>\" \\\n  --location \"\u003Clocation>\"\n",[10058],{"type":49,"tag":67,"props":10059,"children":10060},{"__ignoreMap":1340},[10061,10094,10119,10144],{"type":49,"tag":1346,"props":10062,"children":10063},{"class":1348,"line":1349},[10064,10068,10072,10076,10080,10085,10089],{"type":49,"tag":1346,"props":10065,"children":10066},{"style":1353},[10067],{"type":62,"value":1356},{"type":49,"tag":1346,"props":10069,"children":10070},{"style":1359},[10071],{"type":62,"value":1362},{"type":49,"tag":1346,"props":10073,"children":10074},{"style":1365},[10075],{"type":62,"value":1368},{"type":49,"tag":1346,"props":10077,"children":10078},{"style":1359},[10079],{"type":62,"value":1373},{"type":49,"tag":1346,"props":10081,"children":10082},{"style":1376},[10083],{"type":62,"value":10084},"\u002Fscripts\u002Fcreate-azure-keyvault.js",{"type":49,"tag":1346,"props":10086,"children":10087},{"style":1359},[10088],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10090,"children":10091},{"style":1365},[10092],{"type":62,"value":10093}," \\\n",{"type":49,"tag":1346,"props":10095,"children":10096},{"class":1348,"line":3208},[10097,10102,10106,10111,10115],{"type":49,"tag":1346,"props":10098,"children":10099},{"style":1376},[10100],{"type":62,"value":10101},"  --name",{"type":49,"tag":1346,"props":10103,"children":10104},{"style":1359},[10105],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10107,"children":10108},{"style":1376},[10109],{"type":62,"value":10110},"\u003Cvault-name>",{"type":49,"tag":1346,"props":10112,"children":10113},{"style":1359},[10114],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10116,"children":10117},{"style":1365},[10118],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10120,"children":10121},{"class":1348,"line":3226},[10122,10127,10131,10136,10140],{"type":49,"tag":1346,"props":10123,"children":10124},{"style":1376},[10125],{"type":62,"value":10126},"  --resourceGroup",{"type":49,"tag":1346,"props":10128,"children":10129},{"style":1359},[10130],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10132,"children":10133},{"style":1376},[10134],{"type":62,"value":10135},"\u003Cresource-group>",{"type":49,"tag":1346,"props":10137,"children":10138},{"style":1359},[10139],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10141,"children":10142},{"style":1365},[10143],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10145,"children":10146},{"class":1348,"line":3243},[10147,10152,10156,10161],{"type":49,"tag":1346,"props":10148,"children":10149},{"style":1376},[10150],{"type":62,"value":10151},"  --location",{"type":49,"tag":1346,"props":10153,"children":10154},{"style":1359},[10155],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10157,"children":10158},{"style":1376},[10159],{"type":62,"value":10160},"\u003Clocation>",{"type":49,"tag":1346,"props":10162,"children":10163},{"style":1359},[10164],{"type":62,"value":1399},{"type":49,"tag":54,"props":10166,"children":10167},{},[10168,10170,10175,10176,10181,10182,10187],{"type":62,"value":10169},"The script outputs a JSON object with ",{"type":49,"tag":67,"props":10171,"children":10173},{"className":10172},[],[10174],{"type":62,"value":1451},{"type":62,"value":125},{"type":49,"tag":67,"props":10177,"children":10179},{"className":10178},[],[10180],{"type":62,"value":9837},{"type":62,"value":1527},{"type":49,"tag":67,"props":10183,"children":10185},{"className":10184},[],[10186],{"type":62,"value":9844},{"type":62,"value":10188},". Use the created vault for the remaining steps.",{"type":49,"tag":54,"props":10190,"children":10191},{},[10192,10197],{"type":49,"tag":58,"props":10193,"children":10194},{},[10195],{"type":62,"value":10196},"If \"Store directly as environment variable\"",{"type":62,"value":10198},": Skip the rest of Phase 7.2a and proceed to Phase 7.2b (direct environment variable path).",{"type":49,"tag":54,"props":10200,"children":10201},{},[10202],{"type":49,"tag":58,"props":10203,"children":10204},{},[10205],{"type":62,"value":10206},"Step 3 — Provide instructions for storing each secret in Key Vault:",{"type":49,"tag":54,"props":10208,"children":10209},{},[10210,10212,10216],{"type":62,"value":10211},"For each secret identified in Phase 2.3, give the user instructions to store the value themselves. Do ",{"type":49,"tag":58,"props":10213,"children":10214},{},[10215],{"type":62,"value":2735},{"type":62,"value":10217}," ask for the secret value — secret values must never pass through the conversation.",{"type":49,"tag":54,"props":10219,"children":10220},{},[10221,10223,10228],{"type":62,"value":10222},"Present ",{"type":49,"tag":58,"props":10224,"children":10225},{},[10226],{"type":62,"value":10227},"both",{"type":62,"value":10229}," methods (CLI and Azure Portal) so the user can choose whichever they prefer:",{"type":49,"tag":54,"props":10231,"children":10232},{},[10233],{"type":49,"tag":58,"props":10234,"children":10235},{},[10236],{"type":62,"value":10237},"Option A — Azure CLI (recommended for automation):",{"type":49,"tag":54,"props":10239,"children":10240},{},[10241],{"type":62,"value":10242},"Present the commands as a numbered list the user can copy and run. Use the stdin form so the secret value does not appear in process listings:",{"type":49,"tag":1335,"props":10244,"children":10247},{"className":10245,"code":10246,"language":62},[2706],"For each secret, run the following command (replacing \u003CYOUR_SECRET_VALUE> with the actual value):\n\n1. \u003Csecret-name>:\n   printf '%s' '\u003CYOUR_SECRET_VALUE>' | node \"${PLUGIN_ROOT}\u002Fscripts\u002Fstore-keyvault-secret.js\" \\\n     --vaultName \"\u003Cselected-vault>\" \\\n     --secretName \"\u003Csecret-name>\"\n",[10248],{"type":49,"tag":67,"props":10249,"children":10250},{"__ignoreMap":1340},[10251],{"type":62,"value":10246},{"type":49,"tag":54,"props":10253,"children":10254},{},[10255,10257,10263],{"type":62,"value":10256},"Tell the user each command outputs a JSON object with a ",{"type":49,"tag":67,"props":10258,"children":10260},{"className":10259},[],[10261],{"type":62,"value":10262},"secretUri",{"type":62,"value":10264}," and to share the output (which contains only the URI, not the secret) so the workflow can continue.",{"type":49,"tag":54,"props":10266,"children":10267},{},[10268],{"type":49,"tag":58,"props":10269,"children":10270},{},[10271],{"type":62,"value":10272},"Option B — Azure Portal:",{"type":49,"tag":54,"props":10274,"children":10275},{},[10276],{"type":62,"value":10277},"Provide these steps for each secret:",{"type":49,"tag":1335,"props":10279,"children":10282},{"className":10280,"code":10281,"language":62},[2706],"1. Go to the Azure Portal (https:\u002F\u002Fportal.azure.com)\n2. Search for \"Key vaults\" in the top search bar and select it\n3. Select the Key Vault: \u003Cselected-vault>\n4. In the left menu under \"Objects\", click \"Secrets\"\n5. Click \"+ Generate\u002FImport\" at the top\n6. Fill in the fields:\n   - Upload options: Manual\n   - Name: \u003Csecret-name>\n   - Secret value: paste your secret value here\n   - Leave other fields as defaults\n7. Click \"Create\"\n8. After creation, click on the secret name, then click the current version\n9. Copy the \"Secret Identifier\" URI and share it here so the workflow can continue\n",[10283],{"type":49,"tag":67,"props":10284,"children":10285},{"__ignoreMap":1340},[10286],{"type":62,"value":10281},{"type":49,"tag":54,"props":10288,"children":10289},{},[10290,10292,10298],{"type":62,"value":10291},"Tell the user the Secret Identifier URI looks like ",{"type":49,"tag":67,"props":10293,"children":10295},{"className":10294},[],[10296],{"type":62,"value":10297},"https:\u002F\u002F\u003Cvault-name>.vault.azure.net\u002Fsecrets\u002F\u003Csecret-name>\u002F\u003Cversion>",{"type":62,"value":10299}," and that this URI (not the secret value) is what should be shared back.",{"type":49,"tag":54,"props":10301,"children":10302},{},[10303],{"type":49,"tag":58,"props":10304,"children":10305},{},[10306],{"type":62,"value":10307},"Step 4 — Create environment variable in Dataverse:",{"type":49,"tag":54,"props":10309,"children":10310},{},[10311,10313,10318,10320,10326],{"type":62,"value":10312},"After the user shares the ",{"type":49,"tag":67,"props":10314,"children":10316},{"className":10315},[],[10317],{"type":62,"value":10262},{"type":62,"value":10319}," output from each command, create an environment variable definition in Dataverse that references the Key Vault secret. Use the ",{"type":49,"tag":67,"props":10321,"children":10323},{"className":10322},[],[10324],{"type":62,"value":10325},"secret",{"type":62,"value":10327}," type:",{"type":49,"tag":1335,"props":10329,"children":10331},{"className":1337,"code":10330,"language":1339,"meta":1340,"style":1340},"node \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-environment-variable.js\" \"\u003CENV_URL>\" \\\n  --schemaName \"\u003Cprefix_SecretName>\" \\\n  --displayName \"\u003CSecret Display Name>\" \\\n  --type \"secret\" \\\n  --value \"\u003CsecretUri-from-step-3>\"\n",[10332],{"type":49,"tag":67,"props":10333,"children":10334},{"__ignoreMap":1340},[10335,10379,10404,10429,10453],{"type":49,"tag":1346,"props":10336,"children":10337},{"class":1348,"line":1349},[10338,10342,10346,10350,10354,10359,10363,10367,10371,10375],{"type":49,"tag":1346,"props":10339,"children":10340},{"style":1353},[10341],{"type":62,"value":1356},{"type":49,"tag":1346,"props":10343,"children":10344},{"style":1359},[10345],{"type":62,"value":1362},{"type":49,"tag":1346,"props":10347,"children":10348},{"style":1365},[10349],{"type":62,"value":1368},{"type":49,"tag":1346,"props":10351,"children":10352},{"style":1359},[10353],{"type":62,"value":1373},{"type":49,"tag":1346,"props":10355,"children":10356},{"style":1376},[10357],{"type":62,"value":10358},"\u002Fscripts\u002Fcreate-environment-variable.js",{"type":49,"tag":1346,"props":10360,"children":10361},{"style":1359},[10362],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10364,"children":10365},{"style":1359},[10366],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10368,"children":10369},{"style":1376},[10370],{"type":62,"value":1394},{"type":49,"tag":1346,"props":10372,"children":10373},{"style":1359},[10374],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10376,"children":10377},{"style":1365},[10378],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10380,"children":10381},{"class":1348,"line":3208},[10382,10387,10391,10396,10400],{"type":49,"tag":1346,"props":10383,"children":10384},{"style":1376},[10385],{"type":62,"value":10386},"  --schemaName",{"type":49,"tag":1346,"props":10388,"children":10389},{"style":1359},[10390],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10392,"children":10393},{"style":1376},[10394],{"type":62,"value":10395},"\u003Cprefix_SecretName>",{"type":49,"tag":1346,"props":10397,"children":10398},{"style":1359},[10399],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10401,"children":10402},{"style":1365},[10403],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10405,"children":10406},{"class":1348,"line":3226},[10407,10412,10416,10421,10425],{"type":49,"tag":1346,"props":10408,"children":10409},{"style":1376},[10410],{"type":62,"value":10411},"  --displayName",{"type":49,"tag":1346,"props":10413,"children":10414},{"style":1359},[10415],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10417,"children":10418},{"style":1376},[10419],{"type":62,"value":10420},"\u003CSecret Display Name>",{"type":49,"tag":1346,"props":10422,"children":10423},{"style":1359},[10424],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10426,"children":10427},{"style":1365},[10428],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10430,"children":10431},{"class":1348,"line":3243},[10432,10437,10441,10445,10449],{"type":49,"tag":1346,"props":10433,"children":10434},{"style":1376},[10435],{"type":62,"value":10436},"  --type",{"type":49,"tag":1346,"props":10438,"children":10439},{"style":1359},[10440],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10442,"children":10443},{"style":1376},[10444],{"type":62,"value":10325},{"type":49,"tag":1346,"props":10446,"children":10447},{"style":1359},[10448],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10450,"children":10451},{"style":1365},[10452],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10454,"children":10455},{"class":1348,"line":3261},[10456,10461,10465,10470],{"type":49,"tag":1346,"props":10457,"children":10458},{"style":1376},[10459],{"type":62,"value":10460},"  --value",{"type":49,"tag":1346,"props":10462,"children":10463},{"style":1359},[10464],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10466,"children":10467},{"style":1376},[10468],{"type":62,"value":10469},"\u003CsecretUri-from-step-3>",{"type":49,"tag":1346,"props":10471,"children":10472},{"style":1359},[10473],{"type":62,"value":1399},{"type":49,"tag":54,"props":10475,"children":10476},{},[10477],{"type":49,"tag":58,"props":10478,"children":10479},{},[10480],{"type":62,"value":10481},"Step 5 — Create site setting for the environment variable:",{"type":49,"tag":54,"props":10483,"children":10484},{},[10485],{"type":62,"value":10486},"For each environment variable, create a site setting YAML that maps to it:",{"type":49,"tag":1335,"props":10488,"children":10490},{"className":1337,"code":10489,"language":1339,"meta":1340,"style":1340},"node \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-site-setting.js\" \\\n  --projectRoot \"\u003CPROJECT_ROOT>\" \\\n  --name \"\u003CSiteSetting\u002FName>\" \\\n  --envVarSchema \"\u003CschemaName-from-step-4>\"\n",[10491],{"type":49,"tag":67,"props":10492,"children":10493},{"__ignoreMap":1340},[10494,10526,10550,10574],{"type":49,"tag":1346,"props":10495,"children":10496},{"class":1348,"line":1349},[10497,10501,10505,10509,10513,10518,10522],{"type":49,"tag":1346,"props":10498,"children":10499},{"style":1353},[10500],{"type":62,"value":1356},{"type":49,"tag":1346,"props":10502,"children":10503},{"style":1359},[10504],{"type":62,"value":1362},{"type":49,"tag":1346,"props":10506,"children":10507},{"style":1365},[10508],{"type":62,"value":1368},{"type":49,"tag":1346,"props":10510,"children":10511},{"style":1359},[10512],{"type":62,"value":1373},{"type":49,"tag":1346,"props":10514,"children":10515},{"style":1376},[10516],{"type":62,"value":10517},"\u002Fscripts\u002Fcreate-site-setting.js",{"type":49,"tag":1346,"props":10519,"children":10520},{"style":1359},[10521],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10523,"children":10524},{"style":1365},[10525],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10527,"children":10528},{"class":1348,"line":3208},[10529,10534,10538,10542,10546],{"type":49,"tag":1346,"props":10530,"children":10531},{"style":1376},[10532],{"type":62,"value":10533},"  --projectRoot",{"type":49,"tag":1346,"props":10535,"children":10536},{"style":1359},[10537],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10539,"children":10540},{"style":1376},[10541],{"type":62,"value":8645},{"type":49,"tag":1346,"props":10543,"children":10544},{"style":1359},[10545],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10547,"children":10548},{"style":1365},[10549],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10551,"children":10552},{"class":1348,"line":3226},[10553,10557,10561,10566,10570],{"type":49,"tag":1346,"props":10554,"children":10555},{"style":1376},[10556],{"type":62,"value":10101},{"type":49,"tag":1346,"props":10558,"children":10559},{"style":1359},[10560],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10562,"children":10563},{"style":1376},[10564],{"type":62,"value":10565},"\u003CSiteSetting\u002FName>",{"type":49,"tag":1346,"props":10567,"children":10568},{"style":1359},[10569],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10571,"children":10572},{"style":1365},[10573],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10575,"children":10576},{"class":1348,"line":3243},[10577,10582,10586,10591],{"type":49,"tag":1346,"props":10578,"children":10579},{"style":1376},[10580],{"type":62,"value":10581},"  --envVarSchema",{"type":49,"tag":1346,"props":10583,"children":10584},{"style":1359},[10585],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10587,"children":10588},{"style":1376},[10589],{"type":62,"value":10590},"\u003CschemaName-from-step-4>",{"type":49,"tag":1346,"props":10592,"children":10593},{"style":1359},[10594],{"type":62,"value":1399},{"type":49,"tag":54,"props":10596,"children":10597},{},[10598,10600,10606,10607,10613],{"type":62,"value":10599},"This creates a site setting with ",{"type":49,"tag":67,"props":10601,"children":10603},{"className":10602},[],[10604],{"type":62,"value":10605},"envvar_schema",{"type":62,"value":351},{"type":49,"tag":67,"props":10608,"children":10610},{"className":10609},[],[10611],{"type":62,"value":10612},"source: 1",{"type":62,"value":10614},", which tells Power Pages to resolve the value from the Dataverse environment variable (backed by Key Vault).",{"type":49,"tag":487,"props":10616,"children":10618},{"id":10617},"_72b-direct-environment-variable-path",[10619],{"type":62,"value":10620},"7.2b Direct Environment Variable Path",{"type":49,"tag":54,"props":10622,"children":10623},{},[10624],{"type":62,"value":10625},"If the user chose not to use Azure Key Vault:",{"type":49,"tag":54,"props":10627,"children":10628},{},[10629],{"type":49,"tag":58,"props":10630,"children":10631},{},[10632],{"type":62,"value":10633},"Step 1 — Create environment variables with placeholder values:",{"type":49,"tag":54,"props":10635,"children":10636},{},[10637],{"type":62,"value":10638},"For each secret identified in Phase 2.3, create the environment variable in Dataverse with a placeholder value:",{"type":49,"tag":1335,"props":10640,"children":10642},{"className":1337,"code":10641,"language":1339,"meta":1340,"style":1340},"node \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-environment-variable.js\" \"\u003CENV_URL>\" \\\n  --schemaName \"\u003Cprefix_SecretName>\" \\\n  --displayName \"\u003CSecret Display Name>\" \\\n  --value \"PLACEHOLDER_SET_ACTUAL_VALUE\"\n",[10643],{"type":49,"tag":67,"props":10644,"children":10645},{"__ignoreMap":1340},[10646,10689,10712,10735],{"type":49,"tag":1346,"props":10647,"children":10648},{"class":1348,"line":1349},[10649,10653,10657,10661,10665,10669,10673,10677,10681,10685],{"type":49,"tag":1346,"props":10650,"children":10651},{"style":1353},[10652],{"type":62,"value":1356},{"type":49,"tag":1346,"props":10654,"children":10655},{"style":1359},[10656],{"type":62,"value":1362},{"type":49,"tag":1346,"props":10658,"children":10659},{"style":1365},[10660],{"type":62,"value":1368},{"type":49,"tag":1346,"props":10662,"children":10663},{"style":1359},[10664],{"type":62,"value":1373},{"type":49,"tag":1346,"props":10666,"children":10667},{"style":1376},[10668],{"type":62,"value":10358},{"type":49,"tag":1346,"props":10670,"children":10671},{"style":1359},[10672],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10674,"children":10675},{"style":1359},[10676],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10678,"children":10679},{"style":1376},[10680],{"type":62,"value":1394},{"type":49,"tag":1346,"props":10682,"children":10683},{"style":1359},[10684],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10686,"children":10687},{"style":1365},[10688],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10690,"children":10691},{"class":1348,"line":3208},[10692,10696,10700,10704,10708],{"type":49,"tag":1346,"props":10693,"children":10694},{"style":1376},[10695],{"type":62,"value":10386},{"type":49,"tag":1346,"props":10697,"children":10698},{"style":1359},[10699],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10701,"children":10702},{"style":1376},[10703],{"type":62,"value":10395},{"type":49,"tag":1346,"props":10705,"children":10706},{"style":1359},[10707],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10709,"children":10710},{"style":1365},[10711],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10713,"children":10714},{"class":1348,"line":3226},[10715,10719,10723,10727,10731],{"type":49,"tag":1346,"props":10716,"children":10717},{"style":1376},[10718],{"type":62,"value":10411},{"type":49,"tag":1346,"props":10720,"children":10721},{"style":1359},[10722],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10724,"children":10725},{"style":1376},[10726],{"type":62,"value":10420},{"type":49,"tag":1346,"props":10728,"children":10729},{"style":1359},[10730],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10732,"children":10733},{"style":1365},[10734],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10736,"children":10737},{"class":1348,"line":3243},[10738,10742,10746,10751],{"type":49,"tag":1346,"props":10739,"children":10740},{"style":1376},[10741],{"type":62,"value":10460},{"type":49,"tag":1346,"props":10743,"children":10744},{"style":1359},[10745],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10747,"children":10748},{"style":1376},[10749],{"type":62,"value":10750},"PLACEHOLDER_SET_ACTUAL_VALUE",{"type":49,"tag":1346,"props":10752,"children":10753},{"style":1359},[10754],{"type":62,"value":1399},{"type":49,"tag":54,"props":10756,"children":10757},{},[10758],{"type":49,"tag":58,"props":10759,"children":10760},{},[10761],{"type":62,"value":10762},"Step 2 — Create site setting for the environment variable:",{"type":49,"tag":1335,"props":10764,"children":10766},{"className":1337,"code":10765,"language":1339,"meta":1340,"style":1340},"node \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-site-setting.js\" \\\n  --projectRoot \"\u003CPROJECT_ROOT>\" \\\n  --name \"\u003CSiteSetting\u002FName>\" \\\n  --envVarSchema \"\u003CschemaName-from-step-1>\"\n",[10767],{"type":49,"tag":67,"props":10768,"children":10769},{"__ignoreMap":1340},[10770,10801,10824,10847],{"type":49,"tag":1346,"props":10771,"children":10772},{"class":1348,"line":1349},[10773,10777,10781,10785,10789,10793,10797],{"type":49,"tag":1346,"props":10774,"children":10775},{"style":1353},[10776],{"type":62,"value":1356},{"type":49,"tag":1346,"props":10778,"children":10779},{"style":1359},[10780],{"type":62,"value":1362},{"type":49,"tag":1346,"props":10782,"children":10783},{"style":1365},[10784],{"type":62,"value":1368},{"type":49,"tag":1346,"props":10786,"children":10787},{"style":1359},[10788],{"type":62,"value":1373},{"type":49,"tag":1346,"props":10790,"children":10791},{"style":1376},[10792],{"type":62,"value":10517},{"type":49,"tag":1346,"props":10794,"children":10795},{"style":1359},[10796],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10798,"children":10799},{"style":1365},[10800],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10802,"children":10803},{"class":1348,"line":3208},[10804,10808,10812,10816,10820],{"type":49,"tag":1346,"props":10805,"children":10806},{"style":1376},[10807],{"type":62,"value":10533},{"type":49,"tag":1346,"props":10809,"children":10810},{"style":1359},[10811],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10813,"children":10814},{"style":1376},[10815],{"type":62,"value":8645},{"type":49,"tag":1346,"props":10817,"children":10818},{"style":1359},[10819],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10821,"children":10822},{"style":1365},[10823],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10825,"children":10826},{"class":1348,"line":3226},[10827,10831,10835,10839,10843],{"type":49,"tag":1346,"props":10828,"children":10829},{"style":1376},[10830],{"type":62,"value":10101},{"type":49,"tag":1346,"props":10832,"children":10833},{"style":1359},[10834],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10836,"children":10837},{"style":1376},[10838],{"type":62,"value":10565},{"type":49,"tag":1346,"props":10840,"children":10841},{"style":1359},[10842],{"type":62,"value":1384},{"type":49,"tag":1346,"props":10844,"children":10845},{"style":1365},[10846],{"type":62,"value":10093},{"type":49,"tag":1346,"props":10848,"children":10849},{"class":1348,"line":3243},[10850,10854,10858,10863],{"type":49,"tag":1346,"props":10851,"children":10852},{"style":1376},[10853],{"type":62,"value":10581},{"type":49,"tag":1346,"props":10855,"children":10856},{"style":1359},[10857],{"type":62,"value":1389},{"type":49,"tag":1346,"props":10859,"children":10860},{"style":1376},[10861],{"type":62,"value":10862},"\u003CschemaName-from-step-1>",{"type":49,"tag":1346,"props":10864,"children":10865},{"style":1359},[10866],{"type":62,"value":1399},{"type":49,"tag":54,"props":10868,"children":10869},{},[10870],{"type":49,"tag":58,"props":10871,"children":10872},{},[10873],{"type":62,"value":10874},"Step 3 — Give the user steps to set the actual secret values:",{"type":49,"tag":54,"props":10876,"children":10877},{},[10878,10879,10883],{"type":62,"value":2730},{"type":49,"tag":58,"props":10880,"children":10881},{},[10882],{"type":62,"value":2735},{"type":62,"value":10884}," ask for secret values — they must never pass through the conversation. Instead, tell the user to update each placeholder with the real value using one of these approaches:",{"type":49,"tag":291,"props":10886,"children":10887},{},[10888],{"type":49,"tag":98,"props":10889,"children":10890},{},[10891,10896,10897,10905,10907,10912,10913,10918,10919,10924],{"type":49,"tag":58,"props":10892,"children":10893},{},[10894],{"type":62,"value":10895},"Power Apps maker portal",{"type":62,"value":1474},{"type":49,"tag":478,"props":10898,"children":10902},{"href":10899,"rel":10900},"https:\u002F\u002Fmake.powerapps.com",[10901],"nofollow",[10903],{"type":62,"value":10904},"make.powerapps.com",{"type":62,"value":10906},") — Go to ",{"type":49,"tag":58,"props":10908,"children":10909},{},[10910],{"type":62,"value":10911},"Solutions",{"type":62,"value":5275},{"type":49,"tag":58,"props":10914,"children":10915},{},[10916],{"type":62,"value":10917},"Default Solution",{"type":62,"value":5275},{"type":49,"tag":58,"props":10920,"children":10921},{},[10922],{"type":62,"value":10923},"Environment variables",{"type":62,"value":10925}," → find the variable by display name → update the value",{"type":49,"tag":54,"props":10927,"children":10928},{},[10929],{"type":62,"value":10930},"Present the list of environment variables that need updating (display name and schema name for each) so the user knows exactly which ones to set.",{"type":49,"tag":487,"props":10932,"children":10934},{"id":10933},"_73-verify-environment-variable-configuration",[10935],{"type":62,"value":10936},"7.3 Verify Environment Variable Configuration",{"type":49,"tag":54,"props":10938,"children":10939},{},[10940],{"type":62,"value":10941},"After creating all environment variables and site settings:",{"type":49,"tag":94,"props":10943,"children":10944},{},[10945,10956,10972],{"type":49,"tag":98,"props":10946,"children":10947},{},[10948,10950],{"type":62,"value":10949},"Confirm each site setting YAML was created in ",{"type":49,"tag":67,"props":10951,"children":10953},{"className":10952},[],[10954],{"type":62,"value":10955},".powerpages-site\u002Fsite-settings\u002F",{"type":49,"tag":98,"props":10957,"children":10958},{},[10959,10961,10966,10967],{"type":62,"value":10960},"Verify each YAML contains ",{"type":49,"tag":67,"props":10962,"children":10964},{"className":10963},[],[10965],{"type":62,"value":10605},{"type":62,"value":351},{"type":49,"tag":67,"props":10968,"children":10970},{"className":10969},[],[10971],{"type":62,"value":10612},{"type":49,"tag":98,"props":10973,"children":10974},{},[10975,10977],{"type":62,"value":10976},"Confirm the server logic code references the correct site setting names via ",{"type":49,"tag":67,"props":10978,"children":10980},{"className":10979},[],[10981],{"type":62,"value":10982},"Server.Sitesetting.Get(\"\u003CSiteSetting\u002FName>\")",{"type":49,"tag":487,"props":10984,"children":10986},{"id":10985},"_74-git-commit",[10987],{"type":62,"value":10988},"7.4 Git Commit",{"type":49,"tag":54,"props":10990,"children":10991},{},[10992],{"type":62,"value":10993},"Do a git commit for the environment variable site setting changes.",{"type":49,"tag":54,"props":10995,"children":10996},{},[10997,11001],{"type":49,"tag":58,"props":10998,"children":10999},{},[11000],{"type":62,"value":993},{"type":62,"value":11002},": Environment variables created in Dataverse (with or without Azure Key Vault backing), site settings configured, server logic referencing correct setting names",{"type":49,"tag":281,"props":11004,"children":11005},{},[],{"type":49,"tag":87,"props":11007,"children":11009},{"id":11008},"phase-8-configure-site-settings",[11010],{"type":62,"value":11011},"Phase 8: Configure Site Settings",{"type":49,"tag":54,"props":11013,"children":11014},{},[11015,11019],{"type":49,"tag":58,"props":11016,"children":11017},{},[11018],{"type":62,"value":456},{"type":62,"value":11020},": Set up site settings for the server logic feature",{"type":49,"tag":54,"props":11022,"children":11023},{},[11024,11028],{"type":49,"tag":58,"props":11025,"children":11026},{},[11027],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":11030,"children":11032},{"id":11031},"_81-configure-server-logic-site-settings",[11033],{"type":62,"value":11034},"8.1 Configure Server Logic Site Settings",{"type":49,"tag":54,"props":11036,"children":11037},{},[11038,11039,11044],{"type":62,"value":939},{"type":49,"tag":67,"props":11040,"children":11042},{"className":11041},[],[11043],{"type":62,"value":259},{"type":62,"value":11045}," folder is guaranteed to exist at this point (verified in Phase 1.5).",{"type":49,"tag":54,"props":11047,"children":11048},{},[11049],{"type":62,"value":11050},"The following site settings control server logic behavior. Only create settings that differ from defaults or are specifically needed:",{"type":49,"tag":905,"props":11052,"children":11053},{},[11054,11080],{"type":49,"tag":909,"props":11055,"children":11056},{},[11057],{"type":49,"tag":913,"props":11058,"children":11059},{},[11060,11065,11070,11075],{"type":49,"tag":917,"props":11061,"children":11062},{},[11063],{"type":62,"value":11064},"Setting",{"type":49,"tag":917,"props":11066,"children":11067},{},[11068],{"type":62,"value":11069},"Description",{"type":49,"tag":917,"props":11071,"children":11072},{},[11073],{"type":62,"value":11074},"Default",{"type":49,"tag":917,"props":11076,"children":11077},{},[11078],{"type":62,"value":11079},"When to configure",{"type":49,"tag":928,"props":11081,"children":11082},{},[11083,11114,11141,11179],{"type":49,"tag":913,"props":11084,"children":11085},{},[11086,11095,11100,11109],{"type":49,"tag":935,"props":11087,"children":11088},{},[11089],{"type":49,"tag":67,"props":11090,"children":11092},{"className":11091},[],[11093],{"type":62,"value":11094},"ServerLogic\u002FEnabled",{"type":49,"tag":935,"props":11096,"children":11097},{},[11098],{"type":62,"value":11099},"Enable\u002Fdisable server logic feature",{"type":49,"tag":935,"props":11101,"children":11102},{},[11103],{"type":49,"tag":67,"props":11104,"children":11106},{"className":11105},[],[11107],{"type":62,"value":11108},"true",{"type":49,"tag":935,"props":11110,"children":11111},{},[11112],{"type":62,"value":11113},"Only if explicitly disabled and needs re-enabling",{"type":49,"tag":913,"props":11115,"children":11116},{},[11117,11126,11131,11136],{"type":49,"tag":935,"props":11118,"children":11119},{},[11120],{"type":49,"tag":67,"props":11121,"children":11123},{"className":11122},[],[11124],{"type":62,"value":11125},"ServerLogic\u002FAllowedDomains",{"type":49,"tag":935,"props":11127,"children":11128},{},[11129],{"type":62,"value":11130},"Restrict which external domains HttpClient can call",{"type":49,"tag":935,"props":11132,"children":11133},{},[11134],{"type":62,"value":11135},"All domains",{"type":49,"tag":935,"props":11137,"children":11138},{},[11139],{"type":62,"value":11140},"When the server logic calls external APIs and you want to restrict to specific domains for security",{"type":49,"tag":913,"props":11142,"children":11143},{},[11144,11153,11158,11167],{"type":49,"tag":935,"props":11145,"children":11146},{},[11147],{"type":49,"tag":67,"props":11148,"children":11150},{"className":11149},[],[11151],{"type":62,"value":11152},"ServerLogic\u002FTimeoutInSeconds",{"type":49,"tag":935,"props":11154,"children":11155},{},[11156],{"type":62,"value":11157},"Maximum execution time",{"type":49,"tag":935,"props":11159,"children":11160},{},[11161],{"type":49,"tag":67,"props":11162,"children":11164},{"className":11163},[],[11165],{"type":62,"value":11166},"120",{"type":49,"tag":935,"props":11168,"children":11169},{},[11170,11172,11177],{"type":62,"value":11171},"The platform caps this at ",{"type":49,"tag":58,"props":11173,"children":11174},{},[11175],{"type":62,"value":11176},"120 seconds",{"type":62,"value":11178}," — values above 120 are silently clamped. Only configure when you need to lower the timeout, not raise it.",{"type":49,"tag":913,"props":11180,"children":11181},{},[11182,11191,11196,11204],{"type":49,"tag":935,"props":11183,"children":11184},{},[11185],{"type":49,"tag":67,"props":11186,"children":11188},{"className":11187},[],[11189],{"type":62,"value":11190},"ServerLogic\u002FAllowNetworkingToAllDomains",{"type":49,"tag":935,"props":11192,"children":11193},{},[11194],{"type":62,"value":11195},"Allow networking across domains",{"type":49,"tag":935,"props":11197,"children":11198},{},[11199],{"type":49,"tag":67,"props":11200,"children":11202},{"className":11201},[],[11203],{"type":62,"value":11108},{"type":49,"tag":935,"props":11205,"children":11206},{},[11207,11209,11215],{"type":62,"value":11208},"Set to ",{"type":49,"tag":67,"props":11210,"children":11212},{"className":11211},[],[11213],{"type":62,"value":11214},"false",{"type":62,"value":11216}," when restricting via AllowedDomains",{"type":49,"tag":54,"props":11218,"children":11219},{},[11220],{"type":62,"value":11221},"Use the existing site setting creation script:",{"type":49,"tag":1335,"props":11223,"children":11225},{"className":1337,"code":11224,"language":1339,"meta":1340,"style":1340},"node \"${PLUGIN_ROOT}\u002Fscripts\u002Fcreate-site-setting.js\" --projectRoot \"\u003CPROJECT_ROOT>\" --name \"ServerLogic\u002FAllowedDomains\" --value \"api.example.com,api.other.com\" --description \"Restrict server logic external API calls to these domains\"\n",[11226],{"type":49,"tag":67,"props":11227,"children":11228},{"__ignoreMap":1340},[11229],{"type":49,"tag":1346,"props":11230,"children":11231},{"class":1348,"line":1349},[11232,11236,11240,11244,11248,11252,11256,11260,11264,11268,11272,11276,11280,11284,11288,11293,11297,11302,11306,11310,11314,11319],{"type":49,"tag":1346,"props":11233,"children":11234},{"style":1353},[11235],{"type":62,"value":1356},{"type":49,"tag":1346,"props":11237,"children":11238},{"style":1359},[11239],{"type":62,"value":1362},{"type":49,"tag":1346,"props":11241,"children":11242},{"style":1365},[11243],{"type":62,"value":1368},{"type":49,"tag":1346,"props":11245,"children":11246},{"style":1359},[11247],{"type":62,"value":1373},{"type":49,"tag":1346,"props":11249,"children":11250},{"style":1376},[11251],{"type":62,"value":10517},{"type":49,"tag":1346,"props":11253,"children":11254},{"style":1359},[11255],{"type":62,"value":1384},{"type":49,"tag":1346,"props":11257,"children":11258},{"style":1376},[11259],{"type":62,"value":8636},{"type":49,"tag":1346,"props":11261,"children":11262},{"style":1359},[11263],{"type":62,"value":1389},{"type":49,"tag":1346,"props":11265,"children":11266},{"style":1376},[11267],{"type":62,"value":8645},{"type":49,"tag":1346,"props":11269,"children":11270},{"style":1359},[11271],{"type":62,"value":1384},{"type":49,"tag":1346,"props":11273,"children":11274},{"style":1376},[11275],{"type":62,"value":8654},{"type":49,"tag":1346,"props":11277,"children":11278},{"style":1359},[11279],{"type":62,"value":1389},{"type":49,"tag":1346,"props":11281,"children":11282},{"style":1376},[11283],{"type":62,"value":11125},{"type":49,"tag":1346,"props":11285,"children":11286},{"style":1359},[11287],{"type":62,"value":1384},{"type":49,"tag":1346,"props":11289,"children":11290},{"style":1376},[11291],{"type":62,"value":11292}," --value",{"type":49,"tag":1346,"props":11294,"children":11295},{"style":1359},[11296],{"type":62,"value":1389},{"type":49,"tag":1346,"props":11298,"children":11299},{"style":1376},[11300],{"type":62,"value":11301},"api.example.com,api.other.com",{"type":49,"tag":1346,"props":11303,"children":11304},{"style":1359},[11305],{"type":62,"value":1384},{"type":49,"tag":1346,"props":11307,"children":11308},{"style":1376},[11309],{"type":62,"value":8690},{"type":49,"tag":1346,"props":11311,"children":11312},{"style":1359},[11313],{"type":62,"value":1389},{"type":49,"tag":1346,"props":11315,"children":11316},{"style":1376},[11317],{"type":62,"value":11318},"Restrict server logic external API calls to these domains",{"type":49,"tag":1346,"props":11320,"children":11321},{"style":1359},[11322],{"type":62,"value":1399},{"type":49,"tag":487,"props":11324,"children":11326},{"id":11325},"_82-git-commit",[11327],{"type":62,"value":11328},"8.2 Git Commit",{"type":49,"tag":54,"props":11330,"children":11331},{},[11332],{"type":62,"value":11333},"If any settings were created:",{"type":49,"tag":54,"props":11335,"children":11336},{},[11337],{"type":62,"value":11338},"Do a git commit for the site settings changes.",{"type":49,"tag":54,"props":11340,"children":11341},{},[11342,11346],{"type":49,"tag":58,"props":11343,"children":11344},{},[11345],{"type":62,"value":993},{"type":62,"value":11347},": Site settings configured and committed (or skipped if not needed\u002Fdeployed)",{"type":49,"tag":281,"props":11349,"children":11350},{},[],{"type":49,"tag":87,"props":11352,"children":11354},{"id":11353},"phase-9-client-side-integration",[11355],{"type":62,"value":11356},"Phase 9: Client-Side Integration",{"type":49,"tag":54,"props":11358,"children":11359},{},[11360,11364],{"type":49,"tag":58,"props":11361,"children":11362},{},[11363],{"type":62,"value":456},{"type":62,"value":11365},": Help the user call the server logic endpoints from their site's frontend code, matching existing patterns discovered in Phase 1",{"type":49,"tag":54,"props":11367,"children":11368},{},[11369],{"type":62,"value":11370},"Server logic creates the backend — but without frontend code to call it, the endpoints are unused. This phase creates or updates frontend code to consume the server logic APIs, using the patterns and conventions already established in the codebase.",{"type":49,"tag":54,"props":11372,"children":11373},{},[11374,11378],{"type":49,"tag":58,"props":11375,"children":11376},{},[11377],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":11380,"children":11382},{"id":11381},"_91-ask-user-about-integration-scope",[11383],{"type":62,"value":11384},"9.1 Ask User About Integration Scope",{"type":49,"tag":50,"props":11386,"children":11387},{},[11388,11399],{"type":49,"tag":54,"props":11389,"children":11390},{},[11391,11392,11397],{"type":62,"value":831},{"type":49,"tag":58,"props":11393,"children":11394},{},[11395],{"type":62,"value":11396},"Gate (plan · add-server-logic:9.1.frontend-scope):",{"type":62,"value":11398}," Decide whether the skill also wires the server logic into the frontend UI or stops at the backend.",{"type":49,"tag":54,"props":11400,"children":11401},{},[11402,11406,11408,11412,11414,11418],{"type":49,"tag":58,"props":11403,"children":11404},{},[11405],{"type":62,"value":853},{"type":62,"value":11407}," Phase 8 completed (server logic deployed-ready).\n",{"type":49,"tag":58,"props":11409,"children":11410},{},[11411],{"type":62,"value":867},{"type":62,"value":11413}," Auto-integrating mutates UI files the user wanted to handle themselves; auto-skipping leaves the endpoints unreachable from the app.\n",{"type":49,"tag":58,"props":11415,"children":11416},{},[11417],{"type":62,"value":889},{"type":62,"value":11419}," Nothing — server logic backend is already on disk; this prompt only decides frontend follow-through.",{"type":49,"tag":54,"props":11421,"children":11422},{},[11423,11424,11429],{"type":62,"value":896},{"type":49,"tag":67,"props":11425,"children":11427},{"className":11426},[],[11428],{"type":62,"value":902},{"type":62,"value":468},{"type":49,"tag":905,"props":11431,"children":11432},{},[11433,11447],{"type":49,"tag":909,"props":11434,"children":11435},{},[11436],{"type":49,"tag":913,"props":11437,"children":11438},{},[11439,11443],{"type":49,"tag":917,"props":11440,"children":11441},{},[11442],{"type":62,"value":921},{"type":49,"tag":917,"props":11444,"children":11445},{},[11446],{"type":62,"value":926},{"type":49,"tag":928,"props":11448,"children":11449},{},[11450],{"type":49,"tag":913,"props":11451,"children":11452},{},[11453,11458],{"type":49,"tag":935,"props":11454,"children":11455},{},[11456],{"type":62,"value":11457},"I've created the server logic backend. Would you like me to also fully integrate it into the frontend UI?",{"type":49,"tag":935,"props":11459,"children":11460},{},[11461],{"type":62,"value":11462},"Yes, fully integrate it into the UI (Recommended), No, I'll handle the frontend myself",{"type":49,"tag":54,"props":11464,"children":11465},{},[11466,11471],{"type":49,"tag":58,"props":11467,"children":11468},{},[11469],{"type":62,"value":11470},"If \"No\"",{"type":62,"value":11472},": Skip to Phase 10, but provide the API URL and a code snippet the user can copy.",{"type":49,"tag":487,"props":11474,"children":11476},{"id":11475},"_92-follow-the-frontend-integration-reference",[11477],{"type":62,"value":11478},"9.2 Follow the Frontend Integration Reference",{"type":49,"tag":54,"props":11480,"children":11481},{},[11482],{"type":62,"value":11483},"Use the reference below for the frontend integration approach, examples, and framework-specific patterns:",{"type":49,"tag":50,"props":11485,"children":11486},{},[11487],{"type":49,"tag":54,"props":11488,"children":11489},{},[11490,11491],{"type":62,"value":2476},{"type":49,"tag":67,"props":11492,"children":11494},{"className":11493},[],[11495],{"type":62,"value":8432},{"type":49,"tag":54,"props":11497,"children":11498},{},[11499],{"type":62,"value":11500},"Based on the Explore agent's findings from Phase 1.4 and the approved plan, choose the integration approach from that reference and apply it consistently across all server logic endpoints being wired into the frontend.",{"type":49,"tag":487,"props":11502,"children":11504},{"id":11503},"_93-create-or-update-frontend-integration",[11505],{"type":62,"value":11506},"9.3 Create or Update Frontend Integration",{"type":49,"tag":54,"props":11508,"children":11509},{},[11510],{"type":62,"value":11511},"Following the reference:",{"type":49,"tag":94,"props":11513,"children":11514},{},[11515,11520,11525,11530,11535,11546,11551,11556,11561,11571,11581],{"type":49,"tag":98,"props":11516,"children":11517},{},[11518],{"type":62,"value":11519},"Reuse the existing service layer or API utility when the site already has one",{"type":49,"tag":98,"props":11521,"children":11522},{},[11523],{"type":62,"value":11524},"Create a lightweight CSRF-aware helper only when the site has no established API client pattern",{"type":49,"tag":98,"props":11526,"children":11527},{},[11528],{"type":62,"value":11529},"Group multiple server logic endpoints into a coherent service module when that improves maintainability",{"type":49,"tag":98,"props":11531,"children":11532},{},[11533],{"type":62,"value":11534},"Add framework-specific hooks\u002Fcomposables\u002Fservices only when the codebase already follows that pattern",{"type":49,"tag":98,"props":11536,"children":11537},{},[11538,11540,11544],{"type":62,"value":11539},"Fully integrate the server logic into the actual UI flow — do ",{"type":49,"tag":58,"props":11541,"children":11542},{},[11543],{"type":62,"value":2735},{"type":62,"value":11545}," stop at creating service\u002Fhelper code",{"type":49,"tag":98,"props":11547,"children":11548},{},[11549],{"type":62,"value":11550},"Update the relevant pages, components, forms, buttons, or user journeys so the new backend behavior is reachable from the interface",{"type":49,"tag":98,"props":11552,"children":11553},{},[11554],{"type":62,"value":11555},"Replace placeholder data, mock handlers, or temporary actions when they are meant to be backed by the new server logic endpoints",{"type":49,"tag":98,"props":11557,"children":11558},{},[11559],{"type":62,"value":11560},"Add or preserve loading, success, empty, and error states so the UI behaves like a finished feature",{"type":49,"tag":98,"props":11562,"children":11563},{},[11564,11569],{"type":49,"tag":58,"props":11565,"children":11566},{},[11567],{"type":62,"value":11568},"For validate-and-execute endpoints",{"type":62,"value":11570},": The frontend must call the server logic endpoint for the protected operation (e.g., status transition) — it must NOT make a separate Web API PATCH for the same field. Ensure the UI for that operation (e.g., a \"Submit\" or \"Approve\" button) calls the server logic service function, not the Web API service",{"type":49,"tag":98,"props":11572,"children":11573},{},[11574,11579],{"type":49,"tag":58,"props":11575,"children":11576},{},[11577],{"type":62,"value":11578},"For Dataverse-backed endpoints",{"type":62,"value":11580},": Match the frontend parsing to the response shape chosen in Phase 5.3. See \"Dataverse Connector Response Format\" in the frontend integration reference for the exact parsing per shape.",{"type":49,"tag":98,"props":11582,"children":11583},{},[11584,11589,11591,11597],{"type":49,"tag":58,"props":11585,"children":11586},{},[11587],{"type":62,"value":11588},"If the response shape is unclear",{"type":62,"value":11590},": Do not guess. After the site is deployed, invoke ",{"type":49,"tag":67,"props":11592,"children":11594},{"className":11593},[],[11595],{"type":62,"value":11596},"\u002Ftest-site",{"type":62,"value":11598}," against the live site so the actual server logic response can be captured from the network tab and used to drive the integration",{"type":49,"tag":487,"props":11600,"children":11602},{"id":11601},"_94-git-commit",[11603],{"type":62,"value":11604},"9.4 Git Commit",{"type":49,"tag":54,"props":11606,"children":11607},{},[11608],{"type":62,"value":11609},"If frontend integration code was created:",{"type":49,"tag":54,"props":11611,"children":11612},{},[11613],{"type":62,"value":11614},"Do a git commit for the frontend integration changes.",{"type":49,"tag":54,"props":11616,"children":11617},{},[11618,11622],{"type":49,"tag":58,"props":11619,"children":11620},{},[11621],{"type":62,"value":993},{"type":62,"value":11623},": Frontend service\u002Fhook created as needed, UI components\u002Fpages fully integrated, and changes committed",{"type":49,"tag":281,"props":11625,"children":11626},{},[],{"type":49,"tag":87,"props":11628,"children":11630},{"id":11629},"phase-10-verify-test-guidance",[11631],{"type":62,"value":11632},"Phase 10: Verify & Test Guidance",{"type":49,"tag":54,"props":11634,"children":11635},{},[11636,11640],{"type":49,"tag":58,"props":11637,"children":11638},{},[11639],{"type":62,"value":456},{"type":62,"value":11641},": Validate the code and provide the user with everything needed to test the server logic",{"type":49,"tag":54,"props":11643,"children":11644},{},[11645,11649],{"type":49,"tag":58,"props":11646,"children":11647},{},[11648],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":11651,"children":11653},{"id":11652},"_101-final-code-validation",[11654],{"type":62,"value":11655},"10.1 Final Code Validation",{"type":49,"tag":54,"props":11657,"children":11658},{},[11659,11661,11666],{"type":62,"value":11660},"Re-read each created ",{"type":49,"tag":67,"props":11662,"children":11664},{"className":11663},[],[11665],{"type":62,"value":349},{"type":62,"value":11667}," file and verify:",{"type":49,"tag":94,"props":11669,"children":11672},{"className":11670},[11671],"contains-task-list",[11673,11685,11694,11703,11712,11734,11779,11788,11797,11806],{"type":49,"tag":98,"props":11674,"children":11677},{"className":11675},[11676],"task-list-item",[11678,11683],{"type":49,"tag":11679,"props":11680,"children":11682},"input",{"disabled":42,"type":11681},"checkbox",[],{"type":62,"value":11684}," Only allowed top-level functions (get, post, put, patch, del)",{"type":49,"tag":98,"props":11686,"children":11688},{"className":11687},[11676],[11689,11692],{"type":49,"tag":11679,"props":11690,"children":11691},{"disabled":42,"type":11681},[],{"type":62,"value":11693}," Every function returns a string",{"type":49,"tag":98,"props":11695,"children":11697},{"className":11696},[11676],[11698,11701],{"type":49,"tag":11679,"props":11699,"children":11700},{"disabled":42,"type":11681},[],{"type":62,"value":11702}," try\u002Fcatch in every function",{"type":49,"tag":98,"props":11704,"children":11706},{"className":11705},[11676],[11707,11710],{"type":49,"tag":11679,"props":11708,"children":11709},{"disabled":42,"type":11681},[],{"type":62,"value":11711}," Server.Logger calls in every function",{"type":49,"tag":98,"props":11713,"children":11715},{"className":11714},[11676],[11716,11719,11721,11726,11727,11732],{"type":49,"tag":11679,"props":11717,"children":11718},{"disabled":42,"type":11681},[],{"type":62,"value":11720}," No ",{"type":49,"tag":67,"props":11722,"children":11724},{"className":11723},[],[11725],{"type":62,"value":3479},{"type":62,"value":125},{"type":49,"tag":67,"props":11728,"children":11730},{"className":11729},[],[11731],{"type":62,"value":3486},{"type":62,"value":11733},", or external dependencies",{"type":49,"tag":98,"props":11735,"children":11737},{"className":11736},[11676],[11738,11741,11743,11748,11749,11754,11755,11760,11761,11766,11767,11772,11773,11778],{"type":49,"tag":11679,"props":11739,"children":11740},{"disabled":42,"type":11681},[],{"type":62,"value":11742}," No browser APIs (",{"type":49,"tag":67,"props":11744,"children":11746},{"className":11745},[],[11747],{"type":62,"value":123},{"type":62,"value":125},{"type":49,"tag":67,"props":11750,"children":11752},{"className":11751},[],[11753],{"type":62,"value":131},{"type":62,"value":125},{"type":49,"tag":67,"props":11756,"children":11758},{"className":11757},[],[11759],{"type":62,"value":138},{"type":62,"value":125},{"type":49,"tag":67,"props":11762,"children":11764},{"className":11763},[],[11765],{"type":62,"value":3528},{"type":62,"value":125},{"type":49,"tag":67,"props":11768,"children":11770},{"className":11769},[],[11771],{"type":62,"value":9140},{"type":62,"value":125},{"type":49,"tag":67,"props":11774,"children":11776},{"className":11775},[],[11777],{"type":62,"value":9147},{"type":62,"value":1113},{"type":49,"tag":98,"props":11780,"children":11782},{"className":11781},[11676],[11783,11786],{"type":49,"tag":11679,"props":11784,"children":11785},{"disabled":42,"type":11681},[],{"type":62,"value":11787}," Async only on functions that use await",{"type":49,"tag":98,"props":11789,"children":11791},{"className":11790},[11676],[11792,11795],{"type":49,"tag":11679,"props":11793,"children":11794},{"disabled":42,"type":11681},[],{"type":62,"value":11796}," Correct SDK method usage (verified against Phase 3 documentation)",{"type":49,"tag":98,"props":11798,"children":11800},{"className":11799},[11676],[11801,11804],{"type":49,"tag":11679,"props":11802,"children":11803},{"disabled":42,"type":11681},[],{"type":62,"value":11805}," HttpClient used only for external APIs (not Dataverse)",{"type":49,"tag":98,"props":11807,"children":11809},{"className":11808},[11676],[11810,11813],{"type":49,"tag":11679,"props":11811,"children":11812},{"disabled":42,"type":11681},[],{"type":62,"value":11814}," Dataverse connector used for Dataverse operations",{"type":49,"tag":54,"props":11816,"children":11817},{},[11818,11820,11825],{"type":62,"value":11819},"Re-read each ",{"type":49,"tag":67,"props":11821,"children":11823},{"className":11822},[],[11824],{"type":62,"value":357},{"type":62,"value":11667},{"type":49,"tag":94,"props":11827,"children":11829},{"className":11828},[11671],[11830,11845,11860,11882,11903,11912],{"type":49,"tag":98,"props":11831,"children":11833},{"className":11832},[11676],[11834,11837,11838,11843],{"type":49,"tag":11679,"props":11835,"children":11836},{"disabled":42,"type":11681},[],{"type":62,"value":838},{"type":49,"tag":67,"props":11839,"children":11841},{"className":11840},[],[11842],{"type":62,"value":3249},{"type":62,"value":11844}," field exists and is a valid UUID",{"type":49,"tag":98,"props":11846,"children":11848},{"className":11847},[11676],[11849,11852,11853,11858],{"type":49,"tag":11679,"props":11850,"children":11851},{"disabled":42,"type":11681},[],{"type":62,"value":838},{"type":49,"tag":67,"props":11854,"children":11856},{"className":11855},[],[11857],{"type":62,"value":8749},{"type":62,"value":11859}," array is non-empty (at least one web role)",{"type":49,"tag":98,"props":11861,"children":11863},{"className":11862},[11676],[11864,11867,11868,11873,11875,11880],{"type":49,"tag":11679,"props":11865,"children":11866},{"disabled":42,"type":11681},[],{"type":62,"value":838},{"type":49,"tag":67,"props":11869,"children":11871},{"className":11870},[],[11872],{"type":62,"value":1451},{"type":62,"value":11874}," matches the folder name and ",{"type":49,"tag":67,"props":11876,"children":11878},{"className":11877},[],[11879],{"type":62,"value":349},{"type":62,"value":11881}," file name",{"type":49,"tag":98,"props":11883,"children":11885},{"className":11884},[11676],[11886,11889,11890,11895,11896,11901],{"type":49,"tag":11679,"props":11887,"children":11888},{"disabled":42,"type":11681},[],{"type":62,"value":838},{"type":49,"tag":67,"props":11891,"children":11893},{"className":11892},[],[11894],{"type":62,"value":8815},{"type":62,"value":351},{"type":49,"tag":67,"props":11897,"children":11899},{"className":11898},[],[11900],{"type":62,"value":1465},{"type":62,"value":11902}," are populated",{"type":49,"tag":98,"props":11904,"children":11906},{"className":11905},[11676],[11907,11910],{"type":49,"tag":11679,"props":11908,"children":11909},{"disabled":42,"type":11681},[],{"type":62,"value":11911}," Fields are alphabetically sorted",{"type":49,"tag":98,"props":11913,"children":11915},{"className":11914},[11676],[11916,11919,11921,11926,11928,11933,11935,11940],{"type":49,"tag":11679,"props":11917,"children":11918},{"disabled":42,"type":11681},[],{"type":62,"value":11920}," File names match: folder name, ",{"type":49,"tag":67,"props":11922,"children":11924},{"className":11923},[],[11925],{"type":62,"value":349},{"type":62,"value":11927}," name, ",{"type":49,"tag":67,"props":11929,"children":11931},{"className":11930},[],[11932],{"type":62,"value":357},{"type":62,"value":11934}," name, and ",{"type":49,"tag":67,"props":11936,"children":11938},{"className":11937},[],[11939],{"type":62,"value":1451},{"type":62,"value":11941}," field all use the same value",{"type":49,"tag":487,"props":11943,"children":11945},{"id":11944},"_102-provide-api-url",[11946],{"type":62,"value":11947},"10.2 Provide API URL",{"type":49,"tag":54,"props":11949,"children":11950},{},[11951],{"type":62,"value":11952},"Tell the user each endpoint URL:",{"type":49,"tag":1335,"props":11954,"children":11957},{"className":11955,"code":11956,"language":62},[2706],"https:\u002F\u002F\u003Csite-url>\u002F_api\u002Fserverlogics\u002F\u003Cserver-logic-name>\n",[11958],{"type":49,"tag":67,"props":11959,"children":11960},{"__ignoreMap":1340},[11961],{"type":62,"value":11956},{"type":49,"tag":487,"props":11963,"children":11965},{"id":11964},"_103-test-guidance",[11966],{"type":62,"value":11967},"10.3 Test Guidance",{"type":49,"tag":54,"props":11969,"children":11970},{},[11971],{"type":62,"value":11972},"Provide testing instructions:",{"type":49,"tag":291,"props":11974,"children":11975},{},[11976,11993,12025,12035],{"type":49,"tag":98,"props":11977,"children":11978},{},[11979,11984,11986,11991],{"type":49,"tag":58,"props":11980,"children":11981},{},[11982],{"type":62,"value":11983},"Deploy the site first",{"type":62,"value":11985}," — The server logic must be deployed via ",{"type":49,"tag":67,"props":11987,"children":11989},{"className":11988},[],[11990],{"type":62,"value":967},{"type":62,"value":11992}," before it can be called",{"type":49,"tag":98,"props":11994,"children":11995},{},[11996,12001,12003,12009,12011,12016,12018,12023],{"type":49,"tag":58,"props":11997,"children":11998},{},[11999],{"type":62,"value":12000},"CSRF token required for non-GET requests",{"type":62,"value":12002}," — POST, PUT, PATCH, and DELETE calls to server logic endpoints require a CSRF token. Fetch the token from ",{"type":49,"tag":67,"props":12004,"children":12006},{"className":12005},[],[12007],{"type":62,"value":12008},"\u002F_layout\u002Ftokenhtml",{"type":62,"value":12010}," and include it as ",{"type":49,"tag":67,"props":12012,"children":12014},{"className":12013},[],[12015],{"type":62,"value":664},{"type":62,"value":12017}," header. GET requests are ",{"type":49,"tag":58,"props":12019,"children":12020},{},[12021],{"type":62,"value":12022},"exempt",{"type":62,"value":12024}," from antiforgery validation — no token is needed for read-only calls.",{"type":49,"tag":98,"props":12026,"children":12027},{},[12028,12033],{"type":49,"tag":58,"props":12029,"children":12030},{},[12031],{"type":62,"value":12032},"Authentication",{"type":62,"value":12034}," — Server logic respects the site's authentication. Calls from authenticated sessions use cookie-based auth automatically. Anonymous access depends on governance settings.",{"type":49,"tag":98,"props":12036,"children":12037},{},[12038,12043],{"type":49,"tag":58,"props":12039,"children":12040},{},[12041],{"type":62,"value":12042},"Testing from browser console",{"type":62,"value":468},{"type":49,"tag":54,"props":12045,"children":12046},{},[12047],{"type":62,"value":12048},"Use the frontend integration reference from Phase 9 for the exact calling pattern that matches the site's stack.",{"type":49,"tag":291,"props":12050,"children":12051},{"start":3261},[12052,12062],{"type":49,"tag":98,"props":12053,"children":12054},{},[12055,12060],{"type":49,"tag":58,"props":12056,"children":12057},{},[12058],{"type":62,"value":12059},"Check diagnostics",{"type":62,"value":12061}," — Server.Logger output can be viewed in Power Pages design studio diagnostics",{"type":49,"tag":98,"props":12063,"children":12064},{},[12065,12070,12072,12078,12080,12086],{"type":49,"tag":58,"props":12066,"children":12067},{},[12068],{"type":62,"value":12069},"If the endpoint returns an error or unexpected response",{"type":62,"value":12071}," — see ",{"type":49,"tag":478,"props":12073,"children":12075},{"href":12074},"#troubleshooting-server-logic-execution-errors",[12076],{"type":62,"value":12077},"Troubleshooting Server Logic Execution Errors",{"type":62,"value":12079}," for the Playwright + ",{"type":49,"tag":67,"props":12081,"children":12083},{"className":12082},[],[12084],{"type":62,"value":12085},"X-Ms-UserTrace",{"type":62,"value":12087}," debugging flow",{"type":49,"tag":54,"props":12089,"children":12090},{},[12091,12095],{"type":49,"tag":58,"props":12092,"children":12093},{},[12094],{"type":62,"value":993},{"type":62,"value":12096},": Code validated, API URL provided, test guidance given",{"type":49,"tag":281,"props":12098,"children":12099},{},[],{"type":49,"tag":87,"props":12101,"children":12103},{"id":12102},"phase-11-review-deploy",[12104],{"type":62,"value":12105},"Phase 11: Review & Deploy",{"type":49,"tag":54,"props":12107,"children":12108},{},[12109,12113],{"type":49,"tag":58,"props":12110,"children":12111},{},[12112],{"type":62,"value":456},{"type":62,"value":12114},": Present a summary of all work performed and offer deployment",{"type":49,"tag":54,"props":12116,"children":12117},{},[12118,12122],{"type":49,"tag":58,"props":12119,"children":12120},{},[12121],{"type":62,"value":466},{"type":62,"value":468},{"type":49,"tag":487,"props":12124,"children":12126},{"id":12125},"_111-record-skill-usage",[12127],{"type":62,"value":12128},"11.1 Record Skill Usage",{"type":49,"tag":50,"props":12130,"children":12131},{},[12132],{"type":49,"tag":54,"props":12133,"children":12134},{},[12135,12136],{"type":62,"value":2476},{"type":49,"tag":67,"props":12137,"children":12139},{"className":12138},[],[12140],{"type":62,"value":12141},"${PLUGIN_ROOT}\u002Freferences\u002Fskill-tracking-reference.md",{"type":49,"tag":54,"props":12143,"children":12144},{},[12145,12147,12153],{"type":62,"value":12146},"Follow the skill tracking instructions in the reference to record this skill's usage. Use ",{"type":49,"tag":67,"props":12148,"children":12150},{"className":12149},[],[12151],{"type":62,"value":12152},"--skillName \"AddServerLogic\"",{"type":62,"value":523},{"type":49,"tag":487,"props":12155,"children":12157},{"id":12156},"_112-present-summary",[12158],{"type":62,"value":12159},"11.2 Present Summary",{"type":49,"tag":54,"props":12161,"children":12162},{},[12163],{"type":62,"value":12164},"Present a summary of everything that was done:",{"type":49,"tag":905,"props":12166,"children":12167},{},[12168,12189],{"type":49,"tag":909,"props":12169,"children":12170},{},[12171],{"type":49,"tag":913,"props":12172,"children":12173},{},[12174,12179,12184],{"type":49,"tag":917,"props":12175,"children":12176},{},[12177],{"type":62,"value":12178},"Step",{"type":49,"tag":917,"props":12180,"children":12181},{},[12182],{"type":62,"value":12183},"Status",{"type":49,"tag":917,"props":12185,"children":12186},{},[12187],{"type":62,"value":12188},"Details",{"type":49,"tag":928,"props":12190,"children":12191},{},[12192,12218,12241,12259,12277,12294,12324,12346,12363,12380,12397],{"type":49,"tag":913,"props":12193,"children":12194},{},[12195,12200,12205],{"type":49,"tag":935,"props":12196,"children":12197},{},[12198],{"type":62,"value":12199},"Server Logic JS",{"type":49,"tag":935,"props":12201,"children":12202},{},[12203],{"type":62,"value":12204},"Created",{"type":49,"tag":935,"props":12206,"children":12207},{},[12208,12210,12216],{"type":62,"value":12209},"List each created ",{"type":49,"tag":67,"props":12211,"children":12213},{"className":12212},[],[12214],{"type":62,"value":12215},".powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F\u003Cname>.js",{"type":62,"value":12217}," file",{"type":49,"tag":913,"props":12219,"children":12220},{},[12221,12226,12230],{"type":49,"tag":935,"props":12222,"children":12223},{},[12224],{"type":62,"value":12225},"Server Logic YAML",{"type":49,"tag":935,"props":12227,"children":12228},{},[12229],{"type":62,"value":12204},{"type":49,"tag":935,"props":12231,"children":12232},{},[12233,12234,12240],{"type":62,"value":12209},{"type":49,"tag":67,"props":12235,"children":12237},{"className":12236},[],[12238],{"type":62,"value":12239},".powerpages-site\u002Fserver-logic\u002F\u003Cname>\u002F\u003Cname>.serverlogic.yml",{"type":62,"value":12217},{"type":49,"tag":913,"props":12242,"children":12243},{},[12244,12249,12254],{"type":49,"tag":935,"props":12245,"children":12246},{},[12247],{"type":62,"value":12248},"HTML Plan",{"type":49,"tag":935,"props":12250,"children":12251},{},[12252],{"type":62,"value":12253},"Created\u002FUpdated",{"type":49,"tag":935,"props":12255,"children":12256},{},[12257],{"type":62,"value":12258},"Actual path from render script output",{"type":49,"tag":913,"props":12260,"children":12261},{},[12262,12267,12272],{"type":49,"tag":935,"props":12263,"children":12264},{},[12265],{"type":62,"value":12266},"Functions",{"type":49,"tag":935,"props":12268,"children":12269},{},[12270],{"type":62,"value":12271},"Implemented",{"type":49,"tag":935,"props":12273,"children":12274},{},[12275],{"type":62,"value":12276},"Summarize methods implemented per server logic item",{"type":49,"tag":913,"props":12278,"children":12279},{},[12280,12285,12289],{"type":49,"tag":935,"props":12281,"children":12282},{},[12283],{"type":62,"value":12284},"SDK Features Used",{"type":49,"tag":935,"props":12286,"children":12287},{},[12288],{"type":62,"value":9480},{"type":49,"tag":935,"props":12290,"children":12291},{},[12292],{"type":62,"value":12293},"Summarize features used per server logic item",{"type":49,"tag":913,"props":12295,"children":12296},{},[12297,12302,12307],{"type":49,"tag":935,"props":12298,"children":12299},{},[12300],{"type":62,"value":12301},"Table Permissions",{"type":49,"tag":935,"props":12303,"children":12304},{},[12305],{"type":62,"value":12306},"Created\u002FSkipped",{"type":49,"tag":935,"props":12308,"children":12309},{},[12310,12315,12317,12322],{"type":49,"tag":67,"props":12311,"children":12313},{"className":12312},[],[12314],{"type":62,"value":9471},{"type":62,"value":12316}," (Read), ",{"type":49,"tag":67,"props":12318,"children":12320},{"className":12319},[],[12321],{"type":62,"value":9500},{"type":62,"value":12323}," (Read, Create), etc.",{"type":49,"tag":913,"props":12325,"children":12326},{},[12327,12332,12336],{"type":49,"tag":935,"props":12328,"children":12329},{},[12330],{"type":62,"value":12331},"Secrets & Env Vars",{"type":49,"tag":935,"props":12333,"children":12334},{},[12335],{"type":62,"value":12306},{"type":49,"tag":935,"props":12337,"children":12338},{},[12339,12341],{"type":62,"value":12340},"Environment variables (Key Vault-backed or direct), site settings with ",{"type":49,"tag":67,"props":12342,"children":12344},{"className":12343},[],[12345],{"type":62,"value":10605},{"type":49,"tag":913,"props":12347,"children":12348},{},[12349,12354,12358],{"type":49,"tag":935,"props":12350,"children":12351},{},[12352],{"type":62,"value":12353},"Site Settings",{"type":49,"tag":935,"props":12355,"children":12356},{},[12357],{"type":62,"value":12306},{"type":49,"tag":935,"props":12359,"children":12360},{},[12361],{"type":62,"value":12362},"ServerLogic\u002FAllowedDomains, etc.",{"type":49,"tag":913,"props":12364,"children":12365},{},[12366,12371,12375],{"type":49,"tag":935,"props":12367,"children":12368},{},[12369],{"type":62,"value":12370},"Client-Side Service",{"type":49,"tag":935,"props":12372,"children":12373},{},[12374],{"type":62,"value":12306},{"type":49,"tag":935,"props":12376,"children":12377},{},[12378],{"type":62,"value":12379},"List created or updated frontend service files",{"type":49,"tag":913,"props":12381,"children":12382},{},[12383,12388,12392],{"type":49,"tag":935,"props":12384,"children":12385},{},[12386],{"type":62,"value":12387},"UI Integration",{"type":49,"tag":935,"props":12389,"children":12390},{},[12391],{"type":62,"value":12306},{"type":49,"tag":935,"props":12393,"children":12394},{},[12395],{"type":62,"value":12396},"Pages, components, forms, or actions fully wired to the server logic endpoints",{"type":49,"tag":913,"props":12398,"children":12399},{},[12400,12405,12409],{"type":49,"tag":935,"props":12401,"children":12402},{},[12403],{"type":62,"value":12404},"API URL",{"type":49,"tag":935,"props":12406,"children":12407},{},[12408],{"type":62,"value":9480},{"type":49,"tag":935,"props":12410,"children":12411},{},[12412,12414,12419],{"type":62,"value":12413},"List each ",{"type":49,"tag":67,"props":12415,"children":12417},{"className":12416},[],[12418],{"type":62,"value":6082},{"type":62,"value":12420}," URL",{"type":49,"tag":487,"props":12422,"children":12424},{"id":12423},"_113-ask-to-deploy",[12425],{"type":62,"value":12426},"11.3 Ask to Deploy",{"type":49,"tag":50,"props":12428,"children":12429},{},[12430,12441],{"type":49,"tag":54,"props":12431,"children":12432},{},[12433,12434,12439],{"type":62,"value":831},{"type":49,"tag":58,"props":12435,"children":12436},{},[12437],{"type":62,"value":12438},"Gate (plan · add-server-logic:11.3.deploy):",{"type":62,"value":12440}," Post-implementation deploy prompt — server logic endpoints aren't reachable until deployed.",{"type":49,"tag":54,"props":12442,"children":12443},{},[12444,12448,12450,12454,12456,12460],{"type":49,"tag":58,"props":12445,"children":12446},{},[12447],{"type":62,"value":853},{"type":62,"value":12449}," All server logic artifacts written and committed.\n",{"type":49,"tag":58,"props":12451,"children":12452},{},[12453],{"type":62,"value":867},{"type":62,"value":12455}," Auto-deploy picks wrong env.\n",{"type":49,"tag":58,"props":12457,"children":12458},{},[12459],{"type":62,"value":889},{"type":62,"value":12461}," Nothing — artifacts stay on disk; no deploy fired.",{"type":49,"tag":54,"props":12463,"children":12464},{},[12465,12466,12471],{"type":62,"value":896},{"type":49,"tag":67,"props":12467,"children":12469},{"className":12468},[],[12470],{"type":62,"value":902},{"type":62,"value":468},{"type":49,"tag":905,"props":12473,"children":12474},{},[12475,12489],{"type":49,"tag":909,"props":12476,"children":12477},{},[12478],{"type":49,"tag":913,"props":12479,"children":12480},{},[12481,12485],{"type":49,"tag":917,"props":12482,"children":12483},{},[12484],{"type":62,"value":921},{"type":49,"tag":917,"props":12486,"children":12487},{},[12488],{"type":62,"value":926},{"type":49,"tag":928,"props":12490,"children":12491},{},[12492],{"type":49,"tag":913,"props":12493,"children":12494},{},[12495,12500],{"type":49,"tag":935,"props":12496,"children":12497},{},[12498],{"type":62,"value":12499},"The server logic work is ready. To make it live, the site needs to be deployed. Would you like to deploy now?",{"type":49,"tag":935,"props":12501,"children":12502},{},[12503],{"type":62,"value":12504},"Yes, deploy now (Recommended), No, I'll deploy later",{"type":49,"tag":50,"props":12506,"children":12507},{},[12508,12526],{"type":49,"tag":54,"props":12509,"children":12510},{},[12511,12512,12517,12519,12524],{"type":62,"value":831},{"type":49,"tag":58,"props":12513,"children":12514},{},[12515],{"type":62,"value":12516},"Gate (plan · add-server-logic:11.3.test):",{"type":62,"value":12518}," Post-deploy validation prompt — invokes ",{"type":49,"tag":67,"props":12520,"children":12522},{"className":12521},[],[12523],{"type":62,"value":11596},{"type":62,"value":12525}," to exercise the new endpoints live.",{"type":49,"tag":54,"props":12527,"children":12528},{},[12529,12533,12535,12539,12541,12546,12548,12552],{"type":49,"tag":58,"props":12530,"children":12531},{},[12532],{"type":62,"value":853},{"type":62,"value":12534}," Deploy from the previous gate succeeded.\n",{"type":49,"tag":58,"props":12536,"children":12537},{},[12538],{"type":62,"value":867},{"type":62,"value":12540}," Skipping is harmless (manual test still possible); auto-invoking ",{"type":49,"tag":67,"props":12542,"children":12544},{"className":12543},[],[12545],{"type":62,"value":11596},{"type":62,"value":12547}," adds runtime.\n",{"type":49,"tag":58,"props":12549,"children":12550},{},[12551],{"type":62,"value":889},{"type":62,"value":12553}," Nothing — deploy has already completed.",{"type":49,"tag":54,"props":12555,"children":12556},{},[12557,12561,12563,12568],{"type":49,"tag":58,"props":12558,"children":12559},{},[12560],{"type":62,"value":959},{"type":62,"value":12562},": Invoke the ",{"type":49,"tag":67,"props":12564,"children":12566},{"className":12565},[],[12567],{"type":62,"value":967},{"type":62,"value":12569}," skill to deploy the site.",{"type":49,"tag":54,"props":12571,"children":12572},{},[12573,12575,12580],{"type":62,"value":12574},"After deployment succeeds, use ",{"type":49,"tag":67,"props":12576,"children":12578},{"className":12577},[],[12579],{"type":62,"value":902},{"type":62,"value":468},{"type":49,"tag":905,"props":12582,"children":12583},{},[12584,12598],{"type":49,"tag":909,"props":12585,"children":12586},{},[12587],{"type":49,"tag":913,"props":12588,"children":12589},{},[12590,12594],{"type":49,"tag":917,"props":12591,"children":12592},{},[12593],{"type":62,"value":921},{"type":49,"tag":917,"props":12595,"children":12596},{},[12597],{"type":62,"value":926},{"type":49,"tag":928,"props":12599,"children":12600},{},[12601],{"type":49,"tag":913,"props":12602,"children":12603},{},[12604,12616],{"type":49,"tag":935,"props":12605,"children":12606},{},[12607,12609,12614],{"type":62,"value":12608},"The site has been deployed. Would you like me to run ",{"type":49,"tag":67,"props":12610,"children":12612},{"className":12611},[],[12613],{"type":62,"value":11596},{"type":62,"value":12615}," to validate it now?",{"type":49,"tag":935,"props":12617,"children":12618},{},[12619,12621,12626],{"type":62,"value":12620},"Yes, run ",{"type":49,"tag":67,"props":12622,"children":12624},{"className":12623},[],[12625],{"type":62,"value":11596},{"type":62,"value":12627}," (Recommended), No, skip testing",{"type":49,"tag":54,"props":12629,"children":12630},{},[12631,12642,12643,12648],{"type":49,"tag":58,"props":12632,"children":12633},{},[12634,12636,12641],{"type":62,"value":12635},"If \"Yes, run ",{"type":49,"tag":67,"props":12637,"children":12639},{"className":12638},[],[12640],{"type":62,"value":11596},{"type":62,"value":1384},{"type":62,"value":12562},{"type":49,"tag":67,"props":12644,"children":12646},{"className":12645},[],[12647],{"type":62,"value":11596},{"type":62,"value":12649}," skill.",{"type":49,"tag":54,"props":12651,"children":12652},{},[12653,12658],{"type":49,"tag":58,"props":12654,"children":12655},{},[12656],{"type":62,"value":12657},"If \"No, I'll deploy later\"",{"type":62,"value":12659},": Acknowledge and remind:",{"type":49,"tag":50,"props":12661,"children":12662},{},[12663],{"type":49,"tag":54,"props":12664,"children":12665},{},[12666,12668,12673],{"type":62,"value":12667},"\"No problem! Remember to deploy your site using ",{"type":49,"tag":67,"props":12669,"children":12671},{"className":12670},[],[12672],{"type":62,"value":967},{"type":62,"value":12674}," when you're ready. The server logic endpoints won't be accessible until the site is deployed.\"",{"type":49,"tag":487,"props":12676,"children":12678},{"id":12677},"_114-post-deploy-notes",[12679],{"type":62,"value":12680},"11.4 Post-Deploy Notes",{"type":49,"tag":54,"props":12682,"children":12683},{},[12684],{"type":62,"value":12685},"After deployment (or if skipped), remind the user:",{"type":49,"tag":94,"props":12687,"children":12688},{},[12689,12706,12723,12733,12750,12760,12770,12780],{"type":49,"tag":98,"props":12690,"children":12691},{},[12692,12697,12699,12704],{"type":49,"tag":58,"props":12693,"children":12694},{},[12695],{"type":62,"value":12696},"Test the endpoints",{"type":62,"value":12698},": Call each ",{"type":49,"tag":67,"props":12700,"children":12702},{"className":12701},[],[12703],{"type":62,"value":6082},{"type":62,"value":12705}," URL with the appropriate HTTP method (include CSRF token for non-GET requests)",{"type":49,"tag":98,"props":12707,"children":12708},{},[12709,12714,12716,12721],{"type":49,"tag":58,"props":12710,"children":12711},{},[12712],{"type":62,"value":12713},"Recommended full-site validation",{"type":62,"value":12715},": After deployment, ask whether to run ",{"type":49,"tag":67,"props":12717,"children":12719},{"className":12718},[],[12720],{"type":62,"value":11596},{"type":62,"value":12722}," so the live site can be validated end to end",{"type":49,"tag":98,"props":12724,"children":12725},{},[12726,12731],{"type":49,"tag":58,"props":12727,"children":12728},{},[12729],{"type":62,"value":12730},"Check logs",{"type":62,"value":12732},": Use Server.Logger output in Power Pages design studio diagnostics to debug issues",{"type":49,"tag":98,"props":12734,"children":12735},{},[12736,12741,12743,12748],{"type":49,"tag":58,"props":12737,"children":12738},{},[12739],{"type":62,"value":12740},"Table permissions",{"type":62,"value":12742},": Table permissions were configured for Dataverse tables used by this server logic. If you add new Dataverse tables later, run the table permissions setup again — without permissions, ",{"type":49,"tag":67,"props":12744,"children":12746},{"className":12745},[],[12747],{"type":62,"value":1904},{"type":62,"value":12749}," silently returns 0 records",{"type":49,"tag":98,"props":12751,"children":12752},{},[12753,12758],{"type":49,"tag":58,"props":12754,"children":12755},{},[12756],{"type":62,"value":12757},"Timeout",{"type":62,"value":12759},": Default execution timeout is 120 seconds — this is also the platform maximum (values above 120 are silently clamped)",{"type":49,"tag":98,"props":12761,"children":12762},{},[12763,12768],{"type":49,"tag":58,"props":12764,"children":12765},{},[12766],{"type":62,"value":12767},"Anonymous access",{"type":62,"value":12769},": If the site's governance control disables anonymous access, anonymous users cannot invoke server logic that integrates with external systems",{"type":49,"tag":98,"props":12771,"children":12772},{},[12773,12778],{"type":49,"tag":58,"props":12774,"children":12775},{},[12776],{"type":62,"value":12777},"Preview feature",{"type":62,"value":12779},": Server Logic is currently in preview — monitor Microsoft Learn for updates",{"type":49,"tag":98,"props":12781,"children":12782},{},[12783,12788,12790],{"type":49,"tag":58,"props":12784,"children":12785},{},[12786],{"type":62,"value":12787},"Environment variables with placeholder values",{"type":62,"value":12789},": If Phase 7 created environment variables with placeholder values, remind the user to update them with the actual secret values before testing. They can do this via:\n",{"type":49,"tag":291,"props":12791,"children":12792},{},[12793,12815],{"type":49,"tag":98,"props":12794,"children":12795},{},[12796,12801,12802,12807,12809,12813],{"type":49,"tag":58,"props":12797,"children":12798},{},[12799],{"type":62,"value":12800},"Power Platform admin center",{"type":62,"value":375},{"type":49,"tag":58,"props":12803,"children":12804},{},[12805],{"type":62,"value":12806},"Environments",{"type":62,"value":12808}," → select environment → ",{"type":49,"tag":58,"props":12810,"children":12811},{},[12812],{"type":62,"value":10923},{"type":62,"value":12814}," → find by display name → update value",{"type":49,"tag":98,"props":12816,"children":12817},{},[12818,12822,12823,12827,12829,12833],{"type":49,"tag":58,"props":12819,"children":12820},{},[12821],{"type":62,"value":10895},{"type":62,"value":375},{"type":49,"tag":58,"props":12824,"children":12825},{},[12826],{"type":62,"value":10911},{"type":62,"value":12828}," → open solution → ",{"type":49,"tag":58,"props":12830,"children":12831},{},[12832],{"type":62,"value":10923},{"type":62,"value":12834}," → edit value",{"type":49,"tag":54,"props":12836,"children":12837},{},[12838,12842],{"type":49,"tag":58,"props":12839,"children":12840},{},[12841],{"type":62,"value":993},{"type":62,"value":12843},": Summary presented, deployment completed or deferred, post-deploy guidance provided",{"type":49,"tag":281,"props":12845,"children":12846},{},[],{"type":49,"tag":87,"props":12848,"children":12850},{"id":12849},"troubleshooting-server-logic-execution-errors",[12851],{"type":62,"value":12077},{"type":49,"tag":54,"props":12853,"children":12854},{},[12855,12857,12862],{"type":62,"value":12856},"When a deployed server logic endpoint returns an error or unexpected response, the underlying cause is usually hidden inside the ",{"type":49,"tag":67,"props":12858,"children":12860},{"className":12859},[],[12861],{"type":62,"value":12085},{"type":62,"value":12863}," response header — a base64-encoded blob containing the runtime diagnostic logs. The Power Pages Edge browser extension shows the same data, but inspecting the response header is the fastest path when iterating against a live site.",{"type":49,"tag":54,"props":12865,"children":12866},{},[12867],{"type":62,"value":12868},"Use this flow whenever a server logic call fails or returns a different response than expected:",{"type":49,"tag":487,"props":12870,"children":12872},{"id":12871},"_1-open-the-live-site-in-a-browser-via-playwright",[12873],{"type":62,"value":12874},"1. Open the Live Site in a Browser via Playwright",{"type":49,"tag":54,"props":12876,"children":12877},{},[12878],{"type":62,"value":12879},"Use the Playwright MCP tools to drive the site:",{"type":49,"tag":291,"props":12881,"children":12882},{},[12883,12904,12909],{"type":49,"tag":98,"props":12884,"children":12885},{},[12886,12888,12894,12896,12902],{"type":62,"value":12887},"Navigate to the deployed site URL (the ",{"type":49,"tag":67,"props":12889,"children":12891},{"className":12890},[],[12892],{"type":62,"value":12893},"websiteUrl",{"type":62,"value":12895}," returned by ",{"type":49,"tag":67,"props":12897,"children":12899},{"className":12898},[],[12900],{"type":62,"value":12901},"\u002Factivate-site",{"type":62,"value":12903}," or shown in the Power Pages admin center).",{"type":49,"tag":98,"props":12905,"children":12906},{},[12907],{"type":62,"value":12908},"Ask the user to sign in if the endpoint requires authentication and wait for confirmation.",{"type":49,"tag":98,"props":12910,"children":12911},{},[12912,12914,12920],{"type":62,"value":12913},"Trigger the action that calls the failing server logic endpoint (click the button, submit the form, etc.) — or call the endpoint directly with ",{"type":49,"tag":67,"props":12915,"children":12917},{"className":12916},[],[12918],{"type":62,"value":12919},"fetch()",{"type":62,"value":523},{"type":49,"tag":487,"props":12922,"children":12924},{"id":12923},"_2-capture-the-network-response",[12925],{"type":62,"value":12926},"2. Capture the Network Response",{"type":49,"tag":54,"props":12928,"children":12929},{},[12930,12931,12937,12939,12944],{"type":62,"value":896},{"type":49,"tag":67,"props":12932,"children":12934},{"className":12933},[],[12935],{"type":62,"value":12936},"mcp__plugin_power-pages_playwright__browser_network_requests",{"type":62,"value":12938}," to list network activity, then locate the request to ",{"type":49,"tag":67,"props":12940,"children":12942},{"className":12941},[],[12943],{"type":62,"value":6082},{"type":62,"value":12945},". Note:",{"type":49,"tag":94,"props":12947,"children":12948},{},[12949,12954,12959],{"type":49,"tag":98,"props":12950,"children":12951},{},[12952],{"type":62,"value":12953},"The HTTP status code (e.g., 200, 400, 500)",{"type":49,"tag":98,"props":12955,"children":12956},{},[12957],{"type":62,"value":12958},"The response body (often a generic error or empty payload when validation fails)",{"type":49,"tag":98,"props":12960,"children":12961},{},[12962,12974],{"type":49,"tag":58,"props":12963,"children":12964},{},[12965,12967,12972],{"type":62,"value":12966},"Most importantly: the ",{"type":49,"tag":67,"props":12968,"children":12970},{"className":12969},[],[12971],{"type":62,"value":12085},{"type":62,"value":12973}," response header",{"type":62,"value":12975}," — this is where the actual diagnostic logs live",{"type":49,"tag":54,"props":12977,"children":12978},{},[12979,12980,12986,12988,12994,12996,13001],{"type":62,"value":9907},{"type":49,"tag":67,"props":12981,"children":12983},{"className":12982},[],[12984],{"type":62,"value":12985},"browser_network_requests",{"type":62,"value":12987}," does not surface the response headers directly, fall back to ",{"type":49,"tag":67,"props":12989,"children":12991},{"className":12990},[],[12992],{"type":62,"value":12993},"mcp__plugin_power-pages_playwright__browser_evaluate",{"type":62,"value":12995}," and read the headers from a ",{"type":49,"tag":67,"props":12997,"children":12999},{"className":12998},[],[13000],{"type":62,"value":12919},{"type":62,"value":13002}," call:",{"type":49,"tag":1335,"props":13004,"children":13006},{"className":3722,"code":13005,"language":18,"meta":1340,"style":1340},"const res = await fetch('\u002F_api\u002Fserverlogics\u002F\u003Cname>', { method: 'GET', credentials: 'include' });\nconst trace = res.headers.get('X-Ms-UserTrace');\nreturn { status: res.status, body: await res.text(), trace };\n",[13007],{"type":49,"tag":67,"props":13008,"children":13009},{"__ignoreMap":1340},[13010,13123,13185],{"type":49,"tag":1346,"props":13011,"children":13012},{"class":1348,"line":1349},[13013,13017,13022,13026,13031,13036,13040,13045,13049,13053,13057,13062,13067,13071,13076,13080,13084,13088,13093,13097,13101,13106,13110,13115,13119],{"type":49,"tag":1346,"props":13014,"children":13015},{"style":3742},[13016],{"type":62,"value":8482},{"type":49,"tag":1346,"props":13018,"children":13019},{"style":1365},[13020],{"type":62,"value":13021}," res ",{"type":49,"tag":1346,"props":13023,"children":13024},{"style":1359},[13025],{"type":62,"value":3755},{"type":49,"tag":1346,"props":13027,"children":13028},{"style":3937},[13029],{"type":62,"value":13030}," await",{"type":49,"tag":1346,"props":13032,"children":13033},{"style":3917},[13034],{"type":62,"value":13035}," fetch",{"type":49,"tag":1346,"props":13037,"children":13038},{"style":1365},[13039],{"type":62,"value":3976},{"type":49,"tag":1346,"props":13041,"children":13042},{"style":1359},[13043],{"type":62,"value":13044},"'",{"type":49,"tag":1346,"props":13046,"children":13047},{"style":1376},[13048],{"type":62,"value":6082},{"type":49,"tag":1346,"props":13050,"children":13051},{"style":1359},[13052],{"type":62,"value":13044},{"type":49,"tag":1346,"props":13054,"children":13055},{"style":1359},[13056],{"type":62,"value":4798},{"type":49,"tag":1346,"props":13058,"children":13059},{"style":1359},[13060],{"type":62,"value":13061}," {",{"type":49,"tag":1346,"props":13063,"children":13064},{"style":3192},[13065],{"type":62,"value":13066}," method",{"type":49,"tag":1346,"props":13068,"children":13069},{"style":1359},[13070],{"type":62,"value":468},{"type":49,"tag":1346,"props":13072,"children":13073},{"style":1359},[13074],{"type":62,"value":13075}," '",{"type":49,"tag":1346,"props":13077,"children":13078},{"style":1376},[13079],{"type":62,"value":1818},{"type":49,"tag":1346,"props":13081,"children":13082},{"style":1359},[13083],{"type":62,"value":13044},{"type":49,"tag":1346,"props":13085,"children":13086},{"style":1359},[13087],{"type":62,"value":4798},{"type":49,"tag":1346,"props":13089,"children":13090},{"style":3192},[13091],{"type":62,"value":13092}," credentials",{"type":49,"tag":1346,"props":13094,"children":13095},{"style":1359},[13096],{"type":62,"value":468},{"type":49,"tag":1346,"props":13098,"children":13099},{"style":1359},[13100],{"type":62,"value":13075},{"type":49,"tag":1346,"props":13102,"children":13103},{"style":1376},[13104],{"type":62,"value":13105},"include",{"type":49,"tag":1346,"props":13107,"children":13108},{"style":1359},[13109],{"type":62,"value":13044},{"type":49,"tag":1346,"props":13111,"children":13112},{"style":1359},[13113],{"type":62,"value":13114}," }",{"type":49,"tag":1346,"props":13116,"children":13117},{"style":1365},[13118],{"type":62,"value":1113},{"type":49,"tag":1346,"props":13120,"children":13121},{"style":1359},[13122],{"type":62,"value":3773},{"type":49,"tag":1346,"props":13124,"children":13125},{"class":1348,"line":3208},[13126,13130,13135,13139,13144,13148,13153,13157,13161,13165,13169,13173,13177,13181],{"type":49,"tag":1346,"props":13127,"children":13128},{"style":3742},[13129],{"type":62,"value":8482},{"type":49,"tag":1346,"props":13131,"children":13132},{"style":1365},[13133],{"type":62,"value":13134}," trace ",{"type":49,"tag":1346,"props":13136,"children":13137},{"style":1359},[13138],{"type":62,"value":3755},{"type":49,"tag":1346,"props":13140,"children":13141},{"style":1365},[13142],{"type":62,"value":13143}," res",{"type":49,"tag":1346,"props":13145,"children":13146},{"style":1359},[13147],{"type":62,"value":523},{"type":49,"tag":1346,"props":13149,"children":13150},{"style":1365},[13151],{"type":62,"value":13152},"headers",{"type":49,"tag":1346,"props":13154,"children":13155},{"style":1359},[13156],{"type":62,"value":523},{"type":49,"tag":1346,"props":13158,"children":13159},{"style":3917},[13160],{"type":62,"value":156},{"type":49,"tag":1346,"props":13162,"children":13163},{"style":1365},[13164],{"type":62,"value":3976},{"type":49,"tag":1346,"props":13166,"children":13167},{"style":1359},[13168],{"type":62,"value":13044},{"type":49,"tag":1346,"props":13170,"children":13171},{"style":1376},[13172],{"type":62,"value":12085},{"type":49,"tag":1346,"props":13174,"children":13175},{"style":1359},[13176],{"type":62,"value":13044},{"type":49,"tag":1346,"props":13178,"children":13179},{"style":1365},[13180],{"type":62,"value":1113},{"type":49,"tag":1346,"props":13182,"children":13183},{"style":1359},[13184],{"type":62,"value":3773},{"type":49,"tag":1346,"props":13186,"children":13187},{"class":1348,"line":3226},[13188,13193,13197,13202,13206,13210,13214,13219,13223,13227,13231,13235,13239,13243,13247,13251,13255,13259],{"type":49,"tag":1346,"props":13189,"children":13190},{"style":3937},[13191],{"type":62,"value":13192},"return",{"type":49,"tag":1346,"props":13194,"children":13195},{"style":1359},[13196],{"type":62,"value":13061},{"type":49,"tag":1346,"props":13198,"children":13199},{"style":3192},[13200],{"type":62,"value":13201}," status",{"type":49,"tag":1346,"props":13203,"children":13204},{"style":1359},[13205],{"type":62,"value":468},{"type":49,"tag":1346,"props":13207,"children":13208},{"style":1365},[13209],{"type":62,"value":13143},{"type":49,"tag":1346,"props":13211,"children":13212},{"style":1359},[13213],{"type":62,"value":523},{"type":49,"tag":1346,"props":13215,"children":13216},{"style":1365},[13217],{"type":62,"value":13218},"status",{"type":49,"tag":1346,"props":13220,"children":13221},{"style":1359},[13222],{"type":62,"value":4798},{"type":49,"tag":1346,"props":13224,"children":13225},{"style":3192},[13226],{"type":62,"value":4595},{"type":49,"tag":1346,"props":13228,"children":13229},{"style":1359},[13230],{"type":62,"value":468},{"type":49,"tag":1346,"props":13232,"children":13233},{"style":3937},[13234],{"type":62,"value":13030},{"type":49,"tag":1346,"props":13236,"children":13237},{"style":1365},[13238],{"type":62,"value":13143},{"type":49,"tag":1346,"props":13240,"children":13241},{"style":1359},[13242],{"type":62,"value":523},{"type":49,"tag":1346,"props":13244,"children":13245},{"style":3917},[13246],{"type":62,"value":62},{"type":49,"tag":1346,"props":13248,"children":13249},{"style":1365},[13250],{"type":62,"value":3925},{"type":49,"tag":1346,"props":13252,"children":13253},{"style":1359},[13254],{"type":62,"value":4798},{"type":49,"tag":1346,"props":13256,"children":13257},{"style":1365},[13258],{"type":62,"value":13134},{"type":49,"tag":1346,"props":13260,"children":13261},{"style":1359},[13262],{"type":62,"value":13263},"};\n",{"type":49,"tag":487,"props":13265,"children":13267},{"id":13266},"_3-decode-the-x-ms-usertrace-header",[13268,13270,13275],{"type":62,"value":13269},"3. Decode the ",{"type":49,"tag":67,"props":13271,"children":13273},{"className":13272},[],[13274],{"type":62,"value":12085},{"type":62,"value":13276}," Header",{"type":49,"tag":54,"props":13278,"children":13279},{},[13280],{"type":62,"value":13281},"The header value is base64-encoded JSON. Decode it.",{"type":49,"tag":54,"props":13283,"children":13284},{},[13285],{"type":62,"value":13286},"The decoded payload contains the diagnostic log entries — including the actual error message, the prohibited pattern (if script validation failed).",{"type":49,"tag":54,"props":13288,"children":13289},{},[13290,13292,13297],{"type":62,"value":13291},"After fixing, redeploy via ",{"type":49,"tag":67,"props":13293,"children":13295},{"className":13294},[],[13296],{"type":62,"value":967},{"type":62,"value":13298}," and restart the site so the change is picked up immediately.",{"type":49,"tag":281,"props":13300,"children":13301},{},[],{"type":49,"tag":87,"props":13303,"children":13305},{"id":13304},"important-notes",[13306],{"type":62,"value":13307},"Important Notes",{"type":49,"tag":487,"props":13309,"children":13311},{"id":13310},"throughout-all-phases",[13312],{"type":62,"value":13313},"Throughout All Phases",{"type":49,"tag":94,"props":13315,"children":13316},{},[13317,13326,13336,13346,13356],{"type":49,"tag":98,"props":13318,"children":13319},{},[13320,13324],{"type":49,"tag":58,"props":13321,"children":13322},{},[13323],{"type":62,"value":220},{"type":62,"value":13325}," to track progress at every phase",{"type":49,"tag":98,"props":13327,"children":13328},{},[13329,13334],{"type":49,"tag":58,"props":13330,"children":13331},{},[13332],{"type":62,"value":13333},"Always fetch Microsoft Learn docs",{"type":62,"value":13335}," in Phase 3 before writing code — the docs are the source of truth",{"type":49,"tag":98,"props":13337,"children":13338},{},[13339,13344],{"type":49,"tag":58,"props":13340,"children":13341},{},[13342],{"type":62,"value":13343},"Ask for user confirmation",{"type":62,"value":13345}," at key decision points",{"type":49,"tag":98,"props":13347,"children":13348},{},[13349,13354],{"type":49,"tag":58,"props":13350,"children":13351},{},[13352],{"type":62,"value":13353},"Commit at milestones",{"type":62,"value":13355}," — after server logic code, table permissions (if any), secrets\u002Fenvironment variables (if any), site settings, and frontend integration (if any)",{"type":49,"tag":98,"props":13357,"children":13358},{},[13359,13364],{"type":49,"tag":58,"props":13360,"children":13361},{},[13362],{"type":62,"value":13363},"Validate thoroughly",{"type":62,"value":13365}," — server logic has strict constraints and violations cause runtime errors",{"type":49,"tag":487,"props":13367,"children":13369},{"id":13368},"key-decision-points-wait-for-user",[13370],{"type":62,"value":13371},"Key Decision Points (Wait for User)",{"type":49,"tag":291,"props":13373,"children":13374},{},[13375,13387,13392,13397,13402,13414,13419,13424,13429],{"type":49,"tag":98,"props":13376,"children":13377},{},[13378,13380,13385],{"type":62,"value":13379},"At Phase 1.5: Deploy now or cancel (if ",{"type":49,"tag":67,"props":13381,"children":13383},{"className":13382},[],[13384],{"type":62,"value":259},{"type":62,"value":13386}," missing — mandatory)",{"type":49,"tag":98,"props":13388,"children":13389},{},[13390],{"type":62,"value":13391},"At Phase 2.1.2: Use existing Dataverse custom actions or build from scratch (if custom actions found)",{"type":49,"tag":98,"props":13393,"children":13394},{},[13395],{"type":62,"value":13396},"At Phase 2: Confirm requirements (purpose, name, HTTP methods, secrets)",{"type":49,"tag":98,"props":13398,"children":13399},{},[13400],{"type":62,"value":13401},"At Phase 4: Approve implementation plan before writing code",{"type":49,"tag":98,"props":13403,"children":13404},{},[13405,13407,13412],{"type":62,"value":13406},"At Phase 6.2: Review and approve the ",{"type":49,"tag":67,"props":13408,"children":13410},{"className":13409},[],[13411],{"type":62,"value":9540},{"type":62,"value":13413}," plan (if Dataverse connector is used)",{"type":49,"tag":98,"props":13415,"children":13416},{},[13417],{"type":62,"value":13418},"At Phase 2.3.1: Choose Azure Key Vault or direct environment variable (if secrets needed)",{"type":49,"tag":98,"props":13420,"children":13421},{},[13422],{"type":62,"value":13423},"At Phase 7.2a Step 2: Create a new Key Vault or fall back to direct environment variable (if no vaults found)",{"type":49,"tag":98,"props":13425,"children":13426},{},[13427],{"type":62,"value":13428},"At Phase 9.1: Create frontend integration or skip",{"type":49,"tag":98,"props":13430,"children":13431},{},[13432],{"type":62,"value":13433},"At Phase 11.3: Deploy now or deploy later",{"type":49,"tag":487,"props":13435,"children":13437},{"id":13436},"sdk-pattern-source-of-truth",[13438],{"type":62,"value":13439},"SDK Pattern Source of Truth",{"type":49,"tag":54,"props":13441,"children":13442},{},[13443],{"type":62,"value":13444},"Do not treat this skill file as the canonical SDK reference. The Phase 3 Microsoft Learn fetch is the source of truth for SDK usage patterns, supported methods, signatures, and connector behavior. Keep only task-specific decisions in the plan and implementation notes.",{"type":49,"tag":487,"props":13446,"children":13448},{"id":13447},"progress-tracking",[13449],{"type":62,"value":483},{"type":49,"tag":54,"props":13451,"children":13452},{},[13453,13455,13461],{"type":62,"value":13454},"Before starting Phase 1, create a task list with all phases using ",{"type":49,"tag":67,"props":13456,"children":13458},{"className":13457},[],[13459],{"type":62,"value":13460},"TaskCreate",{"type":62,"value":468},{"type":49,"tag":905,"props":13463,"children":13464},{},[13465,13485],{"type":49,"tag":909,"props":13466,"children":13467},{},[13468],{"type":49,"tag":913,"props":13469,"children":13470},{},[13471,13476,13481],{"type":49,"tag":917,"props":13472,"children":13473},{},[13474],{"type":62,"value":13475},"Task subject",{"type":49,"tag":917,"props":13477,"children":13478},{},[13479],{"type":62,"value":13480},"activeForm",{"type":49,"tag":917,"props":13482,"children":13483},{},[13484],{"type":62,"value":11069},{"type":49,"tag":928,"props":13486,"children":13487},{},[13488,13506,13524,13542,13560,13591,13623,13641,13659,13677,13695],{"type":49,"tag":913,"props":13489,"children":13490},{},[13491,13496,13501],{"type":49,"tag":935,"props":13492,"children":13493},{},[13494],{"type":62,"value":13495},"Verify site exists",{"type":49,"tag":935,"props":13497,"children":13498},{},[13499],{"type":62,"value":13500},"Verifying site prerequisites",{"type":49,"tag":935,"props":13502,"children":13503},{},[13504],{"type":62,"value":13505},"Locate project root, detect framework, explore existing server logics and frontend patterns, verify .powerpages-site exists (mandatory)",{"type":49,"tag":913,"props":13507,"children":13508},{},[13509,13514,13519],{"type":49,"tag":935,"props":13510,"children":13511},{},[13512],{"type":62,"value":13513},"Understand requirements",{"type":49,"tag":935,"props":13515,"children":13516},{},[13517],{"type":62,"value":13518},"Gathering requirements",{"type":49,"tag":935,"props":13520,"children":13521},{},[13522],{"type":62,"value":13523},"Determine user intent, whether one or more server logic files are needed, the methods\u002Ffeatures for each item, discover Dataverse custom actions, and any secrets required",{"type":49,"tag":913,"props":13525,"children":13526},{},[13527,13532,13537],{"type":49,"tag":935,"props":13528,"children":13529},{},[13530],{"type":62,"value":13531},"Fetch latest documentation",{"type":49,"tag":935,"props":13533,"children":13534},{},[13535],{"type":62,"value":13536},"Fetching Microsoft Learn docs",{"type":49,"tag":935,"props":13538,"children":13539},{},[13540],{"type":62,"value":13541},"Query Microsoft Learn for current Server Logic SDK reference and samples",{"type":49,"tag":913,"props":13543,"children":13544},{},[13545,13550,13555],{"type":49,"tag":935,"props":13546,"children":13547},{},[13548],{"type":62,"value":13549},"Review implementation plan",{"type":49,"tag":935,"props":13551,"children":13552},{},[13553],{"type":62,"value":13554},"Reviewing plan with user",{"type":49,"tag":935,"props":13556,"children":13557},{},[13558],{"type":62,"value":13559},"Present plan (server logic inventory, functions, SDK features, external APIs, secrets) and confirm before writing code",{"type":49,"tag":913,"props":13561,"children":13562},{},[13563,13568,13573],{"type":49,"tag":935,"props":13564,"children":13565},{},[13566],{"type":62,"value":13567},"Implement server logic",{"type":49,"tag":935,"props":13569,"children":13570},{},[13571],{"type":62,"value":13572},"Writing server logic code",{"type":49,"tag":935,"props":13574,"children":13575},{},[13576,13578,13583,13584,13589],{"type":62,"value":13577},"Determine\u002Fcreate required web roles, create approved ",{"type":49,"tag":67,"props":13579,"children":13581},{"className":13580},[],[13582],{"type":62,"value":349},{"type":62,"value":351},{"type":49,"tag":67,"props":13585,"children":13587},{"className":13586},[],[13588],{"type":62,"value":357},{"type":62,"value":13590}," files, validate code",{"type":49,"tag":913,"props":13592,"children":13593},{},[13594,13599,13604],{"type":49,"tag":935,"props":13595,"children":13596},{},[13597],{"type":62,"value":13598},"Configure table permissions",{"type":49,"tag":935,"props":13600,"children":13601},{},[13602],{"type":62,"value":13603},"Setting up Dataverse table permissions",{"type":49,"tag":935,"props":13605,"children":13606},{},[13607,13609,13614,13616,13621],{"type":62,"value":13608},"(Conditional) Parse ",{"type":49,"tag":67,"props":13610,"children":13612},{"className":13611},[],[13613],{"type":62,"value":349},{"type":62,"value":13615}," files for Dataverse tables, launch ",{"type":49,"tag":67,"props":13617,"children":13619},{"className":13618},[],[13620],{"type":62,"value":9540},{"type":62,"value":13622},", create permission YAML files",{"type":49,"tag":913,"props":13624,"children":13625},{},[13626,13631,13636],{"type":49,"tag":935,"props":13627,"children":13628},{},[13629],{"type":62,"value":13630},"Manage secrets and environment variables",{"type":49,"tag":935,"props":13632,"children":13633},{},[13634],{"type":62,"value":13635},"Configuring secrets and env vars",{"type":49,"tag":935,"props":13637,"children":13638},{},[13639],{"type":62,"value":13640},"(Conditional) Recommend Azure Key Vault, list vaults, store secrets, create environment variables in Dataverse, create site settings with envvar_schema",{"type":49,"tag":913,"props":13642,"children":13643},{},[13644,13649,13654],{"type":49,"tag":935,"props":13645,"children":13646},{},[13647],{"type":62,"value":13648},"Configure site settings",{"type":49,"tag":935,"props":13650,"children":13651},{},[13652],{"type":62,"value":13653},"Configuring site settings",{"type":49,"tag":935,"props":13655,"children":13656},{},[13657],{"type":62,"value":13658},"Set up ServerLogic\u002F* site settings if needed",{"type":49,"tag":913,"props":13660,"children":13661},{},[13662,13667,13672],{"type":49,"tag":935,"props":13663,"children":13664},{},[13665],{"type":62,"value":13666},"Client-side integration",{"type":49,"tag":935,"props":13668,"children":13669},{},[13670],{"type":62,"value":13671},"Wiring frontend to server logic",{"type":49,"tag":935,"props":13673,"children":13674},{},[13675],{"type":62,"value":13676},"Follow the frontend integration reference, create\u002Fupdate service files as needed, and fully wire the UI to the server logic endpoints",{"type":49,"tag":913,"props":13678,"children":13679},{},[13680,13685,13690],{"type":49,"tag":935,"props":13681,"children":13682},{},[13683],{"type":62,"value":13684},"Verify and test guidance",{"type":49,"tag":935,"props":13686,"children":13687},{},[13688],{"type":62,"value":13689},"Validating and providing test guidance",{"type":49,"tag":935,"props":13691,"children":13692},{},[13693],{"type":62,"value":13694},"Final validation, API URLs, CSRF token instructions, testing guide",{"type":49,"tag":913,"props":13696,"children":13697},{},[13698,13703,13708],{"type":49,"tag":935,"props":13699,"children":13700},{},[13701],{"type":62,"value":13702},"Review and deploy",{"type":49,"tag":935,"props":13704,"children":13705},{},[13706],{"type":62,"value":13707},"Reviewing summary and deploying",{"type":49,"tag":935,"props":13709,"children":13710},{},[13711],{"type":62,"value":13712},"Present summary, ask about deployment, provide post-deploy guidance",{"type":49,"tag":54,"props":13714,"children":13715},{},[13716,13718,13724,13726,13732,13734,13740,13742,13748],{"type":62,"value":13717},"Mark each task ",{"type":49,"tag":67,"props":13719,"children":13721},{"className":13720},[],[13722],{"type":62,"value":13723},"in_progress",{"type":62,"value":13725}," when starting it and ",{"type":49,"tag":67,"props":13727,"children":13729},{"className":13728},[],[13730],{"type":62,"value":13731},"completed",{"type":62,"value":13733}," when done via ",{"type":49,"tag":67,"props":13735,"children":13737},{"className":13736},[],[13738],{"type":62,"value":13739},"TaskUpdate",{"type":62,"value":13741},". Use ",{"type":49,"tag":67,"props":13743,"children":13745},{"className":13744},[],[13746],{"type":62,"value":13747},"TaskList",{"type":62,"value":13749}," between phase transitions and before the final summary to confirm there are no incomplete work items left.",{"type":49,"tag":281,"props":13751,"children":13752},{},[],{"type":49,"tag":54,"props":13754,"children":13755},{},[13756],{"type":49,"tag":58,"props":13757,"children":13758},{},[13759],{"type":62,"value":13760},"Begin with Phase 1: Verify Site Exists",{"type":49,"tag":13762,"props":13763,"children":13764},"style",{},[13765],{"type":62,"value":13766},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":13768,"total":13963},[13769,13791,13812,13833,13848,13865,13876,13889,13904,13919,13938,13951],{"slug":13770,"name":13770,"fn":13771,"description":13772,"org":13773,"tags":13774,"stars":13788,"repoUrl":13789,"updatedAt":13790},"rushstack-best-practices","manage Rush monorepos with best practices","Provides best practices and guidance for working with Rush monorepos. Use when the user is working in a Rush-based repository, asks about Rush commands (install, update, build, rebuild), needs help with project selection, dependency management, build caching, subspace configuration, or troubleshooting Rush-specific issues.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13775,13778,13781,13782,13785],{"name":13776,"slug":13777,"type":15},"Engineering","engineering",{"name":13779,"slug":13780,"type":15},"Local Development","local-development",{"name":9,"slug":8,"type":15},{"name":13783,"slug":13784,"type":15},"Project Management","project-management",{"name":13786,"slug":13787,"type":15},"Rush","rush",6484,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frushstack","2026-04-06T18:34:44.965032",{"slug":13792,"name":13792,"fn":13793,"description":13794,"org":13795,"tags":13796,"stars":13809,"repoUrl":13810,"updatedAt":13811},"azure-ai-agents-persistent-dotnet","build AI agents with Azure .NET SDK","Azure AI Agents Persistent SDK for .NET. Low-level SDK for creating and managing AI agents with threads, messages, runs, and tools. Use for agent CRUD, conversation threads, streaming responses, function calling, file search, and code interpreter. Triggers: \"PersistentAgentsClient\", \"persistent agents\", \"agent threads\", \"agent runs\", \"streaming agents\", \"function calling agents .NET\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13797,13800,13803,13806],{"name":13798,"slug":13799,"type":15},".NET","net",{"name":13801,"slug":13802,"type":15},"Agents","agents",{"name":13804,"slug":13805,"type":15},"Azure","azure",{"name":13807,"slug":13808,"type":15},"LLM","llm",2804,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills","2026-07-03T16:32:10.297433",{"slug":13813,"name":13813,"fn":13814,"description":13815,"org":13816,"tags":13817,"stars":13809,"repoUrl":13810,"updatedAt":13832},"azure-ai-anomalydetector-java","build anomaly detection applications with Java","Build anomaly detection applications with Azure AI Anomaly Detector SDK for Java. Use when implementing univariate\u002Fmultivariate anomaly detection, time-series analysis, or AI-powered monitoring.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13818,13821,13822,13825,13828,13829],{"name":13819,"slug":13820,"type":15},"Analytics","analytics",{"name":13804,"slug":13805,"type":15},{"name":13823,"slug":13824,"type":15},"Data Analysis","data-analysis",{"name":13826,"slug":13827,"type":15},"Java","java",{"name":9,"slug":8,"type":15},{"name":13830,"slug":13831,"type":15},"Monitoring","monitoring","2026-05-13T06:14:16.261754",{"slug":13834,"name":13834,"fn":13835,"description":13836,"org":13837,"tags":13838,"stars":13809,"repoUrl":13810,"updatedAt":13847},"azure-ai-contentsafety-java","build content moderation applications with Azure AI","Build content moderation applications with Azure AI Content Safety SDK for Java. Use when implementing text\u002Fimage analysis, blocklist management, or harm detection for hate, violence, sexual content, and self-harm.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13839,13842,13843,13844],{"name":13840,"slug":13841,"type":15},"AI Infrastructure","ai-infrastructure",{"name":13804,"slug":13805,"type":15},{"name":13826,"slug":13827,"type":15},{"name":13845,"slug":13846,"type":15},"Security","security","2026-07-07T06:53:31.293235",{"slug":13849,"name":13849,"fn":13850,"description":13851,"org":13852,"tags":13853,"stars":13809,"repoUrl":13810,"updatedAt":13864},"azure-ai-contentsafety-py","detect harmful content with Azure AI Content Safety","Azure AI Content Safety SDK for Python. Use for detecting harmful content in text and images with multi-severity classification.\nTriggers: \"azure-ai-contentsafety\", \"ContentSafetyClient\", \"content moderation\", \"harmful content\", \"text analysis\", \"image analysis\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13854,13855,13858,13859,13860,13863],{"name":13804,"slug":13805,"type":15},{"name":13856,"slug":13857,"type":15},"Compliance","compliance",{"name":13807,"slug":13808,"type":15},{"name":9,"slug":8,"type":15},{"name":13861,"slug":13862,"type":15},"Python","python",{"name":13845,"slug":13846,"type":15},"2026-07-18T05:14:23.017504",{"slug":13866,"name":13866,"fn":13867,"description":13868,"org":13869,"tags":13870,"stars":13809,"repoUrl":13810,"updatedAt":13875},"azure-ai-language-conversations-py","implement conversational language understanding with Python","Implement Conversational Language Understanding (CLU) using the azure-ai-language-conversations Python SDK. Use when working with ConversationAnalysisClient to analyze conversation intent and entities, building NLP features, or integrating language understanding into applications.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13871,13872,13873,13874],{"name":13819,"slug":13820,"type":15},{"name":13804,"slug":13805,"type":15},{"name":13807,"slug":13808,"type":15},{"name":13861,"slug":13862,"type":15},"2026-07-31T05:54:29.068751",{"slug":13877,"name":13877,"fn":13878,"description":13879,"org":13880,"tags":13881,"stars":13809,"repoUrl":13810,"updatedAt":13888},"azure-ai-translation-text-py","translate text using Azure AI services","Azure AI Text Translation SDK for real-time text translation, transliteration, language detection, and dictionary lookup. Use for translating text content in applications.\nTriggers: \"text translation\", \"translator\", \"translate text\", \"transliterate\", \"TextTranslationClient\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13882,13885,13886,13887],{"name":13883,"slug":13884,"type":15},"API Development","api-development",{"name":13804,"slug":13805,"type":15},{"name":9,"slug":8,"type":15},{"name":13861,"slug":13862,"type":15},"2026-07-18T05:14:16.988376",{"slug":13890,"name":13890,"fn":13891,"description":13892,"org":13893,"tags":13894,"stars":13809,"repoUrl":13810,"updatedAt":13903},"azure-ai-vision-imageanalysis-py","analyze images with Azure AI Vision","Azure AI Vision Image Analysis SDK for captions, tags, objects, OCR, people detection, and smart cropping. Use for computer vision and image understanding tasks.\nTriggers: \"image analysis\", \"computer vision\", \"OCR\", \"object detection\", \"ImageAnalysisClient\", \"image caption\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13895,13896,13899,13902],{"name":13804,"slug":13805,"type":15},{"name":13897,"slug":13898,"type":15},"Computer Vision","computer-vision",{"name":13900,"slug":13901,"type":15},"Images","images",{"name":13861,"slug":13862,"type":15},"2026-07-18T05:14:18.007737",{"slug":13905,"name":13905,"fn":13906,"description":13907,"org":13908,"tags":13909,"stars":13809,"repoUrl":13810,"updatedAt":13918},"azure-appconfiguration-java","manage configuration with Azure App Configuration","Azure App Configuration SDK for Java. Centralized application configuration management with key-value settings, feature flags, and snapshots.\nTriggers: \"ConfigurationClient java\", \"app configuration java\", \"feature flag java\", \"configuration setting java\", \"azure config java\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13910,13911,13914,13917],{"name":13804,"slug":13805,"type":15},{"name":13912,"slug":13913,"type":15},"Configuration","configuration",{"name":13915,"slug":13916,"type":15},"Feature Flags","feature-flags",{"name":13826,"slug":13827,"type":15},"2026-07-03T16:32:01.278468",{"slug":13920,"name":13920,"fn":13921,"description":13922,"org":13923,"tags":13924,"stars":13809,"repoUrl":13810,"updatedAt":13937},"azure-cosmos-rust","build applications with Azure Cosmos DB","Azure Cosmos DB library for Rust (NoSQL API). Document CRUD, containers, and globally distributed data.\nTriggers: \"cosmos db rust\", \"CosmosClient rust\", \"document crud rust\", \"NoSQL rust\", \"partition key rust\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13925,13928,13931,13934],{"name":13926,"slug":13927,"type":15},"Cosmos DB","cosmos-db",{"name":13929,"slug":13930,"type":15},"Database","database",{"name":13932,"slug":13933,"type":15},"NoSQL","nosql",{"name":13935,"slug":13936,"type":15},"Rust","rust","2026-07-31T05:54:27.021432",{"slug":13939,"name":13939,"fn":13921,"description":13940,"org":13941,"tags":13942,"stars":13809,"repoUrl":13810,"updatedAt":13950},"azure-cosmos-ts","Azure Cosmos DB JavaScript\u002FTypeScript SDK (@azure\u002Fcosmos) for data plane operations. Use for CRUD operations on documents, queries, bulk operations, and container management. Triggers: \"Cosmos DB\", \"@azure\u002Fcosmos\", \"CosmosClient\", \"document CRUD\", \"NoSQL queries\", \"bulk operations\", \"partition key\", \"container.items\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13943,13944,13945,13946,13947],{"name":13926,"slug":13927,"type":15},{"name":13929,"slug":13930,"type":15},{"name":9,"slug":8,"type":15},{"name":13932,"slug":13933,"type":15},{"name":13948,"slug":13949,"type":15},"TypeScript","typescript","2026-07-03T16:31:19.368382",{"slug":13952,"name":13952,"fn":13953,"description":13954,"org":13955,"tags":13956,"stars":13809,"repoUrl":13810,"updatedAt":13962},"azure-data-tables-java","build table storage applications with Java","Build table storage applications with Azure Tables SDK for Java. Use when working with Azure Table Storage or Cosmos DB Table API for NoSQL key-value data, schemaless storage, or structured data at scale.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13957,13958,13959,13960,13961],{"name":13804,"slug":13805,"type":15},{"name":13926,"slug":13927,"type":15},{"name":13929,"slug":13930,"type":15},{"name":13826,"slug":13827,"type":15},{"name":13932,"slug":13933,"type":15},"2026-05-13T06:14:17.582229",267,{"items":13965,"total":4410},[13966,13978,13992,14002,14016,14029,14043],{"slug":13967,"name":13967,"fn":13968,"description":13969,"org":13970,"tags":13971,"stars":23,"repoUrl":24,"updatedAt":13977},"activate-site","provision and activate Power Pages sites","Activates and provisions a Power Pages website in a Power Platform environment via the Power Platform REST API. Use when the user wants to activate, provision, turn on, or enable a Power Pages website or portal.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13972,13975,13976],{"name":13973,"slug":13974,"type":15},"Deployment","deployment",{"name":9,"slug":8,"type":15},{"name":20,"slug":21,"type":15},"2026-04-06T18:34:34.732549",{"slug":13979,"name":13979,"fn":13980,"description":13981,"org":13982,"tags":13983,"stars":23,"repoUrl":24,"updatedAt":13991},"add-connector","add Power Platform connectors to apps","Adds any Power Platform connector to a Power Apps code app. Generic fallback for connectors not covered by a specific skill.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13984,13987,13989],{"name":13985,"slug":13986,"type":15},"Integrations","integrations",{"name":13988,"slug":33,"type":15},"Power Apps",{"name":13990,"slug":34,"type":15},"Power Platform","2026-07-31T05:54:47.042251",{"slug":13993,"name":13993,"fn":13994,"description":13995,"org":13996,"tags":13997,"stars":23,"repoUrl":24,"updatedAt":14001},"add-datasource","add data sources to Power Apps","Adds a data source or connector to a Power Apps code app. Asks what the user wants to accomplish and routes to the appropriate specialized skill.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[13998,13999,14000],{"name":13985,"slug":13986,"type":15},{"name":9,"slug":8,"type":15},{"name":13988,"slug":33,"type":15},"2026-07-03T16:31:47.822186",{"slug":14003,"name":14003,"fn":14004,"description":14005,"org":14006,"tags":14007,"stars":23,"repoUrl":24,"updatedAt":14015},"add-dataverse","add Dataverse tables to Power Apps","Use when the user wants to add Dataverse tables (existing or new) to a Power Apps mobile app, extend an existing Dataverse table with new columns, or apply an approved data model plan.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[14008,14011,14013,14014],{"name":14009,"slug":14010,"type":15},"Data Modeling","data-modeling",{"name":4767,"slug":14012,"type":15},"dataverse",{"name":9,"slug":8,"type":15},{"name":13988,"slug":33,"type":15},"2026-07-31T05:54:46.078014",{"slug":14017,"name":14017,"fn":14018,"description":14019,"org":14020,"tags":14021,"stars":23,"repoUrl":24,"updatedAt":14028},"add-excel","integrate Excel Online into Power Apps","Adds Excel Online (Business) connector to a Power Apps code app. Use when reading or writing Excel workbook data from OneDrive or SharePoint.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[14022,14025,14026,14027],{"name":14023,"slug":14024,"type":15},"Excel","excel",{"name":13985,"slug":13986,"type":15},{"name":9,"slug":8,"type":15},{"name":13988,"slug":33,"type":15},"2026-07-31T05:54:44.030943",{"slug":14030,"name":14030,"fn":14031,"description":14032,"org":14033,"tags":14034,"stars":23,"repoUrl":24,"updatedAt":14042},"add-mcscopilot","add Copilot Studio connectors to Power Apps","Adds Microsoft Copilot Studio connector to a Power Apps code app. Use when invoking Copilot Studio agents, sending prompts to agents, or integrating agent responses.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[14035,14036,14039,14040,14041],{"name":13801,"slug":13802,"type":15},{"name":14037,"slug":14038,"type":15},"Copilot Studio","copilot-studio",{"name":13985,"slug":13986,"type":15},{"name":9,"slug":8,"type":15},{"name":13988,"slug":33,"type":15},"2026-07-31T05:54:39.025597",{"slug":14044,"name":14044,"fn":14045,"description":14046,"org":14047,"tags":14048,"stars":23,"repoUrl":24,"updatedAt":14056},"add-sample-data","populate Power Pages tables with sample data","Populates Dataverse tables with sample records for testing and demoing a Power Pages site. Use when the user wants to add sample data, seed data, generate test records, or insert demo data into their tables.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[14049,14050,14051,14052,14053],{"name":13929,"slug":13930,"type":15},{"name":4767,"slug":14012,"type":15},{"name":9,"slug":8,"type":15},{"name":20,"slug":21,"type":15},{"name":14054,"slug":14055,"type":15},"Testing","testing","2026-04-06T18:34:41.141155"]