Install
$ agentstack add skill-ryanmakesandbreaksstuff-custom-codex-claude-plugins-and-skills-dataverse-web-resources ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Dataverse Web Resources
CRITICAL RULES
formContextis invalid afterawait. Context objects passed to event handlers are valid only during synchronous execution. After anyawaitor inside.then(),formContext.getAttribute("x").getValue()silently returnsnull— not an error. Extract the VALUES you need (strings, GUIDs, numbers) before the firstawait. Never store the context reference itself across an async boundary.
preventDefault()is synchronous-only in OnSave. Calling it afterawaitdoes nothing — the save proceeds regardless. If you need to block a save based on async validation, callpreventDefault()synchronously first, then perform the async check and re-enable if valid viasaveEventArguments.enableSaveValidation.
- Never call
formContext.data.entity.save()inside an OnSave handler. This creates a recursive save loop, producing a "Saving in Progress" runtime error visible to the user.
Xrmis completely unavailable in SiteMap SubArea web resources. NeitherXrmnorparent.Xrmis injected. The only supported approach: include `and callGetGlobalContext()for org context.Xrm.WebApi,Xrm.Navigation, and all otherXrm.*` APIs are inaccessible from these pages — there is no workaround.
- Never hardcode
/WebResources/as a URL path. In multi-org environments this silently resolves to the user's default org, not the current one — causing "File Not Found" for users in a non-default org. It also bypasses the platform's browser cache versioning token. Use$webresource:in SiteMap/Ribbon XML, orXrm.Navigation.openWebResource()in code — both embed the version token automatically.
- "Pass execution context as first parameter" MUST be checked. Without it the function receives no argument,
executionContextisundefined, and the firstgetFormContext()call crashes silently. No error is thrown at registration time.
- Async OnSave handlers have a 10-second platform timeout per handler. After timeout the save continues whether or not you called
preventDefault()— the timed-out handler is simply abandoned. Never calldisableAsyncTimeout()unless you can guarantee the async operation cannot hang.
- Always use
$selectinXrm.WebApicalls. Without it every column on every matching record is returned — including multi-line text fields and computed columns. Severe performance impact on grids and high-traffic views.
- DOM manipulation is unsupported and breaks on platform updates. PowerApps Checker (
avoid-dom-form) flags any direct DOM access in form scripts. The Unified Interface DOM is internal and undocumented. Use exclusivelyformContext.*andXrm.*client API methods.
NEVER
- NEVER use
parent.Xrm.*in a SiteMap SubArea,openWebResourcepopup, or side pane web resource —Xrmis not injected. UseClientGlobalContext.js.aspx→GetGlobalContext(). - NEVER manipulate the model-driven app DOM (
querySelector,element.style,addEventListeneron platform elements) — unsupported, breaks on platform updates, flagged by PowerApps Checker. - NEVER use synchronous
XMLHttpRequest— deprecated, blocked by PowerApps Checker, breaks async form loading. UsefetchorXrm.WebApi(promise-based only). - NEVER call
formContext.data.entity.save()inside an OnSave handler — recursive save loop → "Saving in Progress" error. - NEVER use
preventDefault()to block BPF stage navigation inside an OnSave handler — throws a runtime error. RegisterformContext.data.process.addOnPreStageChange(handler)instead and calleventArgs.preventDefault()there. - NEVER store
executionContextorformContextacross async boundaries — they become stale immediately after the synchronous event phase ends. - NEVER put logic or data you want to hide inside classic RibbonDiffXml display/enable rules — all ribbon XML downloads to and is visible in the user's browser DevTools.
Xrm Context Availability
| Web resource location | Xrm directly | parent.Xrm | Correct approach | |---|---|---|---| | Form event handler | Via executionContext.getFormContext() | N/A | Standard executionContext pattern | | HTML web resource embedded in form tab | NO | parent.Xrm.* works | parent.Xrm.Utility, parent.Xrm.Navigation | | SiteMap SubArea HTML web resource | NO | NO | ClientGlobalContext.js.aspx → GetGlobalContext() | | Opened via openWebResource() | NO | NO | ClientGlobalContext.js.aspx → GetGlobalContext() | | App side pane (Xrm.App.sidePanes) | NO | NO | ClientGlobalContext.js.aspx → GetGlobalContext() | | Ribbon JavaScript action | Not via executionContext | N/A | CrmParameter bindings in ribbon XML |
Quick Reference — Key Operations
| Operation | Method | Endpoint | |---|---|---| | Create web resource | POST | /webresourceset | | Update web resource | PATCH | /webresourceset({id}) | | Add to solution | Action | AddSolutionComponent (ComponentType=61) | | Publish | Action | PublishXml |
Loading Resources
Writing JavaScript for form events (OnLoad, OnSave, OnChange, field validation, UI manipulation): → MANDATORY: Load [resources/js-form-scripts.md](resources/js-form-scripts.md) before writing form scripts. Do NOT load ribbon or navigation files for form-script-only tasks.
HTML pages for dashboards, KPIs, embedded charts, or custom embedded UI: → MANDATORY: Load [resources/html-dashboards.md](resources/html-dashboards.md). Do NOT load js-form-scripts.md for HTML-only tasks.
Side panes, modal/modeless dialogs, or programmatic navigation (Xrm.App, Xrm.Navigation): → MANDATORY: Load [resources/navigation-side-panes.md](resources/navigation-side-panes.md). Do NOT load js-form-scripts.md for navigation-only tasks.
Command bar or ribbon customization (modern commanding JSON vs classic RibbonDiffXml): → MANDATORY: Load [resources/ribbon-command-bar.md](resources/ribbon-command-bar.md). Do NOT load js-form-scripts.md for ribbon-only tasks.
Choosing control types, field formats, navigation patterns, or page layouts before implementing: → MANDATORY: Consult [resources/ux-decision-guide.md](resources/ux-decision-guide.md) FIRST.
Creating or deploying web resources via the Web API: → Load [resources/deployment.md](resources/deployment.md).
Business Process Flow JavaScript API (stage navigation, OnPreStageChange, stage locking): → MANDATORY: Load [resources/bpf-client-api.md](resources/bpf-client-api.md) for any BPF scripting.
All 12 web resource types and their numeric Type IDs: → Load [resources/types-reference.md](resources/types-reference.md) for type/ID lookup only.
Do NOT load all files simultaneously — load only the file matching the specific task.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: RyanMakesAndBreaksStuff
- Source: RyanMakesAndBreaksStuff/Custom-Codex-Claude-Plugins-and-Skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.