diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7091a1d..1a8549c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -79,6 +79,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
#### Stack-level
+- **Liquibase**: `service.type` is limited to `WMS`, `WFS`, and `WMTS` on the development, postgres, and oracle profiles. A stored service of another type is not deleted ([#101](https://github.com/sitmun/sitmun-application-stack/issues/101)).
- **Docker**: `docker compose build front` uses the Angular 22 viewer webpack config. `envsubst` replaces only `PUBLIC_BASE_PATH`, so the viewer image build keeps the `jszip`, `util`, and `@spz-loader` exclusions.
- **Docker**: `sitmun-shared` checks out `gradlew` with LF line endings. On Windows with `core.autocrlf=true`, the backend and proxy image builds failed in `publishToMavenLocal` with `/bin/sh^M: bad interpreter` (exit code 126) ([#89](https://github.com/sitmun/sitmun-application-stack/issues/89)).
- **E2E**: Each root E2E job publishes the pinned `sitmun-shared` to the local Maven repository before the suite starts. The backend resolves `sitmun-spring-upstream` and `sitmun-proxy-contract` `1.2.9` from that repository.
diff --git a/back/backend/sitmun-backend-core b/back/backend/sitmun-backend-core
index 29fa59d..140c337 160000
--- a/back/backend/sitmun-backend-core
+++ b/back/backend/sitmun-backend-core
@@ -1 +1 @@
-Subproject commit 29fa59dd88041f546e2fcc1d8daa9f1f1a91d7a4
+Subproject commit 140c337d1ac5eee577c1b8b951a8ef9d78edb0f5
diff --git a/e2e/README.md b/e2e/README.md
index ba9042e..49dcf06 100644
--- a/e2e/README.md
+++ b/e2e/README.md
@@ -15,6 +15,7 @@ Browser E2E against backend-core on in-memory H2. No Docker Compose.
- Tree form **Details** SVG local-file persist and touristic **Tree structure** node Appearance SVG persist: picker `accept` includes `.svg`; POST/PUT stores `data:image/svg+xml;base64,...` without raster scaling; reload preview stays SVG ([sitmun-admin-app#330](https://github.com/sitmun/sitmun-admin-app/issues/330); `e2e/admin/forms/tree-svg-image.spec.ts`, project `admin-forms`)
- Layers form **Details**: validation, create, reload persistence; Feature Information character-count must not throw `raw.split` beside the queryable-layers CSV validator (`e2e/admin/forms/layers-form.spec.ts`, project `admin-forms`)
- Layers form relation tabs: opening Details must not GET `/cartographies/{id}/availabilities|permissions|treeNodes`; those association requests fire only after the matching tab is selected ([#41](https://github.com/sitmun/sitmun-application-stack/issues/41); same spec)
+- Service form type list offers only `WMS`, `WFS`, and `WMTS` (`e2e/admin/forms/service-type-options.spec.ts`, project `admin-forms`, [sitmun-application-stack#101](https://github.com/sitmun/sitmun-application-stack/issues/101))
- Service form Get Metadata: MapServer-style URL with existing `?map=` POSTs `helpers/capabilities` JSON (`url` is the form endpoint, `type` is WMS); backend adds GetCapabilities (intercepted stub; no live ICGC) (`e2e/admin/forms/service-capabilities-mapserver.spec.ts`, project `admin-forms`)
- Layers list delete: create via form, search, grid delete → `DELETE /api/cartographies/{id}` **204** and GET **404** (`e2e/admin/forms/layers-list-delete.spec.ts`, project `admin-forms`)
- Plantilla dry-run: ADMIN `POST /api/tasks/template/preview` and `/execute-child` without required `appId`/`terId` (`e2e/admin/forms/template-execute-child.spec.ts`, project `admin-forms`)
diff --git a/e2e/admin/forms/service-type-options.spec.ts b/e2e/admin/forms/service-type-options.spec.ts
new file mode 100644
index 0000000..6f34a4f
--- /dev/null
+++ b/e2e/admin/forms/service-type-options.spec.ts
@@ -0,0 +1,19 @@
+import { expect, test } from '../fixtures';
+import { control, dismissBlockingOverlays, gotoCreateForm } from '../helpers/form';
+
+test.describe('Service form type list', () => {
+ test('offers only WMS, WFS, and WMTS', async ({ page }) => {
+ await gotoCreateForm(page, '/#/service/-1/serviceForm', 'name');
+ const typeSelect = control(page, 'type');
+ await typeSelect.scrollIntoViewIfNeeded();
+ await dismissBlockingOverlays(page);
+ await typeSelect.locator('.mat-mdc-select-trigger').click({ force: true });
+ const options = page.getByRole('option');
+ await options.first().waitFor({ state: 'visible', timeout: 15_000 });
+ const names = (await options.allTextContents())
+ .map((text) => text.trim())
+ .filter((text) => text.length > 0)
+ .sort();
+ expect(names).toEqual(['WFS', 'WMS', 'WMTS']);
+ });
+});
diff --git a/profiles/development/backend/liquibase/changelog/87_restrict_service_types.yaml b/profiles/development/backend/liquibase/changelog/87_restrict_service_types.yaml
new file mode 100644
index 0000000..2e69b28
--- /dev/null
+++ b/profiles/development/backend/liquibase/changelog/87_restrict_service_types.yaml
@@ -0,0 +1,8 @@
+databaseChangeLog:
+ - changeSet:
+ id: 87-restrict-service-types
+ author: sitmun
+ changes:
+ - delete:
+ tableName: STM_CODELIST
+ where: "COD_LIST = 'service.type' AND COD_VALUE NOT IN ('WMS', 'WFS', 'WMTS')"
diff --git a/profiles/development/backend/liquibase/master.xml b/profiles/development/backend/liquibase/master.xml
index 689a9ad..56831b1 100644
--- a/profiles/development/backend/liquibase/master.xml
+++ b/profiles/development/backend/liquibase/master.xml
@@ -93,4 +93,5 @@
+
diff --git a/profiles/oracle/liquibase/changelog/31_restrict_service_types.yaml b/profiles/oracle/liquibase/changelog/31_restrict_service_types.yaml
new file mode 100644
index 0000000..de825d7
--- /dev/null
+++ b/profiles/oracle/liquibase/changelog/31_restrict_service_types.yaml
@@ -0,0 +1,8 @@
+databaseChangeLog:
+ - changeSet:
+ id: 31-restrict-service-types
+ author: sitmun
+ changes:
+ - delete:
+ tableName: STM_CODELIST
+ where: "COD_LIST = 'service.type' AND COD_VALUE NOT IN ('WMS', 'WFS', 'WMTS')"
diff --git a/profiles/oracle/liquibase/master.xml b/profiles/oracle/liquibase/master.xml
index a8bd350..406358c 100644
--- a/profiles/oracle/liquibase/master.xml
+++ b/profiles/oracle/liquibase/master.xml
@@ -35,4 +35,5 @@
+
diff --git a/profiles/postgres/liquibase/changelog/31_restrict_service_types.yaml b/profiles/postgres/liquibase/changelog/31_restrict_service_types.yaml
new file mode 100644
index 0000000..de825d7
--- /dev/null
+++ b/profiles/postgres/liquibase/changelog/31_restrict_service_types.yaml
@@ -0,0 +1,8 @@
+databaseChangeLog:
+ - changeSet:
+ id: 31-restrict-service-types
+ author: sitmun
+ changes:
+ - delete:
+ tableName: STM_CODELIST
+ where: "COD_LIST = 'service.type' AND COD_VALUE NOT IN ('WMS', 'WFS', 'WMTS')"
diff --git a/profiles/postgres/liquibase/master.xml b/profiles/postgres/liquibase/master.xml
index 76b0876..c8387ee 100644
--- a/profiles/postgres/liquibase/master.xml
+++ b/profiles/postgres/liquibase/master.xml
@@ -33,4 +33,5 @@
+