diff --git a/.claude/skills/generate-service-impex/SKILL.md b/.claude/skills/generate-service-impex/SKILL.md
index cb94863..1479792 100644
--- a/.claude/skills/generate-service-impex/SKILL.md
+++ b/.claude/skills/generate-service-impex/SKILL.md
@@ -123,14 +123,16 @@ Read `references/service-patterns.md` for pre-built patterns:
```xml
-
-
-
+
+
+
```
-**CRITICAL:** Always use `mode="delete"` and reverse order.
+**CRITICAL:** Always use `mode="delete"`. Site Impex `services.xsd` requires this sequence: `service-credential`, then `service-profile`, then `service`. Use the **same element order for install and uninstall**. The platform processes elements in document order; putting `` first makes the uninstall file invalid against the XSD, so services are not deleted. Impex is safe deleting credentials and profiles first because ORM nulls `SERVICE.CREDENTIALID` / `PROFILEID` when those objects are removed.
+
+**BM UI vs Site Impex:** Business Manager UI still requires deleting the service first (`RemoveServiceProfile` / `RemoveServiceCredential` refuse delete while a service references them). That UI rule does **not** apply to CAP uninstall IMPEX.
## Step 6: Configuration best practices
@@ -222,8 +224,8 @@ Share profile across multiple endpoints:
- [ ] Timeout appropriate for service type
- [ ] Rate limiting configured
- [ ] Circuit breaker enabled for external APIs
-- [ ] Uninstall file includes all services in reverse order
-- [ ] All services use `mode="delete"` in uninstall
+- [ ] Uninstall file includes all credentials, profiles, and services in XSD order (credential → profile → service)
+- [ ] All uninstall entries use `mode="delete"`
- [ ] XML well-formed
- [ ] Log prefix descriptive
@@ -249,7 +251,7 @@ var result = service.call(params);
|---------|-----|
| Hardcoded production credentials | Use placeholders |
| Missing uninstall script | Create matching uninstall |
-| Wrong deletion order | Delete: service → profile → credential |
+| Wrong deletion order | For CAP uninstall IMPEX, use credential → profile → service (`mode="delete"`), the same XSD order as install. BM UI still requires service-first; that rule does not apply to IMPEX. |
| No rate limiting | Add rate limit config |
| Timeout too short | Increase based on API response time |
| No circuit breaker | Enable for external APIs |
diff --git a/.claude/skills/scaffold-app/assets/templates/services-uninstall.xml.tmpl b/.claude/skills/scaffold-app/assets/templates/services-uninstall.xml.tmpl
index 248bd7d..a44680e 100644
--- a/.claude/skills/scaffold-app/assets/templates/services-uninstall.xml.tmpl
+++ b/.claude/skills/scaffold-app/assets/templates/services-uninstall.xml.tmpl
@@ -1,6 +1,7 @@
-
-
+
+
+
diff --git a/.claude/skills/validate-app/SKILL.md b/.claude/skills/validate-app/SKILL.md
index 7c57477..9d8bbdd 100644
--- a/.claude/skills/validate-app/SKILL.md
+++ b/.claude/skills/validate-app/SKILL.md
@@ -193,6 +193,7 @@ find "$CAP_ROOT/impex/" -name "*.xml" -exec xmllint --noout {} \;
See `references/impex-validation.md` for detailed rules:
- Services use dotted notation
- Install/uninstall pairs match
+- Uninstall `services.xml` uses credential → profile → service order with `mode="delete"` (same XSD sequence as install; BM UI service-first delete does not apply to IMPEX)
- Attribute IDs use camelCase with app prefix
- SITEID placeholder (not actual site ID)
- No hardcoded credentials
diff --git a/.claude/skills/validate-app/references/impex-validation.md b/.claude/skills/validate-app/references/impex-validation.md
index 44c7021..7627461 100644
--- a/.claude/skills/validate-app/references/impex-validation.md
+++ b/.claude/skills/validate-app/references/impex-validation.md
@@ -34,10 +34,12 @@ find commerce--app-v/impex/ -name "*.xml" -exec xmllint --noou
### Uninstall file (`impex/uninstall/services.xml`)
**Required checks:**
-- [ ] All services use `mode="delete"`
-- [ ] Deletion order: service → profile → credential
+- [ ] All credentials, profiles, and services use `mode="delete"`
+- [ ] Element order matches `services.xsd` (and install): credential → profile → service
- [ ] All service/profile/credential IDs match install file exactly
+**BM UI vs Site Impex:** Business Manager UI refuses to delete a profile or credential while a service still references it (delete the service first). That UI rule does **not** apply to CAP uninstall IMPEX. Site Impex processes elements in document order and `services.xsd` requires credential → profile → service.
+
## Site Preferences Validation
### Metadata file (`impex/install/meta/system-objecttype-extensions.xml`)
@@ -101,6 +103,7 @@ Check for these frequent issues:
**Structure:**
- [ ] All XML files are well-formed (no unclosed tags)
- [ ] All XML files use correct namespace declarations
+- [ ] Uninstall `services.xml` uses credential → profile → service (XSD order). BM UI service-first delete does not apply to IMPEX.
**If any validation fails:**
- Report specific file path
diff --git a/.claude/skills/validate-impex/SKILL.md b/.claude/skills/validate-impex/SKILL.md
index b106c73..f372708 100644
--- a/.claude/skills/validate-impex/SKILL.md
+++ b/.claude/skills/validate-impex/SKILL.md
@@ -88,10 +88,12 @@ xmllint --schema "$(b2c docs schema preferences --path)" impex/install/preferenc
### Uninstallation file (`impex/uninstall/services.xml`)
**Check:**
-- [ ] All services use `mode="delete"`
-- [ ] Deletion order: service → profile → credential
+- [ ] All credentials, profiles, and services use `mode="delete"`
+- [ ] Element order matches `services.xsd` (and install): credential → profile → service
- [ ] All IDs match install file
+**BM UI vs Site Impex:** Business Manager UI still requires deleting the service first (`RemoveServiceProfile` / `RemoveServiceCredential` refuse delete while a service references them). That UI rule does **not** apply to CAP uninstall IMPEX.
+
**Verify pairs match:**
```bash
# Extract service IDs from both files
@@ -154,7 +156,8 @@ diff /tmp/install-ids.txt /tmp/uninstall-ids.txt
| `Service with ID already exists` | Use unique IDs |
| `Attribute not defined in group` | Add to group-definitions |
| `Invalid value for type` | Match default value to type |
-| `Cannot delete service, profile in use` | Delete in order: service → profile → credential |
+| `Cannot delete service, profile in use` | Business Manager UI: delete the service first, then the profile, then the credential. This UI rule does **not** apply to CAP uninstall IMPEX. |
+| Uninstall `services.xml` fails XSD / services not deleted | Site Impex processes elements in document order. Use credential → profile → service (`mode="delete"`), the same sequence as install. |
| `SITEID not found` | Use SITEID placeholder |
## Step 8: Pre-import checklist
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 34d908f..7296aa6 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -67,6 +67,7 @@
### Impex Files (if applicable)
- [ ] Service install file has matching uninstall file
- [ ] Uninstall files use `mode="delete"`
+- [ ] Uninstall `services.xml` element order is credential → profile → service (same as install)
- [ ] All attribute IDs prefixed with app name
- [ ] No hardcoded production credentials in services.xml
- [ ] SITEID placeholder used (not actual site ID)
diff --git a/AGENTS.md b/AGENTS.md
index a80a93d..ad8c247 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -155,7 +155,7 @@ Your response:
### 5. Impex Rules
- Service install files MUST have matching uninstall files
- Uninstall MUST use `mode="delete"`
-- Deletion order: service → profile → credential
+- Uninstall element order: credential → profile → service (Site Impex `services.xsd`; same order as install). BM UI still requires service-first; that rule does not apply to CAP uninstall IMPEX.
- Use `SITEID` placeholder, not actual site IDs
- All attribute IDs MUST be prefixed with app name
@@ -346,6 +346,21 @@ tax/avalara-tax/catalog.json
```
+### ❌ Wrong Uninstall Element Order
+```xml
+
+
+
+
+
+
+
+
+
+```
+
+Business Manager UI still requires deleting the service first. That UI rule does not apply to CAP uninstall IMPEX.
+
### ❌ Version Mismatch
```json
// manifest.json
@@ -499,6 +514,7 @@ Before suggesting `/submit-app-pr`, verify:
**Impex Validation:**
- [ ] XML syntax valid (no parsing errors)
- [ ] Service install has matching uninstall
+- [ ] Uninstall `services.xml` uses credential → profile → service order with `mode="delete"`
- [ ] Attribute IDs prefixed with app name
- [ ] No hardcoded production credentials
- [ ] SITEID placeholder used (not actual site ID)
diff --git a/docs/testing.md b/docs/testing.md
index 422ed5e..2252569 100644
--- a/docs/testing.md
+++ b/docs/testing.md
@@ -208,7 +208,7 @@ Beyond `b2c cap validate`, validate the XML directly:
- Well-formed XML for every file under `impex/`
- Correct SFCC namespaces (`http://www.demandware.com/xml/impex/services/2015-07-01`, etc.)
- `mode="delete"` on every entry in `impex/uninstall/`
-- Service IDs in install match uninstall, deletion order is service → profile → credential
+- Service IDs in install match uninstall; uninstall element order is credential → profile → service (same `services.xsd` sequence as install)
- Attribute IDs are camelCase and prefixed with the app name
- `SITEID` placeholder used in `preferences.xml` (not a real site ID)
- No hardcoded production credentials