From 9728b000b48ade5c298a30efff9c2eea53bb98bb Mon Sep 17 00:00:00 2001
From: vmaubert <v.maubert@code-troopers.com>
Date: Mon, 12 Jun 2023 10:07:38 +0200
Subject: [PATCH] =?UTF-8?q?feat(prm):=20transforme=20l=E2=80=99arbre=20d?=
 =?UTF-8?q?=E2=80=99instructions=20des=20octrois=20de=20PRM=20en=20machine?=
 =?UTF-8?q?=20(#579)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 packages/api/src/api/_format/etapes-types.ts  |   2 +-
 ...ons-permissions-etapes.test.integration.ts |  12 +-
 .../api/graphql/documents.test.integration.ts |   1 +
 .../src/api/graphql/resolvers/documents.ts    |  17 +-
 .../src/api/graphql/resolvers/entreprises.ts  |   3 +-
 .../api/src/api/graphql/resolvers/points.ts   |   3 +-
 .../api/graphql/resolvers/titre-demande.ts    |   3 +-
 .../api/graphql/resolvers/titres-activites.ts |   2 +-
 .../api/graphql/resolvers/titres-etapes.ts    |  29 +-
 .../titres-demarches.test.integration.ts      |   4 +-
 ...titres-etapes-modifier.test.integration.ts |   1 +
 .../api/graphql/titres.test.integration.ts    |  54 +-
 .../api/rest/entreprises.test.integration.ts  |   1 +
 packages/api/src/api/rest/entreprises.test.ts |  27 +-
 packages/api/src/api/rest/entreprises.ts      |   5 +-
 packages/api/src/api/rest/etapes.test.ts      | 191 ++++-
 packages/api/src/api/rest/etapes.ts           |  29 +-
 packages/api/src/api/rest/fichiers.ts         |   5 +-
 .../api/src/api/rest/titre-contenu.test.ts    |   5 +-
 .../src/api/rest/titres.test.integration.ts   |  19 +-
 packages/api/src/api/rest/titres.ts           |  47 +-
 packages/api/src/business/daily.ts            |   6 +-
 packages/api/src/business/matrices.test.ts    |   7 +-
 .../titres-activites-update-titres.ts         |   5 +-
 ...apes-areas-update.test.integration.ts.snap |   4 +-
 .../titres-demarches-depot-create.ts          |   2 +-
 ...titres-demarches-statut-ids-update.test.ts |  43 +-
 .../titres-demarches-statut-ids-update.ts     |   6 +-
 ...pes-administrations-locales-update.test.ts |  14 +-
 ...es-etapes-areas-update.test.integration.ts |   6 +-
 ...-etapes-heritage-contenu-update.queries.ts |  64 ++
 ...s-heritage-contenu-update.queries.types.ts |  33 +
 .../titres-etapes-heritage-contenu-update.ts  |  75 +-
 .../titres-etapes-ordre-update.test.ts        |   5 +-
 .../processes/titres-etapes-ordre-update.ts   |  17 +-
 .../processes/titres-phases-update.test.ts    |  34 +-
 .../titres-statut-ids-update.test.ts          |  10 +-
 .../business/rules-demarches/_utils.test.ts   |  89 ---
 .../rules-demarches/axm/oct.machine.ts        |   2 +-
 .../rules-demarches/definitions.test.ts       | 131 +---
 .../business/rules-demarches/definitions.ts   |  72 +-
 .../business/rules-demarches/etat-cycles.ts   |  27 -
 .../rules-demarches/machine-common.test.ts    |  24 +-
 .../rules-demarches/machine-common.ts         |  40 +-
 .../src/business/rules-demarches/machines.ts  |  13 +-
 .../business/rules-demarches/prm/oct.cas.json |   1 +
 .../rules-demarches/prm/oct.machine.test.ts   | 167 ++++
 .../rules-demarches/prm/oct.machine.ts        | 723 ++++++++++++++++++
 .../business/rules-demarches/prm/oct.test.ts  |  99 ---
 .../src/business/rules-demarches/prm/oct.ts   | 201 -----
 .../titre-date-demande-find-demarches.ts      |   4 +-
 ...-demarche-date-fin-duree-find-demarches.ts |  14 +-
 .../rules/titre-activites-build.test.ts       |   9 +-
 ...-demarche-annulation-date-fin-find.test.ts |  10 +-
 .../rules/titre-demarche-public-find.test.ts  | 114 +--
 .../rules/titre-demarche-public-find.ts       |  12 +-
 .../titre-demarche-statut-id-find.test.ts     |   7 +-
 .../rules/titre-demarche-statut-id-find.ts    |  13 +-
 .../rules/titre-etape-prop-find.test.ts       |  24 +-
 .../business/rules/titre-phases-find.test.ts  | 200 ++---
 .../rules/titre-prop-etape-find.test.ts       | 106 +--
 .../api/src/business/titre-etape-update.ts    |   9 +-
 .../utils/props-titre-etapes-ids-find.test.ts |   4 +-
 .../utils/titre-demarches-etapes-rebuild.ts   |   4 +-
 .../titre-etape-heritage-contenu-find.ts      |   9 +-
 .../titre-etape-heritage-props-find.test.ts   |  25 +-
 .../business/utils/titre-etapes-sort.test.ts  | 131 ++--
 .../src/business/utils/titre-etapes-sort.ts   |  63 +-
 .../utils/titre-slug-and-relations-update.ts  |   6 +-
 .../titre-demarche-etat-validate.test.ts      | 114 +--
 .../titre-demarche-etat-validate.ts           |  95 +--
 .../titre-etape-etat-validate.test.ts         | 106 ---
 .../validations/titre-etape-etat-validate.ts  | 182 -----
 .../titre-etape-updation-validate.test.ts     |  10 +-
 .../titre-etape-updation-validate.ts          |   8 +-
 .../validations/titre-links-validate.ts       |   3 +-
 .../src/database/models/_format/id-create.ts  |  10 +
 .../models/_format/titre-etape-heritage.ts    |   5 +-
 packages/api/src/database/queries/journaux.ts |   3 +-
 .../permissions/documents.test.integration.ts |  16 +-
 .../titres-demarches.test.integration.ts      |   8 +-
 .../titres-etapes.test.integration.ts         |   8 +-
 .../permissions/titres.test.integration.ts    |  27 +-
 .../titres-activites.test.integration.ts      |   6 +-
 .../api/src/database/queries/titres-etapes.ts |   8 +-
 .../api/src/database/queries/titres-titres.ts |   5 +-
 packages/api/src/database/queries/titres.ts   |   6 +-
 .../20230607092129_etape-ordre-not-null.ts    |   8 +
 .../src/tools/demarches/definitions-check.ts  |   4 +-
 packages/api/src/tools/demarches/tde-check.ts |   4 +-
 .../api/src/tools/demarches/tests-creation.ts |  57 +-
 .../tools/documents/files-document-check.ts   |   3 +-
 packages/api/src/tools/geojson.ts             |   5 +-
 .../api/src/tools/phases/tests-creation.ts    |   4 +-
 packages/api/src/types.ts                     |  16 +-
 .../_utils/administrations-permissions.ts     |  11 +-
 packages/api/tsconfig.json                    |   2 +-
 packages/common/src/demarche.ts               |   3 +-
 packages/common/src/etape.ts                  |   5 +-
 packages/common/src/rest.ts                   |  21 +-
 .../common/src/static/demarchesStatuts.ts     |   7 +-
 packages/common/src/static/pays.test.ts       |  23 +-
 packages/common/src/static/pays.ts            |   4 +
 packages/common/src/titres.ts                 |   7 +-
 .../components/_common/perimetre.stories.tsx  |   5 +-
 .../ui/src/components/_common/perimetre.tsx   |   3 +-
 .../dashboard/pure-onf-dashboard.stories.tsx  |  10 +-
 .../dashboard/pure-ptmg-dashboard.stories.tsx |  10 +-
 .../ui/src/components/dashboard/testData.ts   |  10 +-
 .../etape/fondamentales-edit.stories.ts       |   4 +-
 .../components/titre/edit-popup.stories.tsx   |   5 +-
 .../src/components/titre/header.stories.tsx   |  13 +-
 packages/ui/src/components/titre/header.tsx   |   6 +-
 .../ui/src/components/titre/infos.stories.tsx |  24 +-
 packages/ui/src/components/titre/infos.tsx    |  10 +-
 .../components/titre/territoires.stories.tsx  |  35 +-
 .../ui/src/components/titre/territoires.tsx   |   7 +-
 .../src/components/titre/titre-api-client.ts  |  26 +-
 .../titre/titres-link-form-api-client.ts      |  14 +-
 .../titre/titres-link-form.stories.tsx        |  18 +-
 .../src/components/titre/titres-link-form.tsx |   4 +-
 .../components/titre/titres-link.stories.tsx  |  25 +-
 .../ui/src/utils/titre-etape-edit.test.ts     |   7 +-
 123 files changed, 2274 insertions(+), 1910 deletions(-)
 create mode 100644 packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.ts
 create mode 100644 packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.types.ts
 delete mode 100644 packages/api/src/business/rules-demarches/_utils.test.ts
 delete mode 100644 packages/api/src/business/rules-demarches/etat-cycles.ts
 create mode 100644 packages/api/src/business/rules-demarches/prm/oct.cas.json
 create mode 100644 packages/api/src/business/rules-demarches/prm/oct.machine.test.ts
 create mode 100644 packages/api/src/business/rules-demarches/prm/oct.machine.ts
 delete mode 100644 packages/api/src/business/rules-demarches/prm/oct.test.ts
 delete mode 100644 packages/api/src/business/rules-demarches/prm/oct.ts
 delete mode 100644 packages/api/src/business/validations/titre-etape-etat-validate.test.ts
 delete mode 100644 packages/api/src/business/validations/titre-etape-etat-validate.ts
 create mode 100644 packages/api/src/knex/migrations/20230607092129_etape-ordre-not-null.ts

diff --git a/packages/api/src/api/_format/etapes-types.ts b/packages/api/src/api/_format/etapes-types.ts
index aad54eceb..0112b3527 100644
--- a/packages/api/src/api/_format/etapes-types.ts
+++ b/packages/api/src/api/_format/etapes-types.ts
@@ -97,5 +97,5 @@ export const etapeTypeIsValidCheck = (
   titreEtape.typeId = etapeTypeId
   titreEtape.date = date
 
-  return !titreDemarcheUpdatedEtatValidate(date, demarcheType, titre, titreEtape, demarcheId, titreDemarcheEtapes).length
+  return !titreDemarcheUpdatedEtatValidate(demarcheType, titre, titreEtape, demarcheId, titreDemarcheEtapes).length
 }
diff --git a/packages/api/src/api/graphql/administrations-permissions-etapes.test.integration.ts b/packages/api/src/api/graphql/administrations-permissions-etapes.test.integration.ts
index f0e6aa3c6..cfc1ad603 100644
--- a/packages/api/src/api/graphql/administrations-permissions-etapes.test.integration.ts
+++ b/packages/api/src/api/graphql/administrations-permissions-etapes.test.integration.ts
@@ -70,15 +70,9 @@ describe('Visibilité des étapes', () => {
 })
 
 describe('Création des étapes', () => {
-  test.each<[AdministrationId]>([['min-mtes-dgaln-01']])('un utilisateur admin de l’administration $administrationId peut créer une étape $etapeTypeId sur un titre CXM', async administrationId =>
-    creationCheck(dbPool, administrationId, true, 'etapes', 'cxm')
-  )
+  test('un utilisateur admin de l’administration min-mtes-dgaln-01 peut créer une étape $etapeTypeId sur un titre CXM', () => creationCheck(dbPool, 'min-mtes-dgaln-01', true, 'etapes', 'cxm'))
 
-  test.each<[AdministrationId]>([['min-mtes-dgaln-01']])('un utilisateur admin de l’administration $administrationId peut créer une étape mfr sur un titre PRM', async administrationId =>
-    creationCheck(dbPool, administrationId, true, 'etapes', 'prm')
-  )
+  test('un utilisateur admin de l’administration "min-mtes-dgaln-01" peut créer une étape mfr sur un titre PRM', () => creationCheck(dbPool, 'min-mtes-dgaln-01', true, 'etapes', 'prm'))
 
-  test.each<[AdministrationId]>([['min-mtes-dgaln-01']])('un utilisateur admin de l’administration $administrationId peut créer une étape mfr sur un titre PXM', async administrationId =>
-    creationCheck(dbPool, administrationId, true, 'etapes', 'pxm')
-  )
+  test('un utilisateur admin de l’administration "min-mtes-dgaln-01" peut créer une étape mfr sur un titre PXM', () => creationCheck(dbPool, 'min-mtes-dgaln-01', true, 'etapes', 'pxm'))
 })
diff --git a/packages/api/src/api/graphql/documents.test.integration.ts b/packages/api/src/api/graphql/documents.test.integration.ts
index dcf9a017d..55fe994ee 100644
--- a/packages/api/src/api/graphql/documents.test.integration.ts
+++ b/packages/api/src/api/graphql/documents.test.integration.ts
@@ -85,6 +85,7 @@ describe('documentSupprimer', () => {
       {
         typeId: 'mfr',
         statutId: 'aco',
+        ordre: 1,
         titreDemarcheId: titreDemarche.id,
         date: toCaminoDate('2021-01-01'),
       },
diff --git a/packages/api/src/api/graphql/resolvers/documents.ts b/packages/api/src/api/graphql/resolvers/documents.ts
index 3e66fee42..5d3c76f1d 100644
--- a/packages/api/src/api/graphql/resolvers/documents.ts
+++ b/packages/api/src/api/graphql/resolvers/documents.ts
@@ -22,6 +22,7 @@ import { documentFilePathFind } from '../../../tools/documents/document-path-fin
 import { isBureauDEtudes, isEntreprise, User } from 'camino-common/src/roles.js'
 import { canCreateOrEditEtape } from 'camino-common/src/permissions/titres-etapes.js'
 import { newDocumentId } from '../../../database/models/_format/id-create.js'
+import { EtapeId } from 'camino-common/src/etape.js'
 
 const documentFileCreate = async (document: IDocument, fileUpload: FileUpload) => {
   const documentFilePath = await documentFilePathFind(document, true)
@@ -262,7 +263,14 @@ export const documentSupprimer = async ({ id }: { id: string }, { user }: Contex
   }
 }
 
-export const documentsLier = async (context: Context, documentIds: string[], parentId: string, propParentId: 'titreActiviteId' | 'titreEtapeId', oldParent?: { documents?: IDocument[] | null }) => {
+export const documentsLier = async (
+  context: Context,
+  documentIds: string[],
+
+  { parentId, propParentId }: { parentId: EtapeId; propParentId: 'titreEtapeId' } | { parentId: string; propParentId: 'titreActiviteId' },
+
+  oldParent?: { documents?: IDocument[] | null }
+) => {
   if (oldParent?.documents?.length) {
     // supprime les anciens documents ou ceux qui n'ont pas de fichier
     const oldDocumentsIds = oldParent.documents.map(d => d.id)
@@ -284,8 +292,11 @@ export const documentsLier = async (context: Context, documentIds: string[], par
 
       if (document.fichier) {
         const documentPath = await documentFilePathFind(document)
-        document[propParentId] = parentId
-
+        if (propParentId === 'titreEtapeId') {
+          document[propParentId] = parentId
+        } else {
+          document[propParentId] = parentId
+        }
         const newDocumentPath = await documentFilePathFind(document, true)
 
         await fileRename(documentPath, newDocumentPath)
diff --git a/packages/api/src/api/graphql/resolvers/entreprises.ts b/packages/api/src/api/graphql/resolvers/entreprises.ts
index a01a2b6dc..f7c2537a2 100644
--- a/packages/api/src/api/graphql/resolvers/entreprises.ts
+++ b/packages/api/src/api/graphql/resolvers/entreprises.ts
@@ -7,6 +7,7 @@ import { titreEtapeGet } from '../../../database/queries/titres-etapes.js'
 import { fieldsBuild } from './_fields-build.js'
 
 import { entrepriseFormat } from '../../_format/entreprises.js'
+import { EtapeId } from 'camino-common/src/etape.js'
 
 const entreprisesTitresCreation = async (_: never, { user }: Context, info: GraphQLResolveInfo) => {
   try {
@@ -33,7 +34,7 @@ const entreprises = async (
     archive,
     etapeUniquement,
   }: {
-    etapeId?: string | null
+    etapeId?: EtapeId | null
     page?: number | null
     intervalle?: number | null
     ordre?: 'asc' | 'desc' | null
diff --git a/packages/api/src/api/graphql/resolvers/points.ts b/packages/api/src/api/graphql/resolvers/points.ts
index b49fb9910..ba6d38d23 100644
--- a/packages/api/src/api/graphql/resolvers/points.ts
+++ b/packages/api/src/api/graphql/resolvers/points.ts
@@ -17,6 +17,7 @@ import { titreDemarcheGet } from '../../../database/queries/titres-demarches.js'
 import { TitresStatuts } from 'camino-common/src/static/titresStatuts.js'
 import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools.js'
 import { SDOMZone, SDOMZoneId, SDOMZoneIds, SDOMZones } from 'camino-common/src/static/sdom.js'
+import { EtapeId } from 'camino-common/src/etape.js'
 
 const stream2buffer = async (stream: Stream): Promise<Buffer> => {
   return new Promise<Buffer>((resolve, reject) => {
@@ -246,7 +247,7 @@ export const titreEtapePerimetreInformations = async (
   {
     titreEtapeId,
   }: {
-    titreEtapeId: string
+    titreEtapeId: EtapeId
   },
   { user }: Context
 ): Promise<IPerimetreInformations> => {
diff --git a/packages/api/src/api/graphql/resolvers/titre-demande.ts b/packages/api/src/api/graphql/resolvers/titre-demande.ts
index f13911ab7..208b0b108 100644
--- a/packages/api/src/api/graphql/resolvers/titre-demande.ts
+++ b/packages/api/src/api/graphql/resolvers/titre-demande.ts
@@ -18,8 +18,9 @@ import { getDocuments } from 'camino-common/src/static/titresTypes_demarchesType
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { getSections, SectionsElement } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.js'
 import { DeepReadonly } from 'camino-common/src/typescript-tools.js'
+import { TitreId } from 'camino-common/src/titres.js'
 
-export const titreDemandeCreer = async ({ titreDemande }: { titreDemande: ITitreDemande & { titreFromIds?: string[] } }, { user, pool }: Context) => {
+export const titreDemandeCreer = async ({ titreDemande }: { titreDemande: ITitreDemande & { titreFromIds?: TitreId[] } }, { user, pool }: Context) => {
   try {
     assertsCanCreateTitre(user, titreDemande.typeId)
 
diff --git a/packages/api/src/api/graphql/resolvers/titres-activites.ts b/packages/api/src/api/graphql/resolvers/titres-activites.ts
index d38147b98..9d7f51a4b 100644
--- a/packages/api/src/api/graphql/resolvers/titres-activites.ts
+++ b/packages/api/src/api/graphql/resolvers/titres-activites.ts
@@ -298,7 +298,7 @@ const activiteModifier = async ({ activite }: { activite: ITitreActivite & { doc
     const fields = fieldsBuild(info)
 
     const documentIds = activite.documentIds || []
-    await documentsLier(context, documentIds, activite.id, 'titreActiviteId', oldTitreActivite)
+    await documentsLier(context, documentIds, { parentId: activite.id, propParentId: 'titreActiviteId' }, oldTitreActivite)
     delete activite.documentIds
 
     await titreActiviteUpdateQuery(activite.id, activite)
diff --git a/packages/api/src/api/graphql/resolvers/titres-etapes.ts b/packages/api/src/api/graphql/resolvers/titres-etapes.ts
index c7d51113a..e90760870 100644
--- a/packages/api/src/api/graphql/resolvers/titres-etapes.ts
+++ b/packages/api/src/api/graphql/resolvers/titres-etapes.ts
@@ -23,7 +23,7 @@ import { contenuElementFilesCreate, contenuElementFilesDelete, contenuFilesPathG
 import { documentCreate, documentsGet } from '../../../database/queries/documents.js'
 import { titreEtapeAdministrationsEmailsSend, titreEtapeUtilisateursEmailsSend } from './_titre-etape-email.js'
 import { objectClone } from '../../../tools/index.js'
-import { geojsonFeatureMultiPolygon } from '../../../tools/geojson.js'
+import { geojsonFeatureMultiPolygon, geojsonIntersectsCommunes } from '../../../tools/geojson.js'
 import { newDocumentId } from '../../../database/models/_format/id-create.js'
 import fileRename from '../../../tools/file-rename.js'
 import { documentFilePathFind } from '../../../tools/documents/document-path-find.js'
@@ -33,7 +33,7 @@ import { Feature } from 'geojson'
 import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools.js'
 import { getDocuments } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.js'
 import { isBureauDEtudes, isEntreprise, User } from 'camino-common/src/roles.js'
-import { CaminoDate, getCurrent, toCaminoDate } from 'camino-common/src/date.js'
+import { CaminoDate, toCaminoDate } from 'camino-common/src/date.js'
 import { SDOMZoneId } from 'camino-common/src/static/sdom.js'
 import { titreEtapeFormatFields } from '../../_format/_fields.js'
 import { canCreateOrEditEtape } from 'camino-common/src/permissions/titres-etapes.js'
@@ -42,6 +42,7 @@ import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js'
 import { getSections, SectionsElement } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.js'
 import { isDocumentTypeId } from 'camino-common/src/static/documentsTypes.js'
+import { EtapeId } from 'camino-common/src/etape.js'
 
 const statutIdAndDateGet = (etape: ITitreEtape, user: User, depose = false): { date: CaminoDate; statutId: EtapeStatutId } => {
   const result = { date: etape.date, statutId: etape.statutId }
@@ -62,7 +63,7 @@ const statutIdAndDateGet = (etape: ITitreEtape, user: User, depose = false): { d
   return result
 }
 
-const etape = async ({ id }: { id: string }, { user }: Context, info: GraphQLResolveInfo) => {
+const etape = async ({ id }: { id: EtapeId }, { user }: Context, info: GraphQLResolveInfo) => {
   try {
     const fields = fieldsBuild(info)
 
@@ -197,6 +198,7 @@ const etapeCreer = async ({ etape }: { etape: ITitreEtape }, context: Context, i
     const { statutId, date } = statutIdAndDateGet(etape, user!)
     etape.statutId = statutId
     etape.date = date
+    etape.surface = etape.surface ?? null
 
     const { sections, justificatifsTypes } = await specifiquesGet(titreDemarche.titre!.typeId, titreDemarche.typeId, etapeType)
 
@@ -219,6 +221,14 @@ const etapeCreer = async ({ etape }: { etape: ITitreEtape }, context: Context, i
         console.warn(`utilisation du fallback pour l'étape ${etape.id}`)
       }
       sdomZones.push(...geoJsonResult.data)
+
+      const titreEtapeCommu = await geojsonIntersectsCommunes(geojsonFeatures)
+      if (titreEtapeCommu.fallback) {
+        console.warn(`utilisation du fallback pour l'étape ${etape.id}`)
+      }
+      etape.communes = titreEtapeCommu.data
+    } else {
+      etape.communes = []
     }
 
     const typeId = titreDemarche?.titre?.typeId
@@ -226,7 +236,6 @@ const etapeCreer = async ({ etape }: { etape: ITitreEtape }, context: Context, i
       throw new Error(`le type du titre de la ${titreDemarche.id} n'est pas chargé`)
     }
     const rulesErrors = titreEtapeUpdationValidate(
-      getCurrent(),
       etape,
       titreDemarche,
       titreDemarche.titre,
@@ -269,7 +278,7 @@ const etapeCreer = async ({ etape }: { etape: ITitreEtape }, context: Context, i
 
     await contenuElementFilesCreate(newFiles, 'demarches', etapeUpdated.id)
 
-    await documentsLier(context, documentIds, etapeUpdated.id, 'titreEtapeId')
+    await documentsLier(context, documentIds, { parentId: etapeUpdated.id, propParentId: 'titreEtapeId' })
 
     try {
       await titreEtapeUpdateTask(context.pool, etapeUpdated.id, etapeUpdated.titreDemarcheId, user)
@@ -394,7 +403,6 @@ const etapeModifier = async ({ etape }: { etape: ITitreEtape }, context: Context
       throw new Error(`le type du titre de la ${titreDemarche.id} n'est pas chargé`)
     }
     const rulesErrors = titreEtapeUpdationValidate(
-      getCurrent(),
       etape,
       titreDemarche,
       titreDemarche.titre,
@@ -415,7 +423,7 @@ const etapeModifier = async ({ etape }: { etape: ITitreEtape }, context: Context
     if (titreEtapePoints) {
       etape.points = titreEtapePoints
     }
-    await documentsLier(context, documentIds, etape.id, 'titreEtapeId', titreEtapeOld)
+    await documentsLier(context, documentIds, { parentId: etape.id, propParentId: 'titreEtapeId' }, titreEtapeOld)
 
     const { contenu, newFiles } = sectionsContenuAndFilesGet(etape.contenu, sections)
     etape.contenu = contenu
@@ -461,7 +469,7 @@ const etapeModifier = async ({ etape }: { etape: ITitreEtape }, context: Context
   }
 }
 
-const etapeDeposer = async ({ id }: { id: string }, { user, pool }: Context, info: GraphQLResolveInfo) => {
+const etapeDeposer = async ({ id }: { id: EtapeId }, { user, pool }: Context, info: GraphQLResolveInfo) => {
   try {
     if (!user) {
       throw new Error("l'étape n'existe pas")
@@ -589,7 +597,7 @@ const etapeDeposer = async ({ id }: { id: string }, { user, pool }: Context, inf
   }
 }
 
-const etapeSupprimer = async ({ id }: { id: string }, { user, pool }: Context, info: GraphQLResolveInfo) => {
+const etapeSupprimer = async ({ id }: { id: EtapeId }, { user, pool }: Context, info: GraphQLResolveInfo) => {
   try {
     const fields = fieldsBuild(info)
 
@@ -651,8 +659,7 @@ const etapeSupprimer = async ({ id }: { id: string }, { user, pool }: Context, i
 
     if (!titreDemarche.titre) throw new Error("le titre n'existe pas")
 
-    const currentDate = getCurrent()
-    const rulesErrors = titreDemarcheUpdatedEtatValidate(currentDate, titreDemarche.type!, titreDemarche.titre, titreEtape, titreDemarche.id, titreDemarche.etapes!, true)
+    const rulesErrors = titreDemarcheUpdatedEtatValidate(titreDemarche.type!, titreDemarche.titre, titreEtape, titreDemarche.id, titreDemarche.etapes!, true)
 
     if (rulesErrors.length) {
       throw new Error(rulesErrors.join(', '))
diff --git a/packages/api/src/api/graphql/titres-demarches.test.integration.ts b/packages/api/src/api/graphql/titres-demarches.test.integration.ts
index 280bd4574..da9f6098d 100644
--- a/packages/api/src/api/graphql/titres-demarches.test.integration.ts
+++ b/packages/api/src/api/graphql/titres-demarches.test.integration.ts
@@ -8,6 +8,7 @@ import { toCaminoDate } from 'camino-common/src/date.js'
 
 import { afterAll, beforeAll, afterEach, describe, test, expect, vi } from 'vitest'
 import type { Pool } from 'pg'
+import { newEtapeId } from '../../database/models/_format/id-create.js'
 
 console.info = vi.fn()
 console.error = vi.fn()
@@ -220,10 +221,11 @@ describe('demarcheModifier', () => {
 
     await titreEtapeUpsert(
       {
-        id: `${demarcheId}-mno01`,
+        id: newEtapeId(`${demarcheId}-mno01`),
         typeId: 'mno',
         titreDemarcheId: demarcheId,
         statutId: 'acc',
+        ordre: 1,
         date: toCaminoDate('2020-01-01'),
       },
       userSuper,
diff --git a/packages/api/src/api/graphql/titres-etapes-modifier.test.integration.ts b/packages/api/src/api/graphql/titres-etapes-modifier.test.integration.ts
index e43db76ee..bbb9edc0c 100644
--- a/packages/api/src/api/graphql/titres-etapes-modifier.test.integration.ts
+++ b/packages/api/src/api/graphql/titres-etapes-modifier.test.integration.ts
@@ -62,6 +62,7 @@ async function etapeCreate() {
     {
       typeId: 'mfr',
       statutId: 'fai',
+      ordre: 1,
       titreDemarcheId: titreDemarche.id,
       date: toCaminoDate('2018-01-01'),
     },
diff --git a/packages/api/src/api/graphql/titres.test.integration.ts b/packages/api/src/api/graphql/titres.test.integration.ts
index 8c7fb3a0c..4b72a3feb 100644
--- a/packages/api/src/api/graphql/titres.test.integration.ts
+++ b/packages/api/src/api/graphql/titres.test.integration.ts
@@ -4,7 +4,7 @@ import { titreCreate } from '../../database/queries/titres.js'
 import { ADMINISTRATION_IDS } from 'camino-common/src/static/administrations.js'
 import { ITitre } from '../../types.js'
 import { userSuper } from '../../database/user-super'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { ACTIVITES_STATUTS_IDS } from 'camino-common/src/static/activitesStatuts.js'
 
@@ -27,7 +27,7 @@ afterAll(async () => {
 })
 
 const titrePublicLectureFalse: ITitre = {
-  id: 'titre-id',
+  id: newTitreId('titre-id'),
   nom: 'mon titre',
   typeId: 'arm',
   publicLecture: false,
@@ -35,7 +35,7 @@ const titrePublicLectureFalse: ITitre = {
 }
 
 const titreDemarchesPubliques: ITitre = {
-  id: 'titre-id',
+  id: newTitreId('titre-id'),
   nom: 'mon titre',
   typeId: 'arm',
   publicLecture: true,
@@ -43,20 +43,20 @@ const titreDemarchesPubliques: ITitre = {
   demarches: [
     {
       id: newDemarcheId('titre-id-demarche-oct'),
-      titreId: 'titre-id',
+      titreId: newTitreId('titre-id'),
       typeId: 'oct',
       publicLecture: true,
     },
     {
       id: newDemarcheId('titre-id-demarche-pro'),
-      titreId: 'titre-id',
+      titreId: newTitreId('titre-id'),
       typeId: 'pro',
       publicLecture: false,
     },
   ],
 }
 const titreEtapesPubliques: ITitre = {
-  id: 'titre-id',
+  id: newTitreId('titre-id'),
   nom: 'mon titre',
   typeId: 'arm',
   publicLecture: true,
@@ -64,13 +64,13 @@ const titreEtapesPubliques: ITitre = {
   demarches: [
     {
       id: newDemarcheId('titre-id-demarche-id'),
-      titreId: 'titre-id',
+      titreId: newTitreId('titre-id'),
       typeId: 'oct',
       statutId: 'acc',
       publicLecture: true,
       etapes: [
         {
-          id: 'titre-id-demarche-id-aof',
+          id: newEtapeId('titre-id-demarche-id-aof'),
           typeId: 'aof',
           ordre: 8,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -78,7 +78,7 @@ const titreEtapesPubliques: ITitre = {
           date: toCaminoDate('2020-02-02'),
         },
         {
-          id: 'titre-id-demarche-id-eof',
+          id: newEtapeId('titre-id-demarche-id-eof'),
           typeId: 'eof',
           ordre: 7,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -86,7 +86,7 @@ const titreEtapesPubliques: ITitre = {
           date: toCaminoDate('2020-02-02'),
         },
         {
-          id: 'titre-id-demarche-id-edm',
+          id: newEtapeId('titre-id-demarche-id-edm'),
           typeId: 'edm',
           ordre: 6,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -94,7 +94,7 @@ const titreEtapesPubliques: ITitre = {
           date: toCaminoDate('2020-02-02'),
         },
         {
-          id: 'titre-id-demarche-id-ede',
+          id: newEtapeId('titre-id-demarche-id-ede'),
           typeId: 'ede',
           ordre: 5,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -102,7 +102,7 @@ const titreEtapesPubliques: ITitre = {
           date: toCaminoDate('2020-02-02'),
         },
         {
-          id: 'titre-id-demarche-id-pfd',
+          id: newEtapeId('titre-id-demarche-id-pfd'),
           typeId: 'pfd',
           ordre: 4,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -110,7 +110,7 @@ const titreEtapesPubliques: ITitre = {
           date: toCaminoDate('2020-02-02'),
         },
         {
-          id: 'titre-id-demarche-id-pfc',
+          id: newEtapeId('titre-id-demarche-id-pfc'),
           typeId: 'pfc',
           ordre: 3,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -118,7 +118,7 @@ const titreEtapesPubliques: ITitre = {
           date: toCaminoDate('2020-02-02'),
         },
         {
-          id: 'titre-id-demarche-id-vfd',
+          id: newEtapeId('titre-id-demarche-id-vfd'),
           typeId: 'vfd',
           ordre: 2,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -126,7 +126,7 @@ const titreEtapesPubliques: ITitre = {
           date: toCaminoDate('2020-02-02'),
         },
         {
-          id: 'titre-id-demarche-id-vfc',
+          id: newEtapeId('titre-id-demarche-id-vfc'),
           typeId: 'vfc',
           ordre: 1,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -134,7 +134,7 @@ const titreEtapesPubliques: ITitre = {
           date: toCaminoDate('2020-02-02'),
         },
         {
-          id: 'titre-id-demarche-id-dpu',
+          id: newEtapeId('titre-id-demarche-id-dpu'),
           typeId: 'dpu',
           ordre: 0,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -148,14 +148,14 @@ const titreEtapesPubliques: ITitre = {
 }
 
 const titreWithActiviteGrp: ITitre = {
-  id: 'titre-id',
+  id: newTitreId('titre-id'),
   nom: 'mon titre',
   typeId: 'axm',
   publicLecture: true,
   propsTitreEtapesIds: { points: 'titre-id-demarche-id-dpu' },
   activites: [
     {
-      titreId: 'titre-id',
+      titreId: newTitreId('titre-id'),
       id: 'titre-id-grp-2020-03',
       date: toCaminoDate('2020-10-01'),
       typeId: 'grp',
@@ -187,12 +187,12 @@ const titreWithActiviteGrp: ITitre = {
   demarches: [
     {
       id: newDemarcheId('titre-id-demarche-id'),
-      titreId: 'titre-id',
+      titreId: newTitreId('titre-id'),
       typeId: 'oct',
       publicLecture: true,
       etapes: [
         {
-          id: 'titre-id-demarche-id-dpu',
+          id: newEtapeId('titre-id-demarche-id-dpu'),
           typeId: 'dpu',
           ordre: 0,
           titreDemarcheId: newDemarcheId('titre-id-demarche-id'),
@@ -206,7 +206,7 @@ const titreWithActiviteGrp: ITitre = {
 }
 
 const titreActivites: ITitre = {
-  id: 'titre-id',
+  id: newTitreId('titre-id'),
   nom: 'mon titre',
   typeId: 'arm',
   publicLecture: true,
@@ -214,7 +214,7 @@ const titreActivites: ITitre = {
   activites: [
     {
       id: 'titre-id-activites-oct',
-      titreId: 'titre-id',
+      titreId: newTitreId('titre-id'),
       typeId: 'grp',
       date: toCaminoDate('2020-01-01'),
       activiteStatutId: ACTIVITES_STATUTS_IDS.DEPOSE,
@@ -243,7 +243,7 @@ const titreActivites: ITitre = {
     },
     {
       id: 'titre-id-activites-pro',
-      titreId: 'titre-id',
+      titreId: newTitreId('titre-id'),
       typeId: 'gra',
       date: toCaminoDate('2020-01-01'),
       activiteStatutId: ACTIVITES_STATUTS_IDS.DEPOSE,
@@ -276,7 +276,7 @@ describe('titre', () => {
 
   test('peut voir un titre qui est en "lecture publique" (utilisateur anonyme)', async () => {
     const titrePublicLecture: ITitre = {
-      id: 'titre-id',
+      id: newTitreId('titre-id'),
       nom: 'mon titre',
       typeId: 'arm',
       publicLecture: true,
@@ -306,7 +306,7 @@ describe('titre', () => {
     expect(res.body.errors).toBeUndefined()
     expect(res.body.data).toMatchObject({
       titre: {
-        id: 'titre-id',
+        id: newTitreId('titre-id'),
         demarches: [{ id: 'titre-id-demarche-oct' }],
       },
     })
@@ -321,7 +321,7 @@ describe('titre', () => {
     expect(res.body.errors).toBeUndefined()
     expect(res.body.data).toMatchObject({
       titre: {
-        id: 'titre-id',
+        id: newTitreId('titre-id'),
       },
     })
 
@@ -335,7 +335,7 @@ describe('titre', () => {
     expect(res.body.errors).toBeUndefined()
     expect(res.body.data).toMatchObject({
       titre: {
-        id: 'titre-id',
+        id: newTitreId('titre-id'),
         demarches: [
           {
             id: 'titre-id-demarche-id',
diff --git a/packages/api/src/api/rest/entreprises.test.integration.ts b/packages/api/src/api/rest/entreprises.test.integration.ts
index ae6bf4d13..c0192b337 100644
--- a/packages/api/src/api/rest/entreprises.test.integration.ts
+++ b/packages/api/src/api/rest/entreprises.test.integration.ts
@@ -288,6 +288,7 @@ describe('getEntrepriseDocument', () => {
         statutId: 'fai',
         titreDemarcheId: titreDemarche.id,
         date: toCaminoDate('2022-01-01'),
+        ordre: 1,
       },
       userSuper,
       titre.id
diff --git a/packages/api/src/api/rest/entreprises.test.ts b/packages/api/src/api/rest/entreprises.test.ts
index 229e3e637..82e8c34db 100644
--- a/packages/api/src/api/rest/entreprises.test.ts
+++ b/packages/api/src/api/rest/entreprises.test.ts
@@ -3,6 +3,7 @@ import Titres from '../../database/models/titres.js'
 import { describe, expect, test } from 'vitest'
 import { newEntrepriseId } from 'camino-common/src/entreprise.js'
 import { toCommuneId } from 'camino-common/src/static/communes.js'
+import { newTitreId } from '../../database/models/_format/id-create.js'
 
 const entreprise = {
   id: newEntrepriseId('entrepriseId'),
@@ -49,19 +50,19 @@ describe('construit le corps de la requête pour openFisca', () => {
 
   test('avec activités', () => {
     const activitesAnnuelles = [
-      { titreId: 'titre2', contenu: { substancesFiscales: { auru: 39.715 } } },
-      { titreId: 'titre3', contenu: { substancesFiscales: { auru: 0 } } },
-      { titreId: 'titre1', contenu: { substancesFiscales: { auru: 0 } } },
-      { titreId: 'titre4', contenu: { substancesFiscales: { auru: 0 } } },
-      { titreId: 'titre5', contenu: { substancesFiscales: { auru: 8.91 } } },
+      { titreId: newTitreId('titre2'), contenu: { substancesFiscales: { auru: 39.715 } } },
+      { titreId: newTitreId('titre3'), contenu: { substancesFiscales: { auru: 0 } } },
+      { titreId: newTitreId('titre1'), contenu: { substancesFiscales: { auru: 0 } } },
+      { titreId: newTitreId('titre4'), contenu: { substancesFiscales: { auru: 0 } } },
+      { titreId: newTitreId('titre5'), contenu: { substancesFiscales: { auru: 8.91 } } },
     ]
     const activitesTrimestrielles = [
       {
-        titreId: 'titre2',
+        titreId: newTitreId('titre2'),
         contenu: { renseignements: { environnement: 7300 } },
       },
       {
-        titreId: 'titre3',
+        titreId: newTitreId('titre3'),
         contenu: { renseignements: { environnement: 1000 } },
       },
     ]
@@ -76,7 +77,7 @@ describe('construit le corps de la requête pour openFisca', () => {
             surface: 1006827,
           },
         ],
-        id: 'titreSansActivite',
+        id: newTitreId('titreSansActivite'),
       },
       {
         substances: ['auru', 'scoc'],
@@ -88,7 +89,7 @@ describe('construit le corps de la requête pour openFisca', () => {
         ],
         titulaires: [entreprise2],
         amodiataires: [],
-        id: 'titre1',
+        id: newTitreId('titre1'),
       },
       {
         substances: ['auru', 'scoc'],
@@ -100,7 +101,7 @@ describe('construit le corps de la requête pour openFisca', () => {
             surface: 19805494,
           },
         ],
-        id: 'titre2',
+        id: newTitreId('titre2'),
       },
       {
         substances: ['auru', 'scoc'],
@@ -112,7 +113,7 @@ describe('construit le corps de la requête pour openFisca', () => {
             surface: 5143845,
           },
         ],
-        id: 'titre3',
+        id: newTitreId('titre3'),
       },
       {
         substances: ['auru', 'scoc'],
@@ -124,7 +125,7 @@ describe('construit le corps de la requête pour openFisca', () => {
             surface: 7676552,
           },
         ],
-        id: 'titre4',
+        id: newTitreId('titre4'),
       },
       {
         substances: ['auru', 'scoc'],
@@ -136,7 +137,7 @@ describe('construit le corps de la requête pour openFisca', () => {
             surface: 35604009,
           },
         ],
-        id: 'titre5',
+        id: newTitreId('titre5'),
       },
     ]
 
diff --git a/packages/api/src/api/rest/entreprises.ts b/packages/api/src/api/rest/entreprises.ts
index ce403fef9..27e405571 100644
--- a/packages/api/src/api/rest/entreprises.ts
+++ b/packages/api/src/api/rest/entreprises.ts
@@ -46,6 +46,7 @@ import fileRename from '../../tools/file-rename.js'
 import { newDocumentId } from '../../database/models/_format/id-create.js'
 import { FICHIERS_TYPES } from 'camino-common/src/static/documentsTypes.js'
 import { dbQueryAndValidate } from '../../pg-database.js'
+import { isGuyane } from 'camino-common/src/static/pays.js'
 
 const conversion = (substanceFiscale: SubstanceFiscale, quantite: IContenuValeur): number => {
   if (typeof quantite !== 'number') {
@@ -112,9 +113,7 @@ export const bodyBuilder = (
       const titreGuyannais = titre.communes
         .map(({ id }) => toDepartementId(id))
         .filter(isNotNullNorUndefined)
-        .some(departementId => {
-          return Regions[Departements[departementId].regionId].paysId === 'GF'
-        })
+        .some(departementId => isGuyane(Regions[Departements[departementId].regionId].paysId))
 
       if (!titre.substances) {
         throw new Error(`les substances du titre ${activite.titreId} ne sont pas chargées`)
diff --git a/packages/api/src/api/rest/etapes.test.ts b/packages/api/src/api/rest/etapes.test.ts
index 263cbe3d7..380f0783d 100644
--- a/packages/api/src/api/rest/etapes.test.ts
+++ b/packages/api/src/api/rest/etapes.test.ts
@@ -1,132 +1,182 @@
-import { etapesTypesPossibleACetteDateOuALaPlaceDeLEtape, TitreEtapeForMachine } from './etapes.js'
+import { etapesTypesPossibleACetteDateOuALaPlaceDeLEtape } from './etapes.js'
 import { ArmOctMachine } from '../../business/rules-demarches/arm/oct.machine.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { describe, expect, test, vi } from 'vitest'
 import { onlyUnique } from 'camino-common/src/typescript-tools.js'
+import { newEtapeId } from '../../database/models/_format/id-create.js'
+import { TitreEtapeForMachine } from '../../business/rules-demarches/machine-common.js'
 
 describe('etapesTypesPossibleACetteDateOuALaPlaceDeLEtape', function () {
   const etapes: TitreEtapeForMachine[] = [
     {
-      id: 'etapeId16',
+      id: newEtapeId('etapeId16'),
       typeId: 'sco',
       statutId: 'fai',
       ordre: 16,
       date: toCaminoDate('2020-08-17'),
       contenu: { arm: { mecanise: true } },
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId1',
+      id: newEtapeId('etapeId1'),
       typeId: 'mfr',
       statutId: 'fai',
       ordre: 1,
       date: toCaminoDate('2019-09-19'),
       contenu: { arm: { mecanise: true, franchissements: 19 } },
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId5',
+      id: newEtapeId('etapeId5'),
       typeId: 'mcp',
       statutId: 'com',
       ordre: 5,
       date: toCaminoDate('2019-11-27'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId10',
+      id: newEtapeId('etapeId10'),
       typeId: 'aof',
       statutId: 'fav',
       ordre: 10,
       date: toCaminoDate('2019-12-04'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId9',
+      id: newEtapeId('etapeId9'),
       typeId: 'eof',
       statutId: 'fai',
       ordre: 9,
       date: toCaminoDate('2019-12-04'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId14',
+      id: newEtapeId('etapeId14'),
       typeId: 'pfc',
       statutId: 'fai',
       ordre: 14,
       date: toCaminoDate('2020-05-22'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId8',
+      id: newEtapeId('etapeId8'),
       typeId: 'mcr',
       statutId: 'fav',
       ordre: 8,
       date: toCaminoDate('2019-12-04'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId4',
+      id: newEtapeId('etapeId4'),
       typeId: 'pfd',
       statutId: 'fai',
       ordre: 4,
       date: toCaminoDate('2019-11-20'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId15',
+      id: newEtapeId('etapeId15'),
       typeId: 'vfc',
       statutId: 'fai',
       ordre: 15,
       date: toCaminoDate('2020-05-22'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId13',
+      id: newEtapeId('etapeId13'),
       typeId: 'mnb',
       statutId: 'fai',
       ordre: 13,
       date: toCaminoDate('2020-05-18'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId12',
+      id: newEtapeId('etapeId12'),
       typeId: 'aca',
       statutId: 'fav',
       ordre: 12,
       date: toCaminoDate('2020-05-13'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId6',
+      id: newEtapeId('etapeId6'),
       typeId: 'rde',
       statutId: 'fav',
       ordre: 6,
       date: toCaminoDate('2019-12-04'),
+      communes: [],
+      surface: null,
       contenu: { arm: { franchissements: 19 } },
     },
     {
-      id: 'etapeId2',
+      id: newEtapeId('etapeId2'),
       typeId: 'mdp',
       statutId: 'fai',
       ordre: 2,
       date: toCaminoDate('2019-09-20'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId7',
+      id: newEtapeId('etapeId7'),
       typeId: 'vfd',
       statutId: 'fai',
       ordre: 7,
       date: toCaminoDate('2019-12-04'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId11',
+      id: newEtapeId('etapeId11'),
       typeId: 'sca',
       statutId: 'fai',
       ordre: 11,
       date: toCaminoDate('2020-05-04'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId3',
+      id: newEtapeId('etapeId3'),
       typeId: 'dae',
       statutId: 'exe',
       ordre: 3,
       date: toCaminoDate('2019-10-11'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
     {
-      id: 'etapeId17',
+      id: newEtapeId('etapeId17'),
       typeId: 'aco',
       statutId: 'fai',
       ordre: 17,
       date: toCaminoDate('2022-05-05'),
+      contenu: null,
+      communes: [],
+      surface: null,
     },
   ]
 
@@ -166,19 +216,24 @@ describe('etapesTypesPossibleACetteDateOuALaPlaceDeLEtape', function () {
   test('peut faire une dae, une rde et pfd AVANT la mfr', () => {
     const etapes: TitreEtapeForMachine[] = [
       {
-        id: 'idMfr',
-
+        id: newEtapeId('idMfr'),
+        ordre: 1,
         typeId: 'mfr',
         statutId: 'fai',
         date: toCaminoDate('2022-05-16'),
         contenu: { arm: { mecanise: true, franchissements: 2 } },
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idMdp',
-
+        id: newEtapeId('idMdp'),
+        ordre: 2,
         typeId: 'mdp',
         statutId: 'fai',
         date: toCaminoDate('2022-05-17'),
+        contenu: null,
+        communes: [],
+        surface: null,
       },
     ]
 
@@ -191,17 +246,24 @@ describe('etapesTypesPossibleACetteDateOuALaPlaceDeLEtape', function () {
   test('peut faire que une pfd AVANT la mfr non mecanisee', () => {
     const etapes: TitreEtapeForMachine[] = [
       {
-        id: 'idMfr',
+        id: newEtapeId('idMfr'),
+        ordre: 1,
         typeId: 'mfr',
         statutId: 'fai',
         date: toCaminoDate('2022-05-16'),
         contenu: { arm: { mecanise: false } },
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idMdp',
+        id: newEtapeId('idMdp'),
+        ordre: 2,
         typeId: 'mdp',
         statutId: 'fai',
         date: toCaminoDate('2022-05-17'),
+        contenu: null,
+        communes: [],
+        surface: null,
       },
     ]
 
@@ -215,7 +277,7 @@ describe('etapesTypesPossibleACetteDateOuALaPlaceDeLEtape', function () {
     console.warn = vi.fn()
     const etapes: TitreEtapeForMachine[] = [
       {
-        id: 'idMfr',
+        id: newEtapeId('idMfr'),
         date: toCaminoDate('2021-11-02'),
         typeId: 'mfr',
         statutId: 'fai',
@@ -226,9 +288,11 @@ describe('etapesTypesPossibleACetteDateOuALaPlaceDeLEtape', function () {
           },
         },
         ordre: 3,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idrcm',
+        id: newEtapeId('idrcm'),
         date: toCaminoDate('2021-11-17'),
         typeId: 'rcm',
         statutId: 'fai',
@@ -239,86 +303,120 @@ describe('etapesTypesPossibleACetteDateOuALaPlaceDeLEtape', function () {
           },
         },
         ordre: 7,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idMcp',
+        id: newEtapeId('idMcp'),
         date: toCaminoDate('2021-11-05'),
         typeId: 'mcp',
         statutId: 'inc',
         ordre: 5,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idmcp',
+        id: newEtapeId('idmcp'),
         date: toCaminoDate('2021-11-17'),
         typeId: 'mcp',
         statutId: 'com',
         ordre: 8,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'ideof',
+        id: newEtapeId('ideof'),
         date: toCaminoDate('2021-11-22'),
         typeId: 'eof',
         statutId: 'fai',
         ordre: 11,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'iddae',
+        id: newEtapeId('iddae'),
         date: toCaminoDate('2021-10-15'),
         typeId: 'dae',
         statutId: 'exe',
 
         ordre: 1,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idmcr',
+        id: newEtapeId('idmcr'),
         date: toCaminoDate('2021-11-22'),
         typeId: 'mcr',
         statutId: 'fav',
         contenu: null,
         ordre: 10,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idmcb',
+        id: newEtapeId('idmcb'),
         date: toCaminoDate('2021-12-09'),
         typeId: 'mcb',
         statutId: 'fai',
 
         ordre: 13,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idedm',
+        id: newEtapeId('idedm'),
         date: toCaminoDate('2021-11-30'),
         typeId: 'edm',
         statutId: 'fav',
         ordre: 12,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idvfd',
+        id: newEtapeId('idvfd'),
         date: toCaminoDate('2021-11-19'),
         typeId: 'vfd',
         statutId: 'fai',
         ordre: 9,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idpfd',
+        id: newEtapeId('idpfd'),
         date: toCaminoDate('2021-10-26'),
         typeId: 'pfd',
         statutId: 'fai',
         ordre: 2,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idmdp',
+        id: newEtapeId('idmdp'),
         date: toCaminoDate('2021-11-02'),
         typeId: 'mdp',
         statutId: 'fai',
         ordre: 4,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'idmcm',
+        id: newEtapeId('idmcm'),
         date: toCaminoDate('2021-11-05'),
         typeId: 'mcm',
         statutId: 'fai',
         ordre: 6,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
     ]
 
@@ -331,7 +429,7 @@ describe('etapesTypesPossibleACetteDateOuALaPlaceDeLEtape', function () {
   test('peut faire une completude (mcp) le même jour que le dépôt (mdp) de la demande', () => {
     const etapes: TitreEtapeForMachine[] = [
       {
-        id: 'id3',
+        id: newEtapeId('id3'),
         typeId: 'mfr',
         statutId: 'fai',
         date: toCaminoDate('2022-06-23'),
@@ -342,29 +440,40 @@ describe('etapesTypesPossibleACetteDateOuALaPlaceDeLEtape', function () {
           },
         },
         ordre: 3,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'id1',
+        id: newEtapeId('id1'),
         typeId: 'dae',
         statutId: 'exe',
         date: toCaminoDate('2021-06-22'),
         ordre: 1,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'id4',
+        id: newEtapeId('id4'),
 
         typeId: 'mdp',
         statutId: 'fai',
         date: toCaminoDate('2022-07-01'),
         ordre: 4,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
       {
-        id: 'id2',
+        id: newEtapeId('id2'),
 
         typeId: 'pfd',
         statutId: 'fai',
         date: toCaminoDate('2021-07-05'),
         ordre: 2,
+        contenu: null,
+        communes: [],
+        surface: null,
       },
     ]
 
diff --git a/packages/api/src/api/rest/etapes.ts b/packages/api/src/api/rest/etapes.ts
index b8e2601ba..21a1f55f4 100644
--- a/packages/api/src/api/rest/etapes.ts
+++ b/packages/api/src/api/rest/etapes.ts
@@ -1,21 +1,20 @@
 import { z } from 'zod'
 import { CaminoRequest, CustomResponse } from './express-type.js'
-import { EtapeTypeEtapeStatutWithMainStep } from 'camino-common/src/etape.js'
+import { EtapeTypeEtapeStatutWithMainStep, etapeIdValidator, EtapeId } from 'camino-common/src/etape.js'
 import { DemarcheId, demarcheIdValidator } from 'camino-common/src/demarche.js'
 import { constants } from 'http2'
 import { CaminoDate, caminoDateValidator } from 'camino-common/src/date.js'
 import { titreDemarcheGet } from '../../database/queries/titres-demarches.js'
 import { userSuper } from '../../database/user-super.js'
 import { titreEtapeGet } from '../../database/queries/titres-etapes.js'
-import { demarcheDefinitionFind, isDemarcheDefinitionMachine } from '../../business/rules-demarches/definitions.js'
-import { ITitreEtape } from '../../types.js'
+import { demarcheDefinitionFind } from '../../business/rules-demarches/definitions.js'
 import { etapeTypeIsValidCheck } from '../_format/etapes-types.js'
 import { User } from 'camino-common/src/roles.js'
 import { canCreateOrEditEtape } from 'camino-common/src/permissions/titres-etapes.js'
 import { TitresStatutIds } from 'camino-common/src/static/titresStatuts.js'
 import { CaminoMachines } from '../../business/rules-demarches/machines.js'
 import { titreEtapesSortAscByOrdre } from '../../business/utils/titre-etapes-sort.js'
-import { Etape, toMachineEtapes } from '../../business/rules-demarches/machine-common.js'
+import { Etape, TitreEtapeForMachine, titreEtapeForMachineValidator, toMachineEtapes } from '../../business/rules-demarches/machine-common.js'
 import { EtapesTypes, EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
 import { onlyUnique } from 'camino-common/src/typescript-tools.js'
 import { getEtapesTDE } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index.js'
@@ -28,7 +27,7 @@ export const getEtapesTypesEtapesStatusWithMainStep =
   async (req: CaminoRequest, res: CustomResponse<EtapeTypeEtapeStatutWithMainStep[]>): Promise<void> => {
     const demarcheIdParsed = demarcheIdValidator.safeParse(req.params.demarcheId)
     const dateParsed = caminoDateValidator.safeParse(req.params.date)
-    const etapeIdParsed = z.optional(z.string()).safeParse(req.query.etapeId)
+    const etapeIdParsed = z.optional(etapeIdValidator).safeParse(req.query.etapeId)
     const user = req.auth
 
     if (!demarcheIdParsed.success || !dateParsed.success || !etapeIdParsed.success) {
@@ -44,7 +43,7 @@ export const getEtapesTypesEtapesStatusWithMainStep =
     }
   }
 
-const demarcheEtapesTypesGet = async (titreDemarcheId: DemarcheId, date: CaminoDate, titreEtapeId: string | null, user: User) => {
+const demarcheEtapesTypesGet = async (titreDemarcheId: DemarcheId, date: CaminoDate, titreEtapeId: EtapeId | null, user: User) => {
   const titreDemarche = await titreDemarcheGet(
     titreDemarcheId,
     {
@@ -82,24 +81,21 @@ const demarcheEtapesTypesGet = async (titreDemarcheId: DemarcheId, date: CaminoD
     }
   }
 
-  // si il existe un arbre d’instructions pour cette démarche,
-  // on laisse l’arbre traiter l’unicité des étapes
   const demarcheDefinition = demarcheDefinitionFind(titre.typeId, titreDemarche.typeId, titreDemarche.etapes, titreDemarche.id)
 
   const etapesTypes: EtapeTypeEtapeStatutWithMainStep[] = []
-  if (isDemarcheDefinitionMachine(demarcheDefinition)) {
+  if (demarcheDefinition) {
     if (!titreDemarche.etapes) throw new Error('les étapes ne sont pas chargées')
-    etapesTypes.push(...etapesTypesPossibleACetteDateOuALaPlaceDeLEtape(demarcheDefinition.machine, titreDemarche.etapes, titreEtapeId, date))
+    const etapes = titreDemarche.etapes.map(etape => titreEtapeForMachineValidator.parse(etape))
+    etapesTypes.push(...etapesTypesPossibleACetteDateOuALaPlaceDeLEtape(demarcheDefinition.machine, etapes, titreEtapeId, date))
   } else {
     // dans un premier temps on récupère toutes les étapes possibles pour cette démarche
     let etapesTypesTDE = getEtapesTDE(titre.typeId, titreDemarche.typeId)
 
-    if (!demarcheDefinition) {
-      const etapeTypesExistants = titreDemarche.etapes?.map(({ typeId }) => typeId) ?? []
-      etapesTypesTDE = etapesTypesTDE
-        .filter(typeId => !etapeTypesExistants.includes(typeId) || !EtapesTypes[typeId].unique)
-        .filter(etapeTypeId => etapeTypeIsValidCheck(etapeTypeId, date, titre, titreDemarche.type!, titreDemarche.id, titreDemarche.etapes, titreEtape))
-    }
+    const etapeTypesExistants = titreDemarche.etapes?.map(({ typeId }) => typeId) ?? []
+    etapesTypesTDE = etapesTypesTDE
+      .filter(typeId => !etapeTypesExistants.includes(typeId) || !EtapesTypes[typeId].unique)
+      .filter(etapeTypeId => etapeTypeIsValidCheck(etapeTypeId, date, titre, titreDemarche.type!, titreDemarche.id, titreDemarche.etapes, titreEtape))
     etapesTypes.push(...etapesTypesTDE.flatMap(etapeTypeId => getEtapesStatuts(etapeTypeId).map(etapeStatut => ({ etapeTypeId, etapeStatutId: etapeStatut.id, mainStep: false }))))
   }
 
@@ -120,7 +116,6 @@ const demarcheEtapesTypesGet = async (titreDemarcheId: DemarcheId, date: CaminoD
   )
 }
 
-export type TitreEtapeForMachine = Pick<ITitreEtape, 'ordre' | 'id' | 'typeId' | 'statutId' | 'date' | 'contenu'>
 // VISIBLE_FOR_TESTING
 export const etapesTypesPossibleACetteDateOuALaPlaceDeLEtape = (
   machine: CaminoMachines,
diff --git a/packages/api/src/api/rest/fichiers.ts b/packages/api/src/api/rest/fichiers.ts
index 8f24cc190..af1755f01 100644
--- a/packages/api/src/api/rest/fichiers.ts
+++ b/packages/api/src/api/rest/fichiers.ts
@@ -10,10 +10,11 @@ import { statSync, readFileSync } from 'fs'
 import { User } from 'camino-common/src/roles'
 import { DOWNLOAD_FORMATS } from 'camino-common/src/rest.js'
 import { Pool } from 'pg'
+import { EtapeId } from 'camino-common/src/etape.js'
 
 export const etapeTelecharger =
   (_pool: Pool) =>
-  async ({ params: { etapeId } }: { params: { etapeId?: string } }, user: User) => {
+  async ({ params: { etapeId } }: { params: { etapeId?: EtapeId } }, user: User) => {
     if (!etapeId) {
       throw new Error("id d'étape absent")
     }
@@ -146,7 +147,7 @@ const etapeIdPathGet = (etapeId: string, fichierNom: string, contenu: IContenuVa
 
 export const etapeFichier =
   (_pool: Pool) =>
-  async ({ params: { etapeId, fichierNom } }: { params: { etapeId?: string; fichierNom?: string } }, user: User) => {
+  async ({ params: { etapeId, fichierNom } }: { params: { etapeId?: EtapeId; fichierNom?: string } }, user: User) => {
     if (!etapeId) {
       throw new Error('id de l’étape absent')
     }
diff --git a/packages/api/src/api/rest/titre-contenu.test.ts b/packages/api/src/api/rest/titre-contenu.test.ts
index d821d6c1f..cec13b60e 100644
--- a/packages/api/src/api/rest/titre-contenu.test.ts
+++ b/packages/api/src/api/rest/titre-contenu.test.ts
@@ -1,3 +1,4 @@
+import { newEtapeId } from '../../database/models/_format/id-create.js'
 import { contenuFormat, titreSectionsGet } from './titre-contenu.js'
 import { describe, test, expect } from 'vitest'
 describe('formatage du contenu', () => {
@@ -11,7 +12,7 @@ describe('formatage du contenu', () => {
           {
             etapes: [
               {
-                id: 'etape-id',
+                id: newEtapeId('etape-id'),
                 contenu: {
                   section: {
                     prop1: 'valeur 1',
@@ -75,7 +76,7 @@ describe('titreSectionsGet', () => {
             typeId: 'oct',
             etapes: [
               {
-                id: 'etape-id',
+                id: newEtapeId('etape-id'),
                 typeId: 'mfr',
                 contenu: {
                   arm: {
diff --git a/packages/api/src/api/rest/titres.test.integration.ts b/packages/api/src/api/rest/titres.test.integration.ts
index b2c638a50..73216f556 100644
--- a/packages/api/src/api/rest/titres.test.integration.ts
+++ b/packages/api/src/api/rest/titres.test.integration.ts
@@ -14,18 +14,19 @@ import { newEntrepriseId } from 'camino-common/src/entreprise.js'
 import type { Pool } from 'pg'
 import { createJournalCreate } from '../../database/queries/journaux.js'
 import { dbQueryAndValidate } from '../../pg-database.js'
-import { idGenerate } from '../../database/models/_format/id-create.js'
+import { idGenerate, newTitreId } from '../../database/models/_format/id-create.js'
 import { constants } from 'http2'
 import { toCommuneId } from 'camino-common/src/static/communes.js'
 import { z } from 'zod'
 import { insertCommune } from '../../database/queries/communes.queries.js'
+import { TitreId } from 'camino-common/src/titres.js'
 
 console.info = vi.fn()
 console.error = vi.fn()
 
 let knex: Knex<any, unknown[]>
 let dbPool: Pool
-let titreId1: string | null = null
+let titreId1: TitreId | null = null
 beforeAll(async () => {
   const { knex: knexInstance, pool } = await dbManager.populateDb()
   dbPool = pool
@@ -295,7 +296,7 @@ describe('titresLiaisons', () => {
 })
 
 describe('titreModifier', () => {
-  let id = ''
+  let id = newTitreId('')
 
   beforeEach(async () => {
     const titre = await titreCreate(
@@ -377,7 +378,7 @@ describe('titreModifier', () => {
 })
 
 describe('titreSupprimer', () => {
-  let id = ''
+  let id = newTitreId('')
 
   beforeEach(async () => {
     const titre = await titreCreate(
@@ -404,20 +405,20 @@ describe('titreSupprimer', () => {
   })
 
   test('ne peut pas supprimer un titre inexistant (utilisateur super)', async () => {
-    const tested = await restDeleteCall(dbPool, '/rest/titres/:titreId', { titreId: 'toto' }, userSuper)
+    const tested = await restDeleteCall(dbPool, '/rest/titres/:titreId', { titreId: newTitreId('toto') }, userSuper)
     expect(tested.statusCode).toBe(404)
   })
 })
 
 describe('getTitre', () => {
   test('ne peut pas récupérer un titre (utilisateur non super)', async () => {
-    const tested = await restCall(dbPool, '/rest/titres/:titreId', { titreId: 'not existing' }, undefined)
+    const tested = await restCall(dbPool, '/rest/titres/:titreId', { titreId: newTitreId('not existing') }, undefined)
 
     expect(tested.statusCode).toBe(403)
   })
 
   test('ne peut pas récupérer un titre inexistant', async () => {
-    const tested = await restCall(dbPool, '/rest/titres/:titreId', { titreId: 'not existing' }, userSuper)
+    const tested = await restCall(dbPool, '/rest/titres/:titreId', { titreId: newTitreId('not existing') }, userSuper)
 
     expect(tested.statusCode).toBe(404)
   })
@@ -528,12 +529,12 @@ test('utilisateurTitreAbonner', async () => {
 })
 
 test('peut récupérer les communes d’un titre', async () => {
-  let tested = await restCall(dbPool, '/rest/titres/:id/communes', { id: titreId1 ?? '' }, userSuper)
+  let tested = await restCall(dbPool, '/rest/titres/:id/communes', { id: newTitreId(titreId1 ?? '') }, userSuper)
 
   expect(tested.statusCode).toBe(200)
   expect(tested.body).toEqual([{ id: '97300', nom: 'Une ville en Guyane' }])
 
-  tested = await restCall(dbPool, '/rest/titres/:id/communes', { id: titreId1 ?? '' }, undefined)
+  tested = await restCall(dbPool, '/rest/titres/:id/communes', { id: newTitreId(titreId1 ?? '') }, undefined)
 
   expect(tested.statusCode).toBe(403)
 })
diff --git a/packages/api/src/api/rest/titres.ts b/packages/api/src/api/rest/titres.ts
index f1acd4613..04b79a89a 100644
--- a/packages/api/src/api/rest/titres.ts
+++ b/packages/api/src/api/rest/titres.ts
@@ -17,8 +17,9 @@ import {
   titrePtmgValidator,
   titreLinksValidator,
   utilisateurTitreAbonneValidator,
+  titreIdValidator,
 } from 'camino-common/src/titres.js'
-import { demarcheDefinitionFind, isDemarcheDefinitionMachine } from '../../business/rules-demarches/definitions.js'
+import { demarcheDefinitionFind } from '../../business/rules-demarches/definitions.js'
 import { CaminoRequest, CustomResponse } from './express-type.js'
 import { userSuper } from '../../database/user-super.js'
 import { NotNullableKeys, onlyUnique } from 'camino-common/src/typescript-tools.js'
@@ -27,7 +28,7 @@ import { titreAdministrationsGet } from '../_format/titres.js'
 import { canDeleteTitre, canLinkTitres } from 'camino-common/src/permissions/titres.js'
 import { linkTitres } from '../../database/queries/titres-titres.js'
 import { checkTitreLinks } from '../../business/validations/titre-links-validate.js'
-import { toMachineEtapes } from '../../business/rules-demarches/machine-common.js'
+import { titreEtapeForMachineValidator, toMachineEtapes } from '../../business/rules-demarches/machine-common.js'
 import { TitreReference } from 'camino-common/src/titres-references.js'
 import { DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts.js'
 import { ETAPES_TYPES, EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
@@ -40,6 +41,7 @@ import { getLastJournal, getTitre as getTitreDb, lastJournalGetValidator, getTit
 import type { Pool } from 'pg'
 import { dbQueryAndValidate } from '../../pg-database.js'
 import { Commune, communeValidator } from 'camino-common/src/static/communes.js'
+import { z } from 'zod'
 
 const etapesAMasquer = [
   ETAPES_TYPES.classementSansSuite,
@@ -160,8 +162,8 @@ async function titresArmAvecOctroi(user: User, administrationId: AdministrationI
       }
 
       const dd = demarcheDefinitionFind(titre.typeId, octARM.typeId, octARM.etapes, octARM.id)
-      const hasMachine = isDemarcheDefinitionMachine(dd)
-      const blockedByMe: boolean = hasMachine && dd.machine.whoIsBlocking(toMachineEtapes(octARM.etapes)).includes(administrationId)
+      const etapes = octARM.etapes.map(etape => titreEtapeForMachineValidator.parse(etape))
+      const blockedByMe: boolean = dd !== undefined && dd.machine.whoIsBlocking(toMachineEtapes(etapes)).includes(administrationId)
 
       // TODO 2022-06-08 wait for typescript to get better at type interpolation
       return {
@@ -306,10 +308,11 @@ export const titresDREAL = (_pool: Pool) => async (req: CaminoRequest, res: Cust
             if (demarcheLaPlusRecente.statutId === DemarchesStatutsIds.EnConstruction) {
               return null
             } else {
-              const etapesDerniereDemarche = toMachineEtapes(demarcheLaPlusRecente.etapes)
+              const etapes = demarcheLaPlusRecente.etapes.map(etape => titreEtapeForMachineValidator.parse(etape))
+              const etapesDerniereDemarche = toMachineEtapes(etapes)
               derniereEtape = etapesDerniereDemarche[etapesDerniereDemarche.length - 1]
               const dd = demarcheDefinitionFind(titre.typeId, demarcheLaPlusRecente.typeId, demarcheLaPlusRecente.etapes, demarcheLaPlusRecente.id)
-              if (isDemarcheDefinitionMachine(dd)) {
+              if (dd) {
                 try {
                   enAttenteDeDREAL = dd.machine.whoIsBlocking(etapesDerniereDemarche).includes(user.administrationId)
                   const nextEtapes = dd.machine.possibleNextEtapes(etapesDerniereDemarche, getCurrent())
@@ -359,25 +362,23 @@ export const titresDREAL = (_pool: Pool) => async (req: CaminoRequest, res: Cust
     }
   }
 }
-const isStringArray = (stuff: any): stuff is string[] => {
-  return stuff instanceof Array && stuff.every(value => typeof value === 'string')
-}
+
 export const postTitreLiaisons = (_pool: Pool) => async (req: CaminoRequest, res: CustomResponse<TitreLinks>) => {
   const user = req.auth
 
-  const titreId = req.params.id
-  const titreFromIds = req.body
+  const titreId = titreIdValidator.safeParse(req.params.id)
+  const titreFromIds = z.array(titreIdValidator).safeParse(req.body)
 
-  if (!isStringArray(titreFromIds)) {
+  if (!titreFromIds.success) {
     throw new Error(`un tableau est attendu en corps de message : '${titreFromIds}'`)
   }
 
-  if (!titreId) {
+  if (!titreId.success) {
     throw new Error('le paramètre id est obligatoire')
   }
 
   const titre = await titreGet(
-    titreId,
+    titreId.data,
     {
       fields: {
         pointsEtape: { id: {} },
@@ -396,15 +397,15 @@ export const postTitreLiaisons = (_pool: Pool) => async (req: CaminoRequest, res
     throw new Error('les démarches ne sont pas chargées')
   }
 
-  const titresFrom = await titresGet({ ids: titreFromIds }, { fields: { id: {} } }, user)
+  const titresFrom = await titresGet({ ids: titreFromIds.data }, { fields: { id: {} } }, user)
 
-  checkTitreLinks(titre, titreFromIds, titresFrom, titre.demarches)
+  checkTitreLinks(titre, titreFromIds.data, titresFrom, titre.demarches)
 
-  await linkTitres({ linkTo: titreId, linkFrom: titreFromIds })
+  await linkTitres({ linkTo: titreId.data, linkFrom: titreFromIds.data })
 
   res.json({
-    amont: await titreLinksGet(titreId, 'titreFromId', user),
-    aval: await titreLinksGet(titreId, 'titreToId', user),
+    amont: await titreLinksGet(titreId.data, 'titreFromId', user),
+    aval: await titreLinksGet(titreId.data, 'titreToId', user),
   })
 }
 export const getTitreLiaisons = (_pool: Pool) => async (req: CaminoRequest, res: CustomResponse<TitreLinks>) => {
@@ -459,12 +460,12 @@ const titreLinksGet = async (titreId: string, link: 'titreToId' | 'titreFromId',
 export const removeTitre = (_pool: Pool) => async (req: CaminoRequest, res: CustomResponse<void>) => {
   const user = req.auth
 
-  const titreId: string | undefined = req.params.titreId
-  if (!titreId) {
+  const titreId = titreIdValidator.safeParse(req.params.titreId)
+  if (!titreId.success) {
     res.sendStatus(constants.HTTP_STATUS_BAD_REQUEST)
   } else {
     const titreOld = await titreGet(
-      titreId,
+      titreId.data,
       {
         fields: {
           demarches: { etapes: { id: {} } },
@@ -479,7 +480,7 @@ export const removeTitre = (_pool: Pool) => async (req: CaminoRequest, res: Cust
     } else if (!canDeleteTitre(user)) {
       res.sendStatus(constants.HTTP_STATUS_FORBIDDEN)
     } else {
-      await titreArchive(titreId)
+      await titreArchive(titreId.data)
       res.sendStatus(constants.HTTP_STATUS_NO_CONTENT)
     }
   }
diff --git a/packages/api/src/business/daily.ts b/packages/api/src/business/daily.ts
index 5cab8f444..3e1f6b0d5 100644
--- a/packages/api/src/business/daily.ts
+++ b/packages/api/src/business/daily.ts
@@ -30,11 +30,11 @@ export const daily = async (pool: Pool) => {
     console.info('- - -')
     console.info('mise à jour quotidienne')
 
-    const titresEtapesOrdreUpdated = await titresEtapesOrdreUpdate(userSuper)
+    const titresEtapesOrdreUpdated = await titresEtapesOrdreUpdate(pool, userSuper)
     const titresEtapesHeritagePropsUpdated = await titresEtapesHeritagePropsUpdate(userSuper)
-    const titresEtapesHeritageContenuUpdated = await titresEtapesHeritageContenuUpdate(userSuper)
+    const titresEtapesHeritageContenuUpdated = await titresEtapesHeritageContenuUpdate(pool, userSuper)
 
-    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate()
+    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate(pool)
     const titresDemarchesOrdreUpdated = await titresDemarchesOrdreUpdate()
     const [titresDemarchesDatesUpdated = []] = await titresDemarchesDatesUpdate(pool)
     const titresDemarchesPublicUpdated = await titresDemarchesPublicUpdate()
diff --git a/packages/api/src/business/matrices.test.ts b/packages/api/src/business/matrices.test.ts
index 3f3384ee5..414a96930 100644
--- a/packages/api/src/business/matrices.test.ts
+++ b/packages/api/src/business/matrices.test.ts
@@ -4,6 +4,7 @@ import { newEntrepriseId } from 'camino-common/src/entreprise.js'
 import { describe, expect, test } from 'vitest'
 import { checkCodePostal } from 'camino-common/src/static/departement.js'
 import { toCommuneId } from 'camino-common/src/static/communes.js'
+import { newTitreId } from '../database/models/_format/id-create.js'
 describe('matrices', () => {
   test('buildMatrices', () => {
     const openFiscaResponse = {
@@ -84,7 +85,7 @@ describe('matrices', () => {
     }
     const titres: Pick<ITitre, 'id' | 'slug' | 'titulaires' | 'communes'>[] = [
       {
-        id: 'titre1',
+        id: newTitreId('titre1'),
         titulaires: [
           {
             id: newEntrepriseId(''),
@@ -101,7 +102,7 @@ describe('matrices', () => {
         ],
       },
       {
-        id: 'titre2',
+        id: newTitreId('titre2'),
         titulaires: [
           {
             id: newEntrepriseId(''),
@@ -121,7 +122,7 @@ describe('matrices', () => {
         ],
       },
       {
-        id: 'titre3',
+        id: newTitreId('titre3'),
         titulaires: [
           {
             id: newEntrepriseId(''),
diff --git a/packages/api/src/business/processes/__mocks__/titres-activites-update-titres.ts b/packages/api/src/business/processes/__mocks__/titres-activites-update-titres.ts
index 92a5b5960..134d50ce8 100644
--- a/packages/api/src/business/processes/__mocks__/titres-activites-update-titres.ts
+++ b/packages/api/src/business/processes/__mocks__/titres-activites-update-titres.ts
@@ -1,9 +1,10 @@
+import { newTitreId } from '../../../database/models/_format/id-create.js'
 import ActivitesTypes from '../../../database/models/activites-types.js'
 import Titres from '../../../database/models/titres.js'
 
 const titresSansActivite = [
   {
-    id: 'h-cx-courdemanges-1988',
+    id: newTitreId('h-cx-courdemanges-1988'),
     activites: [],
     titulaires: [{ utilisateurs: [{ email: 'email' }] }],
   },
@@ -11,7 +12,7 @@ const titresSansActivite = [
 
 const titresToutesActivites = [
   {
-    id: 'h-cx-courdemanges-1988',
+    id: newTitreId('h-cx-courdemanges-1988'),
     activites: [
       { annee: 2018, periodeId: 1 },
       { annee: 2018, periodeId: 2 },
diff --git a/packages/api/src/business/processes/__snapshots__/titres-etapes-areas-update.test.integration.ts.snap b/packages/api/src/business/processes/__snapshots__/titres-etapes-areas-update.test.integration.ts.snap
index 98e5f5e78..14a374a47 100644
--- a/packages/api/src/business/processes/__snapshots__/titres-etapes-areas-update.test.integration.ts.snap
+++ b/packages/api/src/business/processes/__snapshots__/titres-etapes-areas-update.test.integration.ts.snap
@@ -29,7 +29,7 @@ exports[`titresEtapesAreasUpdate > met à jour les communes, forêts et zone du
     "heritageProps": null,
     "id": "titreEtapeIdUniquePourMiseAJourAreas",
     "incertitudes": null,
-    "ordre": null,
+    "ordre": 0,
     "sdomZones": [
       "1",
     ],
@@ -95,7 +95,7 @@ exports[`titresEtapesAreasUpdate > met à jour les communes, forêts et zone du
       "heritageProps": null,
       "id": "titreEtapeIdUniquePourMiseAJourAreas",
       "incertitudes": null,
-      "ordre": null,
+      "ordre": 0,
       "sdomZones": [
         "1",
       ],
diff --git a/packages/api/src/business/processes/titres-demarches-depot-create.ts b/packages/api/src/business/processes/titres-demarches-depot-create.ts
index 47e3ad614..52bea47ee 100644
--- a/packages/api/src/business/processes/titres-demarches-depot-create.ts
+++ b/packages/api/src/business/processes/titres-demarches-depot-create.ts
@@ -50,7 +50,7 @@ const titreEtapeDepotConfirmationEmailsSend = async (titreDemarche: ITitreDemarc
 // visibleForTesting
 export const titreDemarcheDepotCheck = (titreDemarche: ITitreDemarche): boolean => {
   const demarcheDefinition = demarcheDefinitionFind(titreDemarche.titre!.typeId, titreDemarche.typeId, titreDemarche.etapes, titreDemarche.id)
-  // On peut déposer automatiquement seulement les démarches qui possèdent un arbre d’instructions
+  // On peut déposer automatiquement seulement les démarches qui possèdent une machine
   if (!demarcheDefinition) return false
   if (titreDemarche.titre!.typeId === 'arm' && titreDemarche.typeId === 'oct') {
     // Si on a pas de demande faite
diff --git a/packages/api/src/business/processes/titres-demarches-statut-ids-update.test.ts b/packages/api/src/business/processes/titres-demarches-statut-ids-update.test.ts
index ca7b1a871..431d6e0c0 100644
--- a/packages/api/src/business/processes/titres-demarches-statut-ids-update.test.ts
+++ b/packages/api/src/business/processes/titres-demarches-statut-ids-update.test.ts
@@ -1,8 +1,9 @@
 import { titresDemarchesStatutIdUpdate } from './titres-demarches-statut-ids-update.js'
 import { vi, describe, expect, test } from 'vitest'
 import { getDemarches } from './titres-etapes-heritage-contenu-update.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
+import { Pool } from 'pg'
 
 vi.mock('./titres-etapes-heritage-contenu-update', () => ({
   getDemarches: vi.fn().mockResolvedValue(true),
@@ -21,31 +22,37 @@ describe("statut des démarches d'un titre", () => {
     getDemarchesMock.mockResolvedValue({
       [newDemarcheId('')]: {
         id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-        titreId: 'h-cx-courdemanges-1988',
+        titreId: newTitreId('h-cx-courdemanges-1988'),
         titreTypeId: 'cxh',
         typeId: 'oct',
         statutId: 'rej',
         etapes: [
           {
-            id: 'h-cx-courdemanges-1988-oct01-dpu01',
-            titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
+            id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
             typeId: 'dpu',
             statutId: 'acc',
             ordre: 2,
             date: toCaminoDate('1988-03-11'),
+            communes: [],
+            contenu: {},
+            heritageContenu: {},
+            surface: null,
           },
           {
-            id: 'h-cx-courdemanges-1988-oct01-dex01',
-            titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
+            id: newEtapeId('h-cx-courdemanges-1988-oct01-dex01'),
             typeId: 'dex',
             statutId: 'acc',
             ordre: 1,
             date: toCaminoDate('1988-03-06'),
+            communes: [],
+            contenu: {},
+            heritageContenu: {},
+            surface: null,
           },
         ],
       },
     })
-    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate()
+    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate(undefined as unknown as Pool)
 
     expect(titresDemarchesStatutUpdated.length).toEqual(1)
   })
@@ -54,31 +61,37 @@ describe("statut des démarches d'un titre", () => {
     getDemarchesMock.mockResolvedValue({
       [newDemarcheId('')]: {
         id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-        titreId: 'h-cx-courdemanges-1988',
+        titreId: newTitreId('h-cx-courdemanges-1988'),
         titreTypeId: 'cxh',
         typeId: 'oct',
         statutId: 'acc',
         etapes: [
           {
-            id: 'h-cx-courdemanges-1988-oct01-dpu01',
-            titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
+            id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
             typeId: 'dpu',
             statutId: 'acc',
             ordre: 2,
             date: toCaminoDate('1988-03-11'),
+            communes: [],
+            contenu: {},
+            heritageContenu: {},
+            surface: null,
           },
           {
-            id: 'h-cx-courdemanges-1988-oct01-dex01',
-            titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
+            id: newEtapeId('h-cx-courdemanges-1988-oct01-dex01'),
             typeId: 'dex',
             statutId: 'acc',
             ordre: 1,
             date: toCaminoDate('1988-03-06'),
+            communes: [],
+            contenu: {},
+            heritageContenu: {},
+            surface: null,
           },
         ],
       },
     })
-    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate()
+    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate(undefined as unknown as Pool)
 
     expect(titresDemarchesStatutUpdated.length).toEqual(0)
   })
@@ -87,14 +100,14 @@ describe("statut des démarches d'un titre", () => {
     getDemarchesMock.mockResolvedValue({
       [newDemarcheId('')]: {
         id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-        titreId: 'h-cx-courdemanges-1988',
+        titreId: newTitreId('h-cx-courdemanges-1988'),
         titreTypeId: 'cxh',
         typeId: 'oct',
         statutId: 'ind',
         etapes: [],
       },
     })
-    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate()
+    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate(undefined as unknown as Pool)
     expect(titresDemarchesStatutUpdated.length).toEqual(0)
   })
 })
diff --git a/packages/api/src/business/processes/titres-demarches-statut-ids-update.ts b/packages/api/src/business/processes/titres-demarches-statut-ids-update.ts
index 6334abcb5..56b7879ee 100644
--- a/packages/api/src/business/processes/titres-demarches-statut-ids-update.ts
+++ b/packages/api/src/business/processes/titres-demarches-statut-ids-update.ts
@@ -1,14 +1,16 @@
+import { TitreId } from 'camino-common/src/titres.js'
 import { titreDemarcheUpdate } from '../../database/queries/titres-demarches.js'
 import { titreDemarcheStatutIdFind } from '../rules/titre-demarche-statut-id-find.js'
 import { titreEtapesSortAscByOrdre } from '../utils/titre-etapes-sort.js'
 import { getDemarches } from './titres-etapes-heritage-contenu-update.js'
+import { Pool } from 'pg'
 
 // met à jour le statut des démarches d'un titre
-export const titresDemarchesStatutIdUpdate = async (titresId?: string) => {
+export const titresDemarchesStatutIdUpdate = async (pool: Pool, titresId?: TitreId) => {
   console.info()
   console.info('statut des démarches…')
 
-  const titresDemarches = await getDemarches(undefined, titresId)
+  const titresDemarches = await getDemarches(pool, undefined, titresId)
 
   // TODO: forcer la présence des démarches sur le titre
   // https://stackoverflow.com/questions/40510611/typescript-interface-require-one-of-two-properties-to-exist/49725198#49725198
diff --git a/packages/api/src/business/processes/titres-etapes-administrations-locales-update.test.ts b/packages/api/src/business/processes/titres-etapes-administrations-locales-update.test.ts
index 94f2d4133..e42e7dfce 100644
--- a/packages/api/src/business/processes/titres-etapes-administrations-locales-update.test.ts
+++ b/packages/api/src/business/processes/titres-etapes-administrations-locales-update.test.ts
@@ -2,7 +2,7 @@ import { titresEtapesAdministrationsLocalesUpdate } from './titres-etapes-admini
 import { titresEtapesGet } from '../../database/queries/titres-etapes.js'
 
 import { ICommune, ITitreEtape } from '../../types.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId } from '../../database/models/_format/id-create.js'
 import { ADMINISTRATION_IDS } from 'camino-common/src/static/administrations.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { vi, describe, expect, test } from 'vitest'
@@ -30,7 +30,7 @@ describe("administrations d'une étape", () => {
   test('ajoute des administrations dans deux étapes', async () => {
     const titresEtapesCommunes: ITitreEtape[] = [
       {
-        id: 'h-cx-courdemanges-1988-oct01-dpu01',
+        id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
         titreDemarcheId: newDemarcheId(),
         statutId: 'fai',
         date: toCaminoDate('2022-01-01'),
@@ -43,7 +43,7 @@ describe("administrations d'une étape", () => {
         ],
       },
       {
-        id: 'h-cx-courdemanges-1988-oct01-dpu01',
+        id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
         titreDemarcheId: newDemarcheId(),
         statutId: 'fai',
         date: toCaminoDate('2022-01-01'),
@@ -66,7 +66,7 @@ describe("administrations d'une étape", () => {
   test("n'ajoute pas deux fois une administration en doublon ", async () => {
     const titresEtapesCommunesMemeCommune: ITitreEtape[] = [
       {
-        id: 'h-cx-courdemanges-1988-oct01-dpu01',
+        id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
         titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
         typeId: 'dpu',
         statutId: 'acc',
@@ -89,7 +89,7 @@ describe("administrations d'une étape", () => {
   test("ne met pas à jour les administrations d'une étape qui n'a pas de commune", async () => {
     const titresEtapesCommunesVides: ITitreEtape[] = [
       {
-        id: 'h-cx-courdemanges-1988-oct01-dpu01',
+        id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
         titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
         typeId: 'dpu',
         statutId: 'acc',
@@ -107,7 +107,7 @@ describe("administrations d'une étape", () => {
 
   test("n'ajoute pas d'administration si elle existe déjà dans l'étape", async () => {
     const titreEtape: ITitreEtape = {
-      id: 'h-cx-courdemanges-1988-oct01-dpu01',
+      id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
       titreDemarcheId: newDemarcheId(),
       statutId: 'fai',
       date: toCaminoDate('2022-01-01'),
@@ -127,7 +127,7 @@ describe("administrations d'une étape", () => {
     const titreEtape: ITitreEtape = {
       statutId: 'fai',
       date: toCaminoDate('2022-01-01'),
-      id: 'h-cx-courdemanges-1988-oct01-dpu01',
+      id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
       titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
       typeId: 'dpu',
       communes: [] as ICommune[],
diff --git a/packages/api/src/business/processes/titres-etapes-areas-update.test.integration.ts b/packages/api/src/business/processes/titres-etapes-areas-update.test.integration.ts
index 3fa244240..e3bb44f28 100644
--- a/packages/api/src/business/processes/titres-etapes-areas-update.test.integration.ts
+++ b/packages/api/src/business/processes/titres-etapes-areas-update.test.integration.ts
@@ -7,7 +7,7 @@ import TitresEtapes from '../../database/models/titres-etapes.js'
 import TitresPoints from '../../database/models/titres-points.js'
 import { titresEtapesAreasUpdate } from './titres-etapes-areas-update.js'
 import { BaisieuxPerimetre, foret2BranchesPerimetre, foretReginaPerimetre, SaintEliePerimetre, SinnamaryPerimetre } from './__mocks__/titres-etapes-areas-update.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create.js'
 import { SDOMZoneIds } from 'camino-common/src/static/sdom.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { vi, beforeAll, afterAll, describe, test, expect } from 'vitest'
@@ -52,7 +52,7 @@ describe('titresEtapesAreasUpdate', () => {
     // Pour simplifier le test, on utilise des forêts en tant que zone de sdom
     await knex!.raw(`insert into sdom_zones_postgis (id, geometry) values ('${SDOMZoneIds.Zone1}','${foret2BranchesPerimetre}')`)
     await knex!.raw(`insert into sdom_zones_postgis (id, geometry) values ('${SDOMZoneIds.Zone2}','${foretReginaPerimetre}')`)
-    const titreId = 'titreIdUniquePourMiseAJourAreas'
+    const titreId = newTitreId('titreIdUniquePourMiseAJourAreas')
     await Titres.query().insert({
       id: titreId,
       slug: `slug-${titreId}`,
@@ -72,7 +72,7 @@ describe('titresEtapesAreasUpdate', () => {
       },
     ])
 
-    const titreEtapeId = 'titreEtapeIdUniquePourMiseAJourAreas'
+    const titreEtapeId = newEtapeId('titreEtapeIdUniquePourMiseAJourAreas')
     await TitresEtapes.query().insert([
       {
         id: titreEtapeId,
diff --git a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.ts b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.ts
new file mode 100644
index 000000000..870551e3c
--- /dev/null
+++ b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.ts
@@ -0,0 +1,64 @@
+import { sql } from '@pgtyped/runtime'
+import { IGetEtapesByDemarcheQuery } from './titres-etapes-heritage-contenu-update.queries.types'
+import { Redefine } from '../../pg-database'
+import { caminoDateValidator } from 'camino-common/src/date.js'
+import { DemarcheId, demarcheIdValidator } from 'camino-common/src/demarche.js'
+import { demarcheStatutIdValidator } from 'camino-common/src/static/demarchesStatuts.js'
+import { demarcheTypeIdValidator } from 'camino-common/src/static/demarchesTypes.js'
+import { etapeStatutIdValidator } from 'camino-common/src/static/etapesStatuts.js'
+import { titreTypeIdValidator } from 'camino-common/src/static/titresTypes.js'
+import { etapeTypeIdValidator } from 'camino-common/src/static/etapesTypes.js'
+import { TitreId, titreIdValidator } from 'camino-common/src/titres.js'
+import { etapeIdValidator } from 'camino-common/src/etape.js'
+import { z } from 'zod'
+import { communeIdValidator } from 'camino-common/src/static/communes.js'
+
+export const getEtapesByDemarcheValidator = z.object({
+  contenu: z.any(),
+  date: caminoDateValidator,
+  demarche_id: demarcheIdValidator,
+  demarche_statut_id: demarcheStatutIdValidator,
+  demarche_type_id: demarcheTypeIdValidator,
+  heritage_contenu: z.any(),
+  id: etapeIdValidator,
+  ordre: z.number(),
+  statut_id: etapeStatutIdValidator,
+  titre_id: titreIdValidator,
+  titre_type_id: titreTypeIdValidator,
+  communes: z.array(z.object({ id: communeIdValidator })),
+  surface: z.number().nullable(),
+  type_id: etapeTypeIdValidator,
+})
+
+export const getEtapesByDemarche = sql<Redefine<IGetEtapesByDemarcheQuery, { demarcheId?: DemarcheId; titreId?: TitreId }, z.infer<typeof getEtapesByDemarcheValidator>>>`
+SELECT
+    titre.id as titre_id,
+    titre.type_id as titre_type_id,
+    etape.id,
+    etape.ordre,
+    etape.type_id,
+    etape.statut_id,
+    etape.date,
+    etape.contenu,
+    etape.surface,
+    etape.heritage_contenu,
+    demarche.id as demarche_id,
+    demarche.type_id as demarche_type_id,
+    demarche.statut_id as demarche_statut_id,
+    etape.communes as communes
+from
+    titres_etapes etape
+    join titres_demarches demarche on etape.titre_demarche_id = demarche.id
+    join titres titre on demarche.titre_id = titre.id
+where
+    etape.archive = false
+    and demarche.archive = false
+    and titre.archive = false
+    and ($ demarcheId::text IS NULL
+        or demarche.id = $ demarcheId)
+    and ($ titreId::text IS NULL
+        or titre.id = $ titreId)
+order by
+    demarche.id,
+    etape.ordre
+`
diff --git a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.types.ts b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.types.ts
new file mode 100644
index 000000000..919cedc7b
--- /dev/null
+++ b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.types.ts
@@ -0,0 +1,33 @@
+/** Types generated for queries found in "src/business/processes/titres-etapes-heritage-contenu-update.queries.ts" */
+export type Json = null | boolean | number | string | Json[] | { [key: string]: Json };
+
+/** 'GetEtapesByDemarche' parameters type */
+export interface IGetEtapesByDemarcheParams {
+  demarcheId?: string | null | void;
+  titreId?: string | null | void;
+}
+
+/** 'GetEtapesByDemarche' return type */
+export interface IGetEtapesByDemarcheResult {
+  communes: Json;
+  contenu: Json | null;
+  date: string;
+  demarche_id: string;
+  demarche_statut_id: string;
+  demarche_type_id: string;
+  heritage_contenu: Json | null;
+  id: string;
+  ordre: number;
+  statut_id: string;
+  surface: number | null;
+  titre_id: string;
+  titre_type_id: string;
+  type_id: string;
+}
+
+/** 'GetEtapesByDemarche' query type */
+export interface IGetEtapesByDemarcheQuery {
+  params: IGetEtapesByDemarcheParams;
+  result: IGetEtapesByDemarcheResult;
+}
+
diff --git a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts
index 7a460cd15..05b27ddd7 100644
--- a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts
+++ b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts
@@ -1,57 +1,43 @@
 /* eslint-disable sql/no-unsafe-query */
-import { IContenu, IHeritageContenu, ITitreEtape } from '../../types.js'
-
 import { titreEtapeUpdate } from '../../database/queries/titres-etapes.js'
 import { titreEtapeHeritageContenuFind } from '../utils/titre-etape-heritage-contenu-find.js'
 import { titreEtapesSortAscByOrdre, titreEtapesSortDescByOrdre } from '../utils/titre-etapes-sort.js'
-import { UserNotNull } from 'camino-common/src/roles'
+import { UserNotNull } from 'camino-common/src/roles.js'
 import { getSections, Section } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.js'
 import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
-import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
-import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts.js'
-import { CaminoDate } from 'camino-common/src/date.js'
 import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js'
-import { knex } from '../../knex.js'
 import { DeepReadonly } from 'camino-common/src/typescript-tools.js'
 import { DemarcheStatutId } from 'camino-common/src/static/demarchesStatuts.js'
 import { DemarcheId } from 'camino-common/src/demarche.js'
+import { Pool } from 'pg'
+import { dbQueryAndValidate } from '../../pg-database.js'
+import { getEtapesByDemarche, getEtapesByDemarcheValidator } from './titres-etapes-heritage-contenu-update.queries.js'
+import { TitreId } from 'camino-common/src/titres.js'
+import { TitreEtapeForMachine } from '../rules-demarches/machine-common.js'
+
+export const getDemarches = async (
+  pool: Pool,
+  demarcheId?: DemarcheId,
+  titreId?: TitreId
+): Promise<{
+  [key: DemarcheId]: {
+    etapes: TitreEtapeForMachine[]
+    id: DemarcheId
+    typeId: DemarcheTypeId
+    titreTypeId: TitreTypeId
+    titreId: TitreId
+    statutId: DemarcheStatutId
+  }
+}> => {
+  const etapes = await dbQueryAndValidate(getEtapesByDemarche, { demarcheId, titreId }, pool, getEtapesByDemarcheValidator)
 
-export const getDemarches = async (demarcheId?: DemarcheId, titreId?: string) => {
-  const etapes: {
-    rows: {
-      titre_id: string
-      titre_type_id: TitreTypeId
-      id: string
-      ordre: number
-      type_id: EtapeTypeId
-      statut_id: EtapeStatutId
-      date: CaminoDate
-      contenu: IContenu
-      heritage_contenu: IHeritageContenu
-      demarche_id: DemarcheId
-      demarche_type_id: DemarcheTypeId
-      demarche_statut_id: DemarcheStatutId
-    }[]
-  } =
-    await knex.raw(`SELECT titre.id as titre_id, titre.type_id as titre_type_id, etape.id, etape.ordre, etape.type_id, etape.statut_id, etape.date, etape.contenu, etape.heritage_contenu, demarche.id as demarche_id, demarche.type_id as demarche_type_id, demarche.statut_id as demarche_statut_id
-  from titres_etapes etape
-      join titres_demarches demarche on etape.titre_demarche_id = demarche.id
-      join titres titre on demarche.titre_id = titre.id
-      where etape.archive = false
-      and demarche.archive = false
-      and titre.archive = false
-      ${demarcheId ? `and demarche.id = '${demarcheId}'` : ''}
-      ${titreId ? `and titre.id = '${titreId}'` : ''}
-
-  order by demarche.id, etape.ordre`)
-
-  return etapes.rows.reduce<{
+  return etapes.reduce<{
     [key: DemarcheId]: {
-      etapes: Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'heritageContenu' | 'titreDemarcheId'>[]
+      etapes: TitreEtapeForMachine[]
       id: DemarcheId
       typeId: DemarcheTypeId
       titreTypeId: TitreTypeId
-      titreId: string
+      titreId: TitreId
       statutId: DemarcheStatutId
     }
   }>((acc, row) => {
@@ -74,17 +60,18 @@ export const getDemarches = async (demarcheId?: DemarcheId, titreId?: string) =>
       date: row.date,
       contenu: row.contenu,
       heritageContenu: row.heritage_contenu,
-      titreDemarcheId: row.demarche_id,
+      communes: row.communes,
+      surface: row.surface,
     })
 
     return acc
   }, {})
 }
-export const titresEtapesHeritageContenuUpdate = async (user: UserNotNull, demarcheId?: DemarcheId) => {
+export const titresEtapesHeritageContenuUpdate = async (pool: Pool, user: UserNotNull, demarcheId?: DemarcheId) => {
   console.info()
   console.info('héritage des contenus des étapes…')
 
-  const titresDemarches = await getDemarches(demarcheId)
+  const titresDemarches = await getDemarches(pool, demarcheId)
 
   // lorsqu'une étape est mise à jour par un utilisateur,
   // l'objet heritageContenu reçu ne contient pas d'id d'étape
@@ -125,8 +112,8 @@ export const titresEtapesHeritageContenuUpdate = async (user: UserNotNull, demar
 
             titresEtapesIdsUpdated.push(titreEtape.id)
 
-            titreEtape.contenu = contenu
-            titreEtape.heritageContenu = heritageContenu
+            titreEtape.contenu = contenu ?? null
+            titreEtape.heritageContenu = heritageContenu ?? null
           }
         }
       }
diff --git a/packages/api/src/business/processes/titres-etapes-ordre-update.test.ts b/packages/api/src/business/processes/titres-etapes-ordre-update.test.ts
index b8eaffc56..fe23143b0 100644
--- a/packages/api/src/business/processes/titres-etapes-ordre-update.test.ts
+++ b/packages/api/src/business/processes/titres-etapes-ordre-update.test.ts
@@ -4,6 +4,7 @@ import { titreEtapeUpdate } from '../../database/queries/titres-etapes.js'
 import TitresDemarches from '../../database/models/titres-demarches.js'
 import { userSuper } from '../../database/user-super.js'
 import { vi, afterEach, describe, expect, test } from 'vitest'
+import { newEtapeId } from '../../database/models/_format/id-create.js'
 vi.mock('../../database/queries/titres-etapes', () => ({
   titreEtapeUpdate: vi.fn().mockResolvedValue(true),
 }))
@@ -11,8 +12,8 @@ vi.mock('../../database/queries/titres-etapes', () => ({
 const titresDemarchesEtapes = {
   '': {
     etapes: [
-      { ordre: 1, date: '1988-03-06' },
-      { ordre: 1, date: '1988-03-08' },
+      { id: newEtapeId(), ordre: 1, date: '1988-03-06', typeId: 'aac', statutId: 'acc', surface: 0, communes: null },
+      { id: newEtapeId(), ordre: 1, date: '1988-03-08', typeId: 'aac', statutId: 'acc', surface: 0, communes: null },
     ],
     titre: null,
   } as TitresDemarches,
diff --git a/packages/api/src/business/processes/titres-etapes-ordre-update.ts b/packages/api/src/business/processes/titres-etapes-ordre-update.ts
index 5e5c7a660..be941df3d 100644
--- a/packages/api/src/business/processes/titres-etapes-ordre-update.ts
+++ b/packages/api/src/business/processes/titres-etapes-ordre-update.ts
@@ -1,5 +1,3 @@
-import { ITitreEtape } from '../../types.js'
-
 import { titreEtapeUpdate } from '../../database/queries/titres-etapes.js'
 import { titreEtapesSortAscByDate } from '../utils/titre-etapes-sort.js'
 import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js'
@@ -7,12 +5,15 @@ import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { getDemarches } from './titres-etapes-heritage-contenu-update.js'
 import { UserNotNull } from 'camino-common/src/roles.js'
 import { DemarcheId } from 'camino-common/src/demarche.js'
+import { Pool } from 'pg'
+import { TitreId } from 'camino-common/src/titres.js'
+import { TitreEtapeForMachine, titreEtapeForMachineValidator } from '../rules-demarches/machine-common.js'
 
-export const titresEtapesOrdreUpdate = async (user: UserNotNull, demarcheId?: DemarcheId) => {
+export const titresEtapesOrdreUpdate = async (pool: Pool, user: UserNotNull, demarcheId?: DemarcheId) => {
   console.info()
   console.info('ordre des étapes…')
 
-  const titresDemarches = await getDemarches(demarcheId)
+  const titresDemarches = await getDemarches(pool, demarcheId)
 
   return titresEtapesOrdreUpdateVisibleForTesting(user, titresDemarches)
 }
@@ -21,11 +22,11 @@ export const titresEtapesOrdreUpdateVisibleForTesting = async (
   user: UserNotNull,
   titresDemarches: {
     [key: DemarcheId]: {
-      etapes: Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'titreDemarcheId'>[]
+      etapes: TitreEtapeForMachine[]
       id: DemarcheId
       typeId: DemarcheTypeId
       titreTypeId: TitreTypeId
-      titreId: string
+      titreId: TitreId
     }
   }
 ): Promise<string[]> => {
@@ -33,7 +34,9 @@ export const titresEtapesOrdreUpdateVisibleForTesting = async (
 
   for (const titreDemarche of Object.values(titresDemarches)) {
     if (titreDemarche.etapes) {
-      const etapes = titreEtapesSortAscByDate(titreDemarche.etapes, titreDemarche.id, titreDemarche.typeId, titreDemarche.titreTypeId)
+      const etapesMachine = titreDemarche.etapes.map(etape => titreEtapeForMachineValidator.parse(etape))
+
+      const etapes = titreEtapesSortAscByDate(etapesMachine, titreDemarche.id, titreDemarche.typeId, titreDemarche.titreTypeId)
       for (let index = 0; index < etapes.length; index++) {
         const titreEtape = etapes[index]
         if (titreEtape.ordre !== index + 1) {
diff --git a/packages/api/src/business/processes/titres-phases-update.test.ts b/packages/api/src/business/processes/titres-phases-update.test.ts
index b68316b04..1b1763a6a 100644
--- a/packages/api/src/business/processes/titres-phases-update.test.ts
+++ b/packages/api/src/business/processes/titres-phases-update.test.ts
@@ -3,7 +3,7 @@ import { titresGet } from '../../database/queries/titres.js'
 import { vi, afterEach, describe, expect, test } from 'vitest'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { ITitre } from '../../types.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create.js'
 import { dbQueryAndValidate } from '../../pg-database.js'
 import { Pool } from 'pg'
 import { updateDatesDemarcheDb } from './titres-phases-update.queries.js'
@@ -34,20 +34,20 @@ describe("phases d'un titre", () => {
   test('met à jour un titre dont une phase est créée', async () => {
     titresGetMock.mockResolvedValue([
       {
-        id: 'h-cx-courdemanges-1988',
+        id: newTitreId('h-cx-courdemanges-1988'),
         nom: 'nom',
         typeId: 'cxh',
         propsTitreEtapesIds: {},
         demarches: [
           {
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-            titreId: 'h-cx-courdemanges-1988',
+            titreId: newTitreId('h-cx-courdemanges-1988'),
             typeId: 'oct',
             statutId: 'acc',
             ordre: 1,
             etapes: [
               {
-                id: 'h-cx-courdemanges-1988-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -56,7 +56,7 @@ describe("phases d'un titre", () => {
                 dateFin: toCaminoDate('2500-01-01'),
               },
               {
-                id: 'h-cx-courdemanges-1988-oct01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1988-oct01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
                 typeId: 'dex',
                 statutId: 'acc',
@@ -84,14 +84,14 @@ describe("phases d'un titre", () => {
   test('met à jour un titre dont une phase est modifiée', async () => {
     titresGetMock.mockResolvedValue([
       {
-        id: 'h-cx-courdemanges-1988',
+        id: newTitreId('h-cx-courdemanges-1988'),
         nom: 'nom',
         typeId: 'cxh',
         propsTitreEtapesIds: {},
         demarches: [
           {
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-            titreId: 'h-cx-courdemanges-1988',
+            titreId: newTitreId('h-cx-courdemanges-1988'),
             typeId: 'oct',
             statutId: 'acc',
             ordre: 1,
@@ -99,7 +99,7 @@ describe("phases d'un titre", () => {
             demarcheDateDebut: toCaminoDate('2300-01-01'),
             etapes: [
               {
-                id: 'h-cx-courdemanges-1988-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -108,7 +108,7 @@ describe("phases d'un titre", () => {
                 dateFin: toCaminoDate('2500-01-01'),
               },
               {
-                id: 'h-cx-courdemanges-1988-oct01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1988-oct01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
                 typeId: 'dex',
                 statutId: 'acc',
@@ -135,14 +135,14 @@ describe("phases d'un titre", () => {
   test('met à jour un titre dont une phase est supprimée', async () => {
     titresGetMock.mockResolvedValue([
       {
-        id: 'h-cx-courdemanges-1988',
+        id: newTitreId('h-cx-courdemanges-1988'),
         nom: 'test',
         typeId: 'cxh',
         propsTitreEtapesIds: {},
         demarches: [
           {
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-            titreId: 'h-cx-courdemanges-1988',
+            titreId: newTitreId('h-cx-courdemanges-1988'),
             typeId: 'oct',
             statutId: 'acc',
             demarcheDateDebut: toCaminoDate('2200-01-01'),
@@ -163,14 +163,14 @@ describe("phases d'un titre", () => {
   test("ne met pas à jour un titre si aucune phase n'est modifiée", async () => {
     titresGetMock.mockResolvedValue([
       {
-        id: 'h-cx-courdemanges-1988',
+        id: newTitreId('h-cx-courdemanges-1988'),
         nom: 'nom',
         propsTitreEtapesIds: {},
         typeId: 'cxh',
         demarches: [
           {
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-            titreId: 'h-cx-courdemanges-1988',
+            titreId: newTitreId('h-cx-courdemanges-1988'),
             typeId: 'oct',
             statutId: 'acc',
             ordre: 1,
@@ -178,7 +178,7 @@ describe("phases d'un titre", () => {
             demarcheDateDebut: toCaminoDate('2200-01-01'),
             etapes: [
               {
-                id: 'h-cx-courdemanges-1988-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -187,7 +187,7 @@ describe("phases d'un titre", () => {
                 dateFin: toCaminoDate('2500-01-01'),
               },
               {
-                id: 'h-cx-courdemanges-1988-oct01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1988-oct01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
                 typeId: 'dex',
                 statutId: 'acc',
@@ -209,14 +209,14 @@ describe("phases d'un titre", () => {
   test("ne met pas à jour un titre si aucune phase n'existe", async () => {
     titresGetMock.mockResolvedValue([
       {
-        id: 'h-cx-courdemanges-1988',
+        id: newTitreId('h-cx-courdemanges-1988'),
         nom: 'nom',
         typeId: 'cxh',
         propsTitreEtapesIds: {},
         demarches: [
           {
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-            titreId: 'h-cx-courdemanges-1988',
+            titreId: newTitreId('h-cx-courdemanges-1988'),
             typeId: 'oct',
             statutId: 'acc',
             ordre: 1,
diff --git a/packages/api/src/business/processes/titres-statut-ids-update.test.ts b/packages/api/src/business/processes/titres-statut-ids-update.test.ts
index 2a2f0158f..2d193b856 100644
--- a/packages/api/src/business/processes/titres-statut-ids-update.test.ts
+++ b/packages/api/src/business/processes/titres-statut-ids-update.test.ts
@@ -2,7 +2,7 @@ import { titresStatutIdsUpdate } from './titres-statut-ids-update.js'
 import { titresGet } from '../../database/queries/titres.js'
 
 import { vi, describe, expect, test, beforeEach } from 'vitest'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newTitreId } from '../../database/models/_format/id-create.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 vi.mock('../../database/queries/titres', () => ({
   __esModule: true,
@@ -22,7 +22,7 @@ describe("statut d'un titre", () => {
   test('met à jour un titre si son statut est obsolète', async () => {
     titresGetMock.mockResolvedValue([
       {
-        id: 'm-pr-saint-pierre-1914',
+        id: newTitreId('m-pr-saint-pierre-1914'),
         nom: 'unused',
         typeId: 'prm',
         propsTitreEtapesIds: {},
@@ -30,7 +30,7 @@ describe("statut d'un titre", () => {
         demarches: [
           {
             id: newDemarcheId('m-pr-saint-pierre-1914-oct01'),
-            titreId: 'm-pr-saint-pierre-1914',
+            titreId: newTitreId('m-pr-saint-pierre-1914'),
             typeId: 'oct',
             statutId: 'acc',
             ordre: 1,
@@ -49,7 +49,7 @@ describe("statut d'un titre", () => {
   test("ne met pas à jour le statut d'un titre", async () => {
     titresGetMock.mockResolvedValue([
       {
-        id: 'm-pr-saint-pierre-2014',
+        id: newTitreId('m-pr-saint-pierre-2014'),
         nom: 'nom',
         typeId: 'prm',
         titreStatutId: 'val',
@@ -57,7 +57,7 @@ describe("statut d'un titre", () => {
         demarches: [
           {
             id: newDemarcheId('m-pr-saint-pierre-2014-oct01'),
-            titreId: 'm-pr-saint-pierre-2014',
+            titreId: newTitreId('m-pr-saint-pierre-2014'),
             typeId: 'oct',
             statutId: 'acc',
             ordre: 1,
diff --git a/packages/api/src/business/rules-demarches/_utils.test.ts b/packages/api/src/business/rules-demarches/_utils.test.ts
deleted file mode 100644
index 43d0b2de8..000000000
--- a/packages/api/src/business/rules-demarches/_utils.test.ts
+++ /dev/null
@@ -1,89 +0,0 @@
-import fs from 'fs'
-import decamelize from 'decamelize'
-import camelcase from 'camelcase'
-
-import { IEtapeType, ITitre, ITitreDemarche, ITitreEtape, ITitreType, ITitreTypeDemarcheTypeEtapeType } from '../../types.js'
-
-import { titreDemarcheEtatValidate } from '../validations/titre-demarche-etat-validate.js'
-import { demarcheDefinitionFind, isDemarcheDefinitionRestriction } from './definitions.js'
-import { contenusTitreEtapesIdsFind } from '../utils/props-titre-etapes-ids-find.js'
-import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
-import { CaminoDate, toCaminoDate } from 'camino-common/src/date.js'
-import { vi, expect, test } from 'vitest'
-import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js'
-test('teste EtatsValidate', () => {
-  const octEtatsValidate = demarcheEtatsValidate('oct', 'prm', toCaminoDate('2021-01-01'))
-
-  expect(octEtatsValidate).toBeTruthy()
-  expect(octEtatsValidate([], {})).toHaveLength(0)
-})
-
-vi.mock('../../database/models/_format/titre-contenu', () => ({
-  __esModule: true,
-  titreContenuFormat: vi.fn(),
-}))
-
-vi.mock('../utils/props-titre-etapes-ids-find', () => ({
-  __esModule: true,
-  contenusTitreEtapesIdsFind: vi.fn(),
-}))
-
-const contenusTitreEtapesIdsFindMock = vi.mocked(contenusTitreEtapesIdsFind, true)
-
-const elementsGet = <T>(fileName: string): T[] => {
-  fileName = decamelize(fileName, { separator: '-' })
-  const filePath = `./sources/${fileName}`
-  const results = JSON.parse(fs.readFileSync(filePath).toString())
-
-  return results.map((result: any) =>
-    Object.keys(result).reduce((acc: { [key: string]: any }, key) => {
-      acc[camelcase(key)] = result[key]
-
-      return acc
-    }, {})
-  )
-}
-
-export const etapesTypesGet = (demarcheTypeId: string, titreTypeId: string) => {
-  const titresTypesDemarchesTypesEtapesTypes = elementsGet<ITitreTypeDemarcheTypeEtapeType>('titres-types--demarches-types--etapes-types.json').filter(
-    tde => tde.titreTypeId === titreTypeId && tde.demarcheTypeId === demarcheTypeId
-  )
-
-  return elementsGet<IEtapeType>('etapes-types.json').reduce((acc, etapeType) => {
-    const tde = titresTypesDemarchesTypesEtapesTypes.find(tde => tde.etapeTypeId === etapeType.id)
-
-    if (tde) {
-      etapeType.titreTypeId = tde.titreTypeId
-      etapeType.ordre = tde.ordre
-      acc.push(etapeType)
-    }
-
-    return acc
-  }, [] as IEtapeType[])
-}
-
-export const demarcheEtatsValidate = (demarcheTypeId: DemarcheTypeId, titreTypeId: TitreTypeId, date: CaminoDate) => {
-  return (titreDemarcheEtapes: Partial<ITitreEtape>[], titre: Partial<ITitre> = {}) => {
-    contenusTitreEtapesIdsFindMock.mockReturnValue({})
-
-    const demarcheDefinitions = demarcheDefinitionFind(titreTypeId, demarcheTypeId, [{ typeId: 'mfr', date }], newDemarcheId())
-    if (!isDemarcheDefinitionRestriction(demarcheDefinitions)) {
-      throw new Error('cette démarche n’a pas de restrictions')
-    }
-    const demarcheDefinitionRestrictions = demarcheDefinitions!.restrictions
-
-    const titreDemarche = { typeId: demarcheTypeId } as ITitreDemarche
-    titre = {
-      ...titre,
-      typeId: titreTypeId,
-      type: {
-        id: titreTypeId,
-        contenuIds: [],
-      } as unknown as ITitreType,
-      demarches: [titreDemarche] as ITitreDemarche[],
-    }
-
-    return titreDemarcheEtatValidate(date, demarcheDefinitionRestrictions!, demarcheTypeId, titreDemarche, titreDemarcheEtapes as ITitreEtape[], titre as ITitre)
-  }
-}
diff --git a/packages/api/src/business/rules-demarches/axm/oct.machine.ts b/packages/api/src/business/rules-demarches/axm/oct.machine.ts
index 6839a08fa..13e9dff56 100644
--- a/packages/api/src/business/rules-demarches/axm/oct.machine.ts
+++ b/packages/api/src/business/rules-demarches/axm/oct.machine.ts
@@ -683,7 +683,7 @@ const axmOctMachine = createMachine<AxmContext, AXMOctXStateEvent>({
     publicationsEtNotificationsMachine: {
       type: 'parallel',
       states: {
-        notificationDuDemadeurMachine: {
+        notificationDuDemandeurMachine: {
           initial: 'notificationDuDemandeurAFaire',
           states: {
             notificationDuDemandeurAFaire: {
diff --git a/packages/api/src/business/rules-demarches/definitions.test.ts b/packages/api/src/business/rules-demarches/definitions.test.ts
index ffcd1363c..c4274bab3 100644
--- a/packages/api/src/business/rules-demarches/definitions.test.ts
+++ b/packages/api/src/business/rules-demarches/definitions.test.ts
@@ -1,123 +1,20 @@
-import { demarchesDefinitions, IEtapeTypeIdCondition, isDemarcheDefinitionMachine, isDemarcheDefinitionRestriction } from './definitions.js'
-import { ArmOctMachine } from './arm/oct.machine.js'
-import { expect, test } from 'vitest'
-import { toCaminoDate } from 'camino-common/src/date.js'
-import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
-import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js'
-import { getEtapesTDE } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index.js'
-import { EtapesTypes, isEtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
-import { etatsDefinitionPrmOct } from './prm/oct.js'
+import { test, expect } from 'vitest'
+import { demarcheDefinitionFind } from './definitions'
+import { toCaminoDate } from 'camino-common/src/date'
+import { newDemarcheId } from '../../database/models/_format/id-create'
 
-test('isDemarcheDefinitionMachine', () => {
-  expect(
-    isDemarcheDefinitionMachine({
-      titreTypeId: 'pxm',
-      demarcheTypeIds: [],
-      dateDebut: toCaminoDate('2022-01-01'),
-      machine: new ArmOctMachine(),
-    })
-  ).toBe(true)
-  expect(
-    isDemarcheDefinitionMachine({
-      titreTypeId: 'pxm',
-      demarcheTypeIds: [],
-      dateDebut: toCaminoDate('2022-01-01'),
-      restrictions: etatsDefinitionPrmOct,
-    })
-  ).toBe(false)
-  expect(isDemarcheDefinitionMachine(undefined)).toBe(false)
+test('demarcheDefinitionFind retourne une machine', () => {
+  expect(demarcheDefinitionFind('prm', 'oct', [{ date: toCaminoDate('2023-06-07'), typeId: 'mdp' }], newDemarcheId('demarcheId'))).not.toBeUndefined()
 })
-test('isDemarcheDefinitionRestriction', () => {
-  expect(
-    isDemarcheDefinitionRestriction({
-      titreTypeId: 'pxm',
-      demarcheTypeIds: [],
-      dateDebut: toCaminoDate('2022-01-01'),
-      machine: new ArmOctMachine(),
-    })
-  ).toBe(false)
-  expect(
-    isDemarcheDefinitionRestriction({
-      titreTypeId: 'pxm',
-      demarcheTypeIds: [],
-      dateDebut: toCaminoDate('2022-01-01'),
-      restrictions: etatsDefinitionPrmOct,
-    })
-  ).toBe(true)
-})
-
-test('tdeValidate', () => {
-  const etapeTypeIdsGet = (contraintes?: IEtapeTypeIdCondition[][]) => {
-    const etapeTypeIds = [] as string[]
-    if (contraintes?.length) {
-      contraintes.forEach(contrainte => {
-        contrainte.forEach(c => {
-          if (c.etapeTypeId) {
-            etapeTypeIds.push(c.etapeTypeId)
-          }
-        })
-      })
-    }
-
-    return etapeTypeIds
-  }
-
-  const etapesTypesIdsGet = (titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId) => getEtapesTDE(titreTypeId, demarcheTypeId).filter(etapeTypeId => !EtapesTypes[etapeTypeId].dateFin)
-
-  const errors: string[] = []
-
-  const definitionsWithRestrictions = demarchesDefinitions.filter(isDemarcheDefinitionRestriction)
-
-  for (const demarcheDefinition of definitionsWithRestrictions) {
-    for (const demarcheTypeId of demarcheDefinition.demarcheTypeIds) {
-      const demarcheEtatsEtapeTypeIds = Object.keys(demarcheDefinition.restrictions)
-        .filter(isEtapeTypeId)
-        .reduce((acc, etapeTypeId) => {
-          acc.push(etapeTypeId)
-          const restriction = demarcheDefinition.restrictions[etapeTypeId]
-          if (restriction?.separation) {
-            acc.push(...restriction.separation)
-          }
-          acc.push(...etapeTypeIdsGet(restriction?.avant ?? []))
-          acc.push(...etapeTypeIdsGet(restriction?.apres ?? []))
-          acc.push(...etapeTypeIdsGet(restriction?.justeApres ?? []))
 
-          return acc
-        }, [] as string[])
-        .map(type => type.split('-')[0])
-
-      const tdeEtapeTypeIds = etapesTypesIdsGet(demarcheDefinition.titreTypeId, demarcheTypeId)
-
-      // on vérifie que toutes les étapes définies dans l’arbre existent dans TDE
-      demarcheEtatsEtapeTypeIds.forEach(demarcheEtatsEtapeTypeId => {
-        if (!tdeEtapeTypeIds.includes(demarcheEtatsEtapeTypeId)) {
-          errors.push(`titre "${demarcheDefinition.titreTypeId}" démarche "${demarcheTypeId}" étape "${demarcheEtatsEtapeTypeId}" présent dans l’arbre d’instructions mais pas dans TDE`)
-        }
-      })
-
-      // on vérifie que toutes les étapes définies dans TDE existent dans l’arbre
-      tdeEtapeTypeIds.forEach(tdeEtapeTypeId => {
-        if (!demarcheEtatsEtapeTypeIds.includes(tdeEtapeTypeId)) {
-          errors.push(`titre "${demarcheDefinition.titreTypeId}" démarche "${demarcheTypeId}" étape "${tdeEtapeTypeId}" présent dans TDE mais pas dans l’arbre d’instructions`)
-        }
-      })
-    }
-  }
-
-  // on vérifie qu’il existe un bloc dans l’arbre par étapes définies dans TDE
-  for (const demarcheDefinition of definitionsWithRestrictions) {
-    for (const demarcheTypeId of demarcheDefinition.demarcheTypeIds) {
-      const demarcheEtatsEtapeTypeIds = Object.keys(demarcheDefinition.restrictions)
-
-      const tdeEtapeTypeIds = etapesTypesIdsGet(demarcheDefinition.titreTypeId, demarcheTypeId)
+test("demarcheDefinitionFind retourne une machine quand il n'y a pas d'étape", () => {
+  expect(demarcheDefinitionFind('prm', 'oct', [], newDemarcheId('demarcheId'))).not.toBeUndefined()
+})
 
-      tdeEtapeTypeIds.forEach(tdeEtapeTypeId => {
-        if (!demarcheEtatsEtapeTypeIds.includes(tdeEtapeTypeId)) {
-          errors.push(`bloc manquant "${tdeEtapeTypeId}" dans l’arbre des démarches "${demarcheTypeId}" des titres "${demarcheDefinition.titreTypeId}"`)
-        }
-      })
-    }
-  }
+test('demarcheDefinitionFind ne retourne pas une machine quand la démarche fait partie des exceptions', () => {
+  expect(demarcheDefinitionFind('prm', 'oct', [{ date: toCaminoDate('2023-06-07'), typeId: 'mdp' }], newDemarcheId('FfJTtP9EEfvf3VZy81hpF7ms'))).toBeUndefined()
+})
 
-  expect(errors).toStrictEqual([])
+test('demarcheDefinitionFind ne retourne pas une machine quand les étapes sont trop anciennes', () => {
+  expect(demarcheDefinitionFind('prm', 'oct', [{ date: toCaminoDate('2010-06-07'), typeId: 'mdp' }], newDemarcheId('FfJTtP9EEfvf3VZy81hpF7ms'))).toBeUndefined()
 })
diff --git a/packages/api/src/business/rules-demarches/definitions.ts b/packages/api/src/business/rules-demarches/definitions.ts
index 2b1a0c853..54379d68b 100644
--- a/packages/api/src/business/rules-demarches/definitions.ts
+++ b/packages/api/src/business/rules-demarches/definitions.ts
@@ -1,6 +1,5 @@
-import { IContenuValeur, ITitreEtape } from '../../types.js'
+import { ITitreEtape } from '../../types.js'
 import { DemarcheId } from 'camino-common/src/demarche.js'
-import { etatsDefinitionPrmOct } from './prm/oct.js'
 import { titreDemarcheDepotDemandeDateFind } from '../rules/titre-demarche-depot-demande-date-find.js'
 import { CaminoMachines } from './machines.js'
 import { ArmOctMachine } from './arm/oct.machine.js'
@@ -11,37 +10,8 @@ import { newDemarcheId } from '../../database/models/_format/id-create.js'
 import { CaminoDate, toCaminoDate } from 'camino-common/src/date.js'
 import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js'
 import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
-import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
 import { ArmRenProMachine } from './arm/ren-pro.machine.js'
-
-export interface IEtapeTypeIdCondition {
-  etapeTypeId?: string
-  statutId?: string
-  titre?: ITitreCondition
-  contextCheck?: (_etapes: ITitreEtape[]) => boolean
-}
-
-export type IDemarcheDefinitionRestrictions = { [key in EtapeTypeId]?: IDemarcheDefinitionRestrictionsProps }
-
-export interface IDemarcheDefinitionRestrictionsProps {
-  separation?: string[]
-  final?: boolean
-  avant?: IEtapeTypeIdCondition[][]
-  apres?: IEtapeTypeIdCondition[][]
-  justeApres: IEtapeTypeIdCondition[][]
-}
-
-export interface IDemarcheDefinitionRestrictionsElements extends IDemarcheDefinitionRestrictionsProps {
-  etapeTypeId?: string
-}
-export type IDemarcheDefinition = DemarcheDefinitionRestriction | DemarcheDefinitionMachine
-
-export const isDemarcheDefinitionRestriction = (dd: IDemarcheDefinition | undefined): dd is DemarcheDefinitionRestriction => {
-  return dd !== undefined && 'restrictions' in dd
-}
-export const isDemarcheDefinitionMachine = (dd: IDemarcheDefinition | undefined): dd is DemarcheDefinitionMachine => {
-  return dd !== undefined && 'machine' in dd
-}
+import { PrmOctMachine } from './prm/oct.machine.js'
 
 interface DemarcheDefinitionCommon {
   titreTypeId: TitreTypeId
@@ -49,33 +19,12 @@ interface DemarcheDefinitionCommon {
   dateDebut: CaminoDate
   demarcheIdExceptions?: DemarcheId[]
 }
-export interface DemarcheDefinitionRestriction extends DemarcheDefinitionCommon {
-  restrictions: IDemarcheDefinitionRestrictions
-}
-export interface DemarcheDefinitionMachine extends DemarcheDefinitionCommon {
+export interface DemarcheDefinition extends DemarcheDefinitionCommon {
   machine: CaminoMachines
 }
 
-type IContenuOperation = {
-  valeur: IContenuValeur
-  operation?: 'NOT_EQUAL' | 'EQUAL'
-}
-
-export interface IContenuElementCondition {
-  [id: string]: IContenuOperation | undefined
-}
-
-interface IContenuCondition {
-  [id: string]: IContenuElementCondition
-}
-
-export interface ITitreCondition {
-  statutId?: string
-  contenu: IContenuCondition
-}
-
 const plusVieilleDateEnBase = toCaminoDate('1717-01-09')
-export const demarchesDefinitions: IDemarcheDefinition[] = [
+export const demarchesDefinitions: DemarcheDefinition[] = [
   {
     titreTypeId: 'arm',
     demarcheTypeIds: ['oct'],
@@ -91,8 +40,17 @@ export const demarchesDefinitions: IDemarcheDefinition[] = [
   {
     titreTypeId: 'prm',
     demarcheTypeIds: ['oct'],
-    restrictions: etatsDefinitionPrmOct,
+    machine: new PrmOctMachine(),
     dateDebut: toCaminoDate('2019-10-31'),
+    demarcheIdExceptions: [
+      newDemarcheId('FfJTtP9EEfvf3VZy81hpF7ms'),
+      newDemarcheId('lynG9hx3x05LaqpySr0qxeca'),
+      newDemarcheId('xjvFNG3I8YOv2xLw6FQJjTab'),
+      newDemarcheId('fWlR3sADjURm21wM2j7UZF3R'),
+      newDemarcheId('eySDrrpK4KKukIw3II3nk3G1'),
+      newDemarcheId('PYrSWWMeDDDYfJfgWa09LVlp'),
+      newDemarcheId('R0XYcNUZrJFzZ8DghumpwqXw'),
+    ],
   },
   {
     titreTypeId: 'axm',
@@ -152,7 +110,7 @@ export const demarcheDefinitionFind = (
   demarcheTypeId: DemarcheTypeId,
   titreEtapes: Pick<ITitreEtape, 'date' | 'typeId'>[] | undefined,
   demarcheId: DemarcheId
-): IDemarcheDefinition | undefined => {
+): DemarcheDefinition | undefined => {
   const date = titreDemarcheDepotDemandeDateFind(titreEtapes)
 
   const definition = demarchesDefinitions
diff --git a/packages/api/src/business/rules-demarches/etat-cycles.ts b/packages/api/src/business/rules-demarches/etat-cycles.ts
deleted file mode 100644
index f363b1f4f..000000000
--- a/packages/api/src/business/rules-demarches/etat-cycles.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { IDemarcheDefinitionRestrictionsElements } from './definitions.js'
-
-const etatCycleGet = (etapeTypeIdDefinition: IDemarcheDefinitionRestrictionsElements, demandeEtapeTypeId: string, receptionEtapeTypeId: string) => {
-  const newEtapeTypeIdDefinition = Object.assign({}, etapeTypeIdDefinition)
-  delete newEtapeTypeIdDefinition.etapeTypeId
-
-  return {
-    [demandeEtapeTypeId]: {
-      avant: [[{ etapeTypeId: etapeTypeIdDefinition.etapeTypeId }]],
-      justeApres: [...etapeTypeIdDefinition.justeApres, [{ etapeTypeId: receptionEtapeTypeId }]],
-    },
-    [receptionEtapeTypeId]: {
-      justeApres: [[{ etapeTypeId: demandeEtapeTypeId }]],
-    },
-    [etapeTypeIdDefinition.etapeTypeId!]: {
-      ...newEtapeTypeIdDefinition,
-      avant: [[{ etapeTypeId: etapeTypeIdDefinition.etapeTypeId }]],
-      justeApres: [...etapeTypeIdDefinition.justeApres, [{ etapeTypeId: receptionEtapeTypeId }]],
-    },
-  }
-}
-
-const etatInformationsGet = (mifId: string, rifId: string, etapeTypeIdDefinition: IDemarcheDefinitionRestrictionsElements) => etatCycleGet(etapeTypeIdDefinition, mifId, rifId)
-
-const etatComplementsGet = (mcoId: string, rcoId: string, etapeTypeIdDefinition: IDemarcheDefinitionRestrictionsElements) => etatCycleGet(etapeTypeIdDefinition, mcoId, rcoId)
-
-export { etatInformationsGet, etatComplementsGet }
diff --git a/packages/api/src/business/rules-demarches/machine-common.test.ts b/packages/api/src/business/rules-demarches/machine-common.test.ts
index 4cd1d2c47..57268f147 100644
--- a/packages/api/src/business/rules-demarches/machine-common.test.ts
+++ b/packages/api/src/business/rules-demarches/machine-common.test.ts
@@ -1,7 +1,8 @@
 import { toCaminoDate } from 'camino-common/src/date.js'
-import { ITitreEtape } from '../../types.js'
-import { toMachineEtapes } from './machine-common.js'
-import { describe, expect, test } from 'vitest'
+import { TitreEtapeForMachine, toMachineEtapes } from './machine-common.js'
+import { describe, expect, test, vi } from 'vitest'
+
+console.error = vi.fn()
 describe('toMachineEtapes', () => {
   test('transforme une étape de la bdd en étape de machine', () => {
     expect(
@@ -10,6 +11,10 @@ describe('toMachineEtapes', () => {
           typeId: 'mfr',
           statutId: 'fai',
           date: toCaminoDate('2022-01-01'),
+          communes: [],
+          ordre: 0,
+          surface: null,
+          contenu: null,
         },
       ])
     ).toEqual([
@@ -27,6 +32,9 @@ describe('toMachineEtapes', () => {
           statutId: 'fai',
           date: toCaminoDate('2022-01-01'),
           contenu: { arm: { mecanise: true } },
+          communes: [],
+          ordre: 0,
+          surface: null,
         },
       ])
     ).toEqual([
@@ -47,8 +55,7 @@ describe('toMachineEtapes', () => {
           typeId: 'iii',
           statutId: 'fai',
           date: '2022-01-01',
-          titreDemarcheId: 'idDemarche',
-        } as unknown as ITitreEtape,
+        } as unknown as TitreEtapeForMachine,
       ])
     ).toThrowErrorMatchingInlineSnapshot(`"l'état iii est inconnu"`)
   })
@@ -61,11 +68,8 @@ describe('toMachineEtapes', () => {
           typeId: 'mfr',
           statutId: 'ffi',
           date: '2022-01-01',
-          titreDemarcheId: 'idDemarche',
-        } as unknown as ITitreEtape,
+        } as unknown as TitreEtapeForMachine,
       ])
-    ).toThrowErrorMatchingInlineSnapshot(
-      `"le status ffi est inconnu, {\\"id\\":\\"id\\",\\"typeId\\":\\"mfr\\",\\"statutId\\":\\"ffi\\",\\"date\\":\\"2022-01-01\\",\\"titreDemarcheId\\":\\"idDemarche\\"}"`
-    )
+    ).toThrowErrorMatchingInlineSnapshot(`"le status ffi est inconnu, {\\"id\\":\\"id\\",\\"typeId\\":\\"mfr\\",\\"statutId\\":\\"ffi\\",\\"date\\":\\"2022-01-01\\"}"`)
   })
 })
diff --git a/packages/api/src/business/rules-demarches/machine-common.ts b/packages/api/src/business/rules-demarches/machine-common.ts
index 68ee18dd6..d0c787f25 100644
--- a/packages/api/src/business/rules-demarches/machine-common.ts
+++ b/packages/api/src/business/rules-demarches/machine-common.ts
@@ -1,17 +1,24 @@
 import { IContenu, ITitreEtape } from '../../types.js'
-import { EtapeStatutId, EtapeStatutKey, ETAPES_STATUTS, isStatut } from 'camino-common/src/static/etapesStatuts.js'
-import { EtapeTypeId, isEtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
+import { EtapeStatutId, EtapeStatutKey, ETAPES_STATUTS, isStatut, etapeStatutIdValidator } from 'camino-common/src/static/etapesStatuts.js'
+import { EtapeTypeId, etapeTypeIdValidator, isEtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
 import { ADMINISTRATION_IDS } from 'camino-common/src/static/administrations.js'
 import { EtapeTypeEtapeStatut } from 'camino-common/src/static/etapesTypesEtapesStatuts.js'
 import { DemarcheStatutId } from 'camino-common/src/static/demarchesStatuts.js'
-import { CaminoDate } from 'camino-common/src/date.js'
-
+import { CaminoDate, caminoDateValidator } from 'camino-common/src/date.js'
+import { Departements, toDepartementId } from 'camino-common/src/static/departement.js'
+import { Regions } from 'camino-common/src/static/region.js'
+import { PaysId } from 'camino-common/src/static/pays.js'
+import { communeIdValidator } from 'camino-common/src/static/communes.js'
+import { z } from 'zod'
+import { etapeIdValidator } from 'camino-common/src/etape.js'
 export interface Etape {
   // TODO 2022-07-28 : ceci pourrait être réduit en utilisant les états de 'trad'
   etapeTypeId: EtapeTypeId
   etapeStatutId: EtapeStatutId
   date: CaminoDate
   contenu?: IContenu
+  paysId?: PaysId
+  surface?: number
 }
 
 export interface CaminoCommonContext {
@@ -19,7 +26,22 @@ export interface CaminoCommonContext {
   visibilite: 'confidentielle' | 'publique'
 }
 
-export const toMachineEtapes = (etapes: Pick<ITitreEtape, 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu'>[]): Etape[] => {
+export const titreEtapeForMachineValidator = z.object({
+  ordre: z.number(),
+  id: etapeIdValidator,
+  typeId: etapeTypeIdValidator,
+  statutId: etapeStatutIdValidator,
+  date: caminoDateValidator,
+  contenu: z.any().nullable(),
+  heritageContenu: z.any().nullable(),
+  communes: z.array(z.object({ id: communeIdValidator })).nullable(),
+  surface: z.number().nullable(),
+})
+
+export type TitreEtapeForMachine = z.infer<typeof titreEtapeForMachineValidator>
+export const isTitreEtapeForMachine = (etape: Omit<ITitreEtape, 'titreDemarcheId'>): etape is TitreEtapeForMachine => titreEtapeForMachineValidator.safeParse(etape).success
+
+export const toMachineEtapes = (etapes: (Pick<Partial<TitreEtapeForMachine>, 'ordre'> & Omit<TitreEtapeForMachine, 'id' | 'ordre'>)[]): Etape[] => {
   // FIXME si on appelle titreEtapesSortAscByOrdre on se retrouve avec une grosse dépendance cyclique
   return etapes
     .slice()
@@ -27,7 +49,7 @@ export const toMachineEtapes = (etapes: Pick<ITitreEtape, 'ordre' | 'typeId' | '
     .map(dbEtape => toMachineEtape(dbEtape))
 }
 
-const toMachineEtape = (dbEtape: Pick<ITitreEtape, 'typeId' | 'statutId' | 'date' | 'contenu'>): Etape => {
+const toMachineEtape = (dbEtape: Omit<TitreEtapeForMachine, 'id' | 'ordre'>): Etape => {
   let typeId
   if (isEtapeTypeId(dbEtape.typeId)) {
     typeId = dbEtape.typeId
@@ -50,6 +72,12 @@ const toMachineEtape = (dbEtape: Pick<ITitreEtape, 'typeId' | 'statutId' | 'date
   if (dbEtape.contenu) {
     machineEtape.contenu = dbEtape.contenu
   }
+  if (dbEtape.communes?.length) {
+    machineEtape.paysId = Regions[Departements[toDepartementId(dbEtape.communes[0].id)].regionId].paysId
+  }
+  if (dbEtape.surface !== null) {
+    machineEtape.surface = dbEtape.surface
+  }
 
   return machineEtape
 }
diff --git a/packages/api/src/business/rules-demarches/machines.ts b/packages/api/src/business/rules-demarches/machines.ts
index f2b5ce503..343c0c77a 100644
--- a/packages/api/src/business/rules-demarches/machines.ts
+++ b/packages/api/src/business/rules-demarches/machines.ts
@@ -1,7 +1,8 @@
-import { ArmOctMachine } from './arm/oct.machine.js'
-import { ArmRenProMachine } from './arm/ren-pro.machine.js'
-import { AxmOctMachine } from './axm/oct.machine.js'
-import { AxmProMachine } from './axm/pro.machine.js'
-import { PxgOctMachine } from './pxg/oct.machine.js'
+import type { ArmOctMachine } from './arm/oct.machine.js'
+import type { ArmRenProMachine } from './arm/ren-pro.machine.js'
+import type { AxmOctMachine } from './axm/oct.machine.js'
+import type { AxmProMachine } from './axm/pro.machine.js'
+import type { PrmOctMachine } from './prm/oct.machine.js'
+import type { PxgOctMachine } from './pxg/oct.machine.js'
 
-export type CaminoMachines = ArmOctMachine | AxmOctMachine | PxgOctMachine | AxmProMachine | ArmRenProMachine
+export type CaminoMachines = ArmOctMachine | AxmOctMachine | PxgOctMachine | AxmProMachine | ArmRenProMachine | PrmOctMachine
diff --git a/packages/api/src/business/rules-demarches/prm/oct.cas.json b/packages/api/src/business/rules-demarches/prm/oct.cas.json
new file mode 100644
index 000000000..ff1f58577
--- /dev/null
+++ b/packages/api/src/business/rules-demarches/prm/oct.cas.json
@@ -0,0 +1 @@
+[{"id":0,"demarcheStatutId":"ins","demarchePublique":true,"etapes":[{"date":"2022-08-13","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"FR"},{"date":"2022-08-13","etapeTypeId":"mdp","etapeStatutId":"fai"},{"date":"2022-08-16","etapeTypeId":"spp","etapeStatutId":"fai"},{"date":"2022-12-06","etapeTypeId":"mcr","etapeStatutId":"fav"},{"date":"2022-12-12","etapeTypeId":"anf","etapeStatutId":"ter","paysId":"FR"},{"date":"2023-04-28","etapeTypeId":"ppu","etapeStatutId":"pro"}]},{"id":1,"demarcheStatutId":"eco","demarchePublique":false,"etapes":[{"date":"2022-12-07","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"FR"}]},{"id":2,"demarcheStatutId":"ins","demarchePublique":true,"etapes":[{"date":"2023-02-17","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"FR"},{"date":"2023-03-05","etapeTypeId":"mdp","etapeStatutId":"fai"},{"date":"2023-03-19","etapeTypeId":"spp","etapeStatutId":"fai"},{"date":"2023-04-07","etapeTypeId":"mcr","etapeStatutId":"fav"},{"date":"2023-04-18","etapeTypeId":"anf","etapeStatutId":"enc","paysId":"FR"}]},{"id":3,"demarcheStatutId":"dep","demarchePublique":false,"etapes":[{"date":"2022-04-19","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"GF"},{"date":"2022-05-10","etapeTypeId":"mdp","etapeStatutId":"fai"},{"date":"2022-05-16","etapeTypeId":"spp","etapeStatutId":"fai"}]},{"id":4,"demarcheStatutId":"dep","demarchePublique":false,"etapes":[{"date":"2019-11-24","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"GF"},{"date":"2019-12-22","etapeTypeId":"mdp","etapeStatutId":"fai"},{"date":"2020-02-18","etapeTypeId":"spp","etapeStatutId":"fai"},{"date":"2020-06-22","etapeTypeId":"mif","etapeStatutId":"fai"},{"date":"2020-07-28","etapeTypeId":"rif","etapeStatutId":"fai"}]},{"id":5,"demarcheStatutId":"dep","demarchePublique":false,"etapes":[{"date":"2019-10-31","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"GF"},{"date":"2019-11-28","etapeTypeId":"mdp","etapeStatutId":"fai"},{"date":"2020-01-25","etapeTypeId":"spp","etapeStatutId":"fai"},{"date":"2020-05-30","etapeTypeId":"mif","etapeStatutId":"fai"},{"date":"2020-07-04","etapeTypeId":"rif","etapeStatutId":"fai"}]},{"id":6,"demarcheStatutId":"dep","demarchePublique":false,"etapes":[{"date":"2020-10-15","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"GF"},{"date":"2020-12-10","etapeTypeId":"mdp","etapeStatutId":"fai"},{"date":"2021-01-11","etapeTypeId":"spp","etapeStatutId":"fai"}]},{"id":7,"demarcheStatutId":"ins","demarchePublique":true,"etapes":[{"date":"2022-07-25","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"FR"},{"date":"2022-07-25","etapeTypeId":"mdp","etapeStatutId":"fai"},{"date":"2022-08-22","etapeTypeId":"spp","etapeStatutId":"fai"},{"date":"2022-10-10","etapeTypeId":"mcr","etapeStatutId":"fav"},{"date":"2022-11-30","etapeTypeId":"anf","etapeStatutId":"ter","paysId":"FR"},{"date":"2023-01-22","etapeTypeId":"ppu","etapeStatutId":"fai"}]},{"id":8,"demarcheStatutId":"ins","demarchePublique":true,"etapes":[{"date":"2022-04-16","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"FR"},{"date":"2022-05-13","etapeTypeId":"mdp","etapeStatutId":"fai"},{"date":"2022-06-22","etapeTypeId":"spp","etapeStatutId":"fai"},{"date":"2022-10-07","etapeTypeId":"mcr","etapeStatutId":"fav"},{"date":"2023-01-14","etapeTypeId":"anf","etapeStatutId":"fai","paysId":"FR"}]},{"id":9,"demarcheStatutId":"eco","demarchePublique":false,"etapes":[{"date":"2023-03-14","etapeTypeId":"mfr","etapeStatutId":"fai","paysId":"FR"}]}]
\ No newline at end of file
diff --git a/packages/api/src/business/rules-demarches/prm/oct.machine.test.ts b/packages/api/src/business/rules-demarches/prm/oct.machine.test.ts
new file mode 100644
index 000000000..18584e278
--- /dev/null
+++ b/packages/api/src/business/rules-demarches/prm/oct.machine.test.ts
@@ -0,0 +1,167 @@
+import { interpretMachine, orderAndInterpretMachine } from '../machine-test-helper.js'
+import { PrmOctMachine } from './oct.machine.js'
+import { EtapesTypesEtapesStatuts as ETES } from 'camino-common/src/static/etapesTypesEtapesStatuts.js'
+import { toCaminoDate } from 'camino-common/src/date.js'
+import { describe, expect, test } from 'vitest'
+import { PAYS_IDS } from 'camino-common/src/static/pays.js'
+const etapesProd = require('./oct.cas.json')
+
+describe('vérifie l’arbre d’octroi de PRM', () => {
+  const prmOctMachine = new PrmOctMachine()
+  test('peut créer une demande d’octroi de PRM complète en Métropole', () => {
+    const etapes = [
+      { ...ETES.demande.FAIT, date: toCaminoDate('2022-04-14'), paysId: PAYS_IDS['République Française'] },
+      { ...ETES.depotDeLaDemande.FAIT, date: toCaminoDate('2022-04-15') },
+      { ...ETES.saisineDuPrefet.FAIT, date: toCaminoDate('2022-04-16') },
+      { ...ETES.recevabiliteDeLaDemande.FAVORABLE, date: toCaminoDate('2022-04-17') },
+      { ...ETES.avisDeMiseEnConcurrenceAuJORF.FAIT, date: toCaminoDate('2022-04-18') },
+      { ...ETES.saisineDesServices.FAIT, date: toCaminoDate('2022-04-19') },
+      { ...ETES.avisDeLOfficeNationalDesForets.FAVORABLE, date: toCaminoDate('2022-04-20') },
+      { ...ETES.avisEtRapportDuDirecteurRegionalChargeDeLenvironnementDeLamenagementEtDuLogement.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.avisDuPrefet.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.ouvertureDeLaParticipationDuPublic.FAIT, date: toCaminoDate('2022-05-18') },
+      { ...ETES.clotureDeLaParticipationDuPublic.TERMINE, date: toCaminoDate('2022-05-19') },
+      { ...ETES.consultationDesAdministrationsCentrales.FAIT, date: toCaminoDate('2022-05-21') },
+      { ...ETES.saisineDuConseilGeneralDeLeconomie_CGE_.FAIT, date: toCaminoDate('2022-05-22') },
+      { ...ETES.rapportDuConseilGeneralDeLeconomie_CGE_.FAVORABLE, date: toCaminoDate('2022-05-23') },
+      { ...ETES.avisDuConseilGeneralDeLeconomie_CGE_.FAVORABLE, date: toCaminoDate('2022-05-24') },
+      { ...ETES.saisineDeLautoriteSignataire.FAIT, date: toCaminoDate('2022-05-25') },
+      { ...ETES.decisionDeLadministration.ACCEPTE, date: toCaminoDate('2022-05-26') },
+      { ...ETES.publicationDeDecisionAuJORF.ACCEPTE, date: toCaminoDate('2022-05-27') },
+      { ...ETES.notificationDesCollectivitesLocales.FAIT, date: toCaminoDate('2022-05-28') },
+      { ...ETES.publicationDeDecisionAuRecueilDesActesAdministratifs.FAIT, date: toCaminoDate('2022-05-29') },
+      { ...ETES.publicationDansUnJournalLocalOuNational.FAIT, date: toCaminoDate('2022-05-30') },
+      { ...ETES.notificationAuDemandeur.FAIT, date: toCaminoDate('2022-05-31') },
+      { ...ETES.notificationAuPrefet.FAIT, date: toCaminoDate('2022-05-31') },
+    ]
+    const service = orderAndInterpretMachine(prmOctMachine, etapes)
+    expect(service).canOnlyTransitionTo({ machine: prmOctMachine, date: toCaminoDate('2022-07-01') }, [])
+    expect(prmOctMachine.demarcheStatut(etapes)).toMatchInlineSnapshot(`
+      {
+        "demarcheStatut": "acc",
+        "publique": true,
+      }
+    `)
+  })
+
+  test('peut créer une demande d’octroi de PRM en Guyane', () => {
+    const etapes = [
+      { ...ETES.demande.FAIT, date: toCaminoDate('2022-04-14'), paysId: PAYS_IDS['Département de la Guyane'], surface: 200 },
+      { ...ETES.depotDeLaDemande.FAIT, date: toCaminoDate('2022-04-15') },
+      { ...ETES.saisineDuPrefet.FAIT, date: toCaminoDate('2022-04-16') },
+      { ...ETES.recevabiliteDeLaDemande.FAVORABLE, date: toCaminoDate('2022-04-17') },
+      { ...ETES.avisDeMiseEnConcurrenceAuJORF.FAIT, date: toCaminoDate('2022-04-18') },
+      { ...ETES.saisineDesServices.FAIT, date: toCaminoDate('2022-04-19') },
+      { ...ETES.saisineDesCollectivitesLocales.FAIT, date: toCaminoDate('2022-04-19') },
+      { ...ETES.avisDunMaire.FAVORABLE, date: toCaminoDate('2022-04-19') },
+      { ...ETES.avisDeLOfficeNationalDesForets.FAVORABLE, date: toCaminoDate('2022-04-20') },
+      { ...ETES.avisDeLaCommissionDepartementaleDesMines_CDM_.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.avisEtRapportDuDirecteurRegionalChargeDeLenvironnementDeLamenagementEtDuLogement.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.avisDuPrefet.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.ouvertureDeLaParticipationDuPublic.FAIT, date: toCaminoDate('2022-05-18') },
+      { ...ETES.clotureDeLaParticipationDuPublic.TERMINE, date: toCaminoDate('2022-05-19') },
+    ]
+    expect(() => orderAndInterpretMachine(prmOctMachine, etapes)).not.toThrowError()
+  })
+
+  test('peut créer une demande d’octroi de PRM en Outre mer (hors Guyane)', () => {
+    const etapes = [
+      { ...ETES.demande.FAIT, date: toCaminoDate('2022-04-14'), paysId: PAYS_IDS['Wallis-et-Futuna'] },
+      { ...ETES.depotDeLaDemande.FAIT, date: toCaminoDate('2022-04-15') },
+      { ...ETES.saisineDuPrefet.FAIT, date: toCaminoDate('2022-04-16') },
+      { ...ETES.recevabiliteDeLaDemande.FAVORABLE, date: toCaminoDate('2022-04-17') },
+      { ...ETES.avisDeMiseEnConcurrenceAuJORF.FAIT, date: toCaminoDate('2022-04-18') },
+      { ...ETES.saisineDesServices.FAIT, date: toCaminoDate('2022-04-19') },
+      { ...ETES.avisDeLOfficeNationalDesForets.FAVORABLE, date: toCaminoDate('2022-04-20') },
+      { ...ETES.avisDeLaCommissionDepartementaleDesMines_CDM_.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.avisEtRapportDuDirecteurRegionalChargeDeLenvironnementDeLamenagementEtDuLogement.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.avisDuPrefet.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.ouvertureDeLaParticipationDuPublic.FAIT, date: toCaminoDate('2022-05-18') },
+      { ...ETES.clotureDeLaParticipationDuPublic.TERMINE, date: toCaminoDate('2022-05-19') },
+    ]
+    expect(() => orderAndInterpretMachine(prmOctMachine, etapes)).not.toThrowError()
+  })
+
+  test('ne peut pas faire l’avis de la DREAL si la saisine des services a été faite dans les 30 jours', () => {
+    const etapes = [
+      { ...ETES.demande.FAIT, date: toCaminoDate('2022-04-14'), paysId: PAYS_IDS['République Française'] },
+      { ...ETES.depotDeLaDemande.FAIT, date: toCaminoDate('2022-04-15') },
+      { ...ETES.saisineDuPrefet.FAIT, date: toCaminoDate('2022-04-16') },
+      { ...ETES.recevabiliteDeLaDemande.FAVORABLE, date: toCaminoDate('2022-04-17') },
+      { ...ETES.avisDeMiseEnConcurrenceAuJORF.FAIT, date: toCaminoDate('2022-04-18') },
+      { ...ETES.saisineDesServices.FAIT, date: toCaminoDate('2022-04-19') },
+      { ...ETES.avisEtRapportDuDirecteurRegionalChargeDeLenvironnementDeLamenagementEtDuLogement.FAVORABLE, date: toCaminoDate('2022-04-20') },
+    ]
+    expect(() => orderAndInterpretMachine(prmOctMachine, etapes)).toThrowErrorMatchingInlineSnapshot(
+      '"Error: cannot execute step: \'{\\"etapeTypeId\\":\\"apd\\",\\"etapeStatutId\\":\\"fav\\",\\"ordre\\":1,\\"date\\":\\"2022-04-20\\"}\' after \'[\\"mfr_fai\\",\\"mdp_fai\\",\\"spp_fai\\",\\"mcr_fav\\",\\"anf_fai\\",\\"ssr_fai\\"]\'. The event {\\"type\\":\\"RENDRE_RAPPORT_DREAL\\",\\"date\\":\\"2022-04-20\\"} should be one of \'RENDRE_AVIS_SERVICE_ADMINISTRATIF_CIVIL_LOCAL,RENDRE_AVIS_AUTORITE_MILITAIRE,RENDRE_AVIS_DES_DTT,RENDRE_AVIS_PARC_NATUREL_REGIONAL,RENDRE_AVIS_PARC_NATIONAL,RENDRE_AVIS_AGENCE_REGIONALE_SANTE_ARS,RENDRE_AVIS_ONF,RENDRE_AVIS_INSTITUT_NATIONAL_ORIGINE_ET_QUALITE_INAO,RENDRE_AVIS_DIRECTION_REGIONALE_AFFAIRES_CULTURELLES,RENDRE_AVIS_DIRECTION_REGIONALE_FINANCES_PUBLIQUES,MODIFIER_DEMANDE,DEMANDER_INFORMATIONS,RECEVOIR_INFORMATIONS,DESISTER_PAR_LE_DEMANDEUR,CLASSER_SANS_SUITE,DEPOSER_DEMANDE_CONCURRENTE\'"'
+    )
+  })
+
+  test('ne peut pas faire 2 saisines des services', () => {
+    const etapes = [
+      { ...ETES.demande.FAIT, date: toCaminoDate('2022-04-14'), paysId: PAYS_IDS['République Française'] },
+      { ...ETES.depotDeLaDemande.FAIT, date: toCaminoDate('2022-04-15') },
+      { ...ETES.saisineDuPrefet.FAIT, date: toCaminoDate('2022-04-16') },
+      { ...ETES.recevabiliteDeLaDemande.FAVORABLE, date: toCaminoDate('2022-04-17') },
+      { ...ETES.avisDeMiseEnConcurrenceAuJORF.FAIT, date: toCaminoDate('2022-04-18') },
+      { ...ETES.saisineDesServices.FAIT, date: toCaminoDate('2022-04-19') },
+      { ...ETES.saisineDesServices.FAIT, date: toCaminoDate('2022-04-19') },
+    ]
+    expect(() => orderAndInterpretMachine(prmOctMachine, etapes)).toThrowErrorMatchingInlineSnapshot(
+      '"Error: cannot execute step: \'{\\"etapeTypeId\\":\\"ssr\\",\\"etapeStatutId\\":\\"fai\\",\\"ordre\\":1,\\"date\\":\\"2022-04-19\\"}\' after \'[\\"mfr_fai\\",\\"mdp_fai\\",\\"spp_fai\\",\\"mcr_fav\\",\\"anf_fai\\",\\"ssr_fai\\"]\'. The event {\\"type\\":\\"FAIRE_SAISINE_DES_SERVICES\\",\\"date\\":\\"2022-04-19\\"} should be one of \'RENDRE_AVIS_SERVICE_ADMINISTRATIF_CIVIL_LOCAL,RENDRE_AVIS_AUTORITE_MILITAIRE,RENDRE_AVIS_DES_DTT,RENDRE_AVIS_PARC_NATUREL_REGIONAL,RENDRE_AVIS_PARC_NATIONAL,RENDRE_AVIS_AGENCE_REGIONALE_SANTE_ARS,RENDRE_AVIS_ONF,RENDRE_AVIS_INSTITUT_NATIONAL_ORIGINE_ET_QUALITE_INAO,RENDRE_AVIS_DIRECTION_REGIONALE_AFFAIRES_CULTURELLES,RENDRE_AVIS_DIRECTION_REGIONALE_FINANCES_PUBLIQUES,MODIFIER_DEMANDE,DEMANDER_INFORMATIONS,RECEVOIR_INFORMATIONS,DESISTER_PAR_LE_DEMANDEUR,CLASSER_SANS_SUITE,DEPOSER_DEMANDE_CONCURRENTE\'"'
+    )
+  })
+
+  test('ne peut pas ouvrir la participation du public si la mise en concurrence n’est pas terminée', () => {
+    const etapes = [
+      { ...ETES.demande.FAIT, date: toCaminoDate('2022-04-14'), paysId: PAYS_IDS['République Française'] },
+      { ...ETES.depotDeLaDemande.FAIT, date: toCaminoDate('2022-04-15') },
+      { ...ETES.saisineDuPrefet.FAIT, date: toCaminoDate('2022-04-16') },
+      { ...ETES.recevabiliteDeLaDemande.FAVORABLE, date: toCaminoDate('2022-04-17') },
+      { ...ETES.avisDeMiseEnConcurrenceAuJORF.FAIT, date: toCaminoDate('2022-04-18') },
+      { ...ETES.ouvertureDeLaParticipationDuPublic.FAIT, date: toCaminoDate('2022-04-19') },
+    ]
+    expect(() => orderAndInterpretMachine(prmOctMachine, etapes)).toThrowErrorMatchingInlineSnapshot(
+      '"Error: cannot execute step: \'{\\"etapeTypeId\\":\\"ppu\\",\\"etapeStatutId\\":\\"fai\\",\\"ordre\\":2,\\"date\\":\\"2022-04-19\\"}\' after \'[\\"mfr_fai\\",\\"mdp_fai\\",\\"spp_fai\\",\\"mcr_fav\\",\\"anf_fai\\"]\'. The event {\\"type\\":\\"OUVRIR_PARTICIPATION_DU_PUBLIC\\",\\"date\\":\\"2022-04-19\\"} should be one of \'MODIFIER_DEMANDE,DEMANDER_INFORMATIONS,RECEVOIR_INFORMATIONS,DESISTER_PAR_LE_DEMANDEUR,CLASSER_SANS_SUITE,FAIRE_SAISINE_DES_SERVICES,DEPOSER_DEMANDE_CONCURRENTE\'"'
+    )
+  })
+
+  test('ne peut pas créer une "rpu" après une "dex" rejetée', () => {
+    const etapes = [
+      { ...ETES.demande.FAIT, date: toCaminoDate('2022-04-14'), paysId: PAYS_IDS['République Française'] },
+      { ...ETES.depotDeLaDemande.FAIT, date: toCaminoDate('2022-04-15') },
+      { ...ETES.saisineDuPrefet.FAIT, date: toCaminoDate('2022-04-16') },
+      { ...ETES.recevabiliteDeLaDemande.FAVORABLE, date: toCaminoDate('2022-04-17') },
+      { ...ETES.avisDeMiseEnConcurrenceAuJORF.FAIT, date: toCaminoDate('2022-04-18') },
+      { ...ETES.saisineDesServices.FAIT, date: toCaminoDate('2022-04-19') },
+      { ...ETES.avisDeLOfficeNationalDesForets.FAVORABLE, date: toCaminoDate('2022-04-20') },
+      { ...ETES.avisEtRapportDuDirecteurRegionalChargeDeLenvironnementDeLamenagementEtDuLogement.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.avisDuPrefet.FAVORABLE, date: toCaminoDate('2022-05-20') },
+      { ...ETES.ouvertureDeLaParticipationDuPublic.FAIT, date: toCaminoDate('2022-05-18') },
+      { ...ETES.clotureDeLaParticipationDuPublic.TERMINE, date: toCaminoDate('2022-05-19') },
+      { ...ETES.consultationDesAdministrationsCentrales.FAIT, date: toCaminoDate('2022-05-21') },
+      { ...ETES.saisineDuConseilGeneralDeLeconomie_CGE_.FAIT, date: toCaminoDate('2022-05-22') },
+      { ...ETES.rapportDuConseilGeneralDeLeconomie_CGE_.FAVORABLE, date: toCaminoDate('2022-05-23') },
+      { ...ETES.avisDuConseilGeneralDeLeconomie_CGE_.FAVORABLE, date: toCaminoDate('2022-05-24') },
+      { ...ETES.saisineDeLautoriteSignataire.FAIT, date: toCaminoDate('2022-05-25') },
+      { ...ETES.decisionDeLadministration.REJETE, date: toCaminoDate('2022-05-26') },
+      { ...ETES.notificationAuPrefet.FAIT, date: toCaminoDate('2022-05-31') },
+      { ...ETES.notificationAuDemandeur.FAIT, date: toCaminoDate('2022-06-01') },
+      { ...ETES.publicationDeDecisionAuRecueilDesActesAdministratifs.FAIT, date: toCaminoDate('2022-06-01') },
+    ]
+
+    expect(() => orderAndInterpretMachine(prmOctMachine, etapes)).toThrowErrorMatchingInlineSnapshot(
+      '"Error: cannot execute step: \'{\\"etapeTypeId\\":\\"rpu\\",\\"etapeStatutId\\":\\"fai\\",\\"ordre\\":3,\\"date\\":\\"2022-06-01\\"}\' after \'[\\"mfr_fai\\",\\"mdp_fai\\",\\"spp_fai\\",\\"mcr_fav\\",\\"anf_fai\\",\\"ssr_fai\\",\\"aof_fav\\",\\"ppu_fai\\",\\"ppc_ter\\",\\"apd_fav\\",\\"app_fav\\",\\"cac_fai\\",\\"scg_fai\\",\\"rcg_fav\\",\\"acg_fav\\",\\"sas_fai\\",\\"dex_rej\\",\\"npp_fai\\",\\"mno_fai\\"]\'. The event {\\"type\\":\\"PUBLIER_DECISIONS_RECUEIL_ACTES_ADMINISTRATIFS\\"} should be one of \'RENDRE_DECISION_ANNULATION_PAR_JUGE_ADMINISTRATIF,RENDRE_DECISION_ABROGATION,RENDRE_DECISION_RETRAIT\'"'
+    )
+  })
+
+  // pour regénérer le oct.cas.json: `npm run test:generate-data -w packages/api`
+  test.each(etapesProd as any[])('cas réel N°$id', demarche => {
+    // ici les étapes sont déjà ordonnées
+    interpretMachine(prmOctMachine, demarche.etapes)
+    expect(prmOctMachine.demarcheStatut(demarche.etapes)).toStrictEqual({
+      demarcheStatut: demarche.demarcheStatutId,
+      publique: demarche.demarchePublique,
+    })
+  })
+})
diff --git a/packages/api/src/business/rules-demarches/prm/oct.machine.ts b/packages/api/src/business/rules-demarches/prm/oct.machine.ts
new file mode 100644
index 000000000..126d6ebb7
--- /dev/null
+++ b/packages/api/src/business/rules-demarches/prm/oct.machine.ts
@@ -0,0 +1,723 @@
+import { assign, createMachine } from 'xstate'
+import { EtapesTypesEtapesStatuts } from 'camino-common/src/static/etapesTypesEtapesStatuts.js'
+import { CaminoMachine } from '../machine-helper.js'
+import { CaminoCommonContext, DBEtat, Etape } from '../machine-common.js'
+import { DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts.js'
+import { CaminoDate, dateAddMonths, daysBetween } from 'camino-common/src/date.js'
+import { PAYS_IDS, PaysId, isGuyane, isMetropole, isOutreMer } from 'camino-common/src/static/pays.js'
+
+type RendreAvisMiseEnConcurrentJORF = {
+  date: CaminoDate
+  type: 'RENDRE_AVIS_DE_MISE_EN_CONCURRENCE_AU_JORF'
+}
+
+type OuvrirParticipationDuPublic = {
+  date: CaminoDate
+  type: 'OUVRIR_PARTICIPATION_DU_PUBLIC'
+}
+
+type FaireSaisineDesServices = {
+  date: CaminoDate
+  type: 'FAIRE_SAISINE_DES_SERVICES'
+}
+
+type RendreAvisCDM = {
+  date: CaminoDate
+  type: 'RENDRE_AVIS_CDM'
+}
+
+type RendreRapportDREAL = {
+  date: CaminoDate
+  type: 'RENDRE_RAPPORT_DREAL'
+}
+
+type FaireDemande = {
+  type: 'FAIRE_DEMANDE'
+  paysId: PaysId
+  surface: number
+}
+
+export type XStateEvent =
+  | FaireDemande
+  | { type: 'DEPOSER_DEMANDE' }
+  | { type: 'FAIRE_SAISINE_PREFET' }
+  | { type: 'DEMANDER_COMPLEMENTS_POUR_RECEVABILITE' }
+  | { type: 'RECEVOIR_COMPLEMENTS_POUR_RECEVABILITE' }
+  | { type: 'FAIRE_RECEVABILITE_DEMANDE_FAVORABLE' }
+  | { type: 'FAIRE_RECEVABILITE_DEMANDE_DEFAVORABLE' }
+  | RendreAvisMiseEnConcurrentJORF
+  | { type: 'DEPOSER_DEMANDE_CONCURRENTE' }
+  | OuvrirParticipationDuPublic
+  | { type: 'CLOTURER_PARTICIPATION_DU_PUBLIC' }
+  | FaireSaisineDesServices
+  | { type: 'RENDRE_AVIS_ONF' }
+  | { type: 'RENDRE_AVIS_SERVICE_ADMINISTRATIF_CIVIL_LOCAL' }
+  | { type: 'RENDRE_AVIS_AUTORITE_MILITAIRE' }
+  | { type: 'RENDRE_AVIS_DES_DTT' }
+  | { type: 'RENDRE_AVIS_PARC_NATUREL_REGIONAL' }
+  | { type: 'RENDRE_AVIS_PARC_NATIONAL' }
+  | { type: 'RENDRE_AVIS_AGENCE_REGIONALE_SANTE_ARS' }
+  | { type: 'RENDRE_AVIS_INSTITUT_NATIONAL_ORIGINE_ET_QUALITE_INAO' }
+  | { type: 'RENDRE_AVIS_DIRECTION_REGIONALE_AFFAIRES_CULTURELLES' }
+  | { type: 'RENDRE_AVIS_DIRECTION_REGIONALE_FINANCES_PUBLIQUES' }
+  | { type: 'RENDRE_AVIS_POLICE_EAU' }
+  | RendreAvisCDM
+  | RendreRapportDREAL
+  | { type: 'RENDRE_AVIS_PREFET' }
+  | { type: 'FAIRE_SAISINE_DES_COLLECTIVITES_LOCALES' }
+  | { type: 'RENDRE_AVIS_DU_MAIRE' }
+  | { type: 'FAIRE_RAPPORT_ADMINISTRATION_CENTRALE' }
+  | { type: 'FAIRE_SAISINE_CONSEIL_GENERAL_CHARGE_DES_MINES' }
+  | { type: 'FAIRE_RAPPORT_CONSEIL_GENERAL_CHARGE_DES_MINES' }
+  | { type: 'RENDRE_AVIS_CONSEIL_GENERAL_CHARGE_DES_MINES' }
+  | { type: 'FAIRE_SAISINE_AUTORITE_SIGNATAIRE' }
+  | { type: 'RENDRE_DECISION_ADMINISTRATION_ACCEPTE' }
+  | { type: 'RENDRE_DECISION_ADMINISTRATION_REJETE' }
+  | { type: 'FAIRE_PUBLICATION_AU_JORF' }
+  | { type: 'NOTIFIER_PREFET' }
+  | { type: 'NOTIFIER_DEMANDEUR' }
+  | { type: 'PUBLIER_DECISIONS_RECUEIL_ACTES_ADMINISTRATIFS' }
+  | { type: 'PUBLIER_DANS_UN_JOURNAL_LOCAL_OU_NATIONAL' }
+  | { type: 'NOTIFIER_COLLECTIVITES_LOCALES' }
+  | { type: 'RENDRE_DECISION_ANNULATION_PAR_JUGE_ADMINISTRATIF' }
+  | { type: 'RENDRE_DECISION_ABROGATION' }
+  | { type: 'RENDRE_DECISION_RETRAIT' }
+  | { type: 'DESISTER_PAR_LE_DEMANDEUR' }
+  | { type: 'CLASSER_SANS_SUITE' }
+  | { type: 'MODIFIER_DEMANDE' }
+  | { type: 'DEMANDER_INFORMATIONS' }
+  | { type: 'RECEVOIR_INFORMATIONS' }
+
+export type Event = XStateEvent['type']
+
+const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
+  FAIRE_DEMANDE: { db: EtapesTypesEtapesStatuts.demande, mainStep: true },
+  DEPOSER_DEMANDE: { db: EtapesTypesEtapesStatuts.depotDeLaDemande, mainStep: true },
+  FAIRE_SAISINE_PREFET: { db: EtapesTypesEtapesStatuts.saisineDuPrefet, mainStep: true },
+  DEMANDER_COMPLEMENTS_POUR_RECEVABILITE: { db: EtapesTypesEtapesStatuts.demandeDeComplements_RecevabiliteDeLaDemande_, mainStep: false },
+  RECEVOIR_COMPLEMENTS_POUR_RECEVABILITE: { db: EtapesTypesEtapesStatuts.receptionDeComplements_RecevabiliteDeLaDemande_, mainStep: false },
+  FAIRE_RECEVABILITE_DEMANDE_FAVORABLE: {
+    db: {
+      FAVORABLE: EtapesTypesEtapesStatuts.recevabiliteDeLaDemande.FAVORABLE,
+    },
+    mainStep: true,
+  },
+  FAIRE_RECEVABILITE_DEMANDE_DEFAVORABLE: {
+    db: {
+      DEFAVORABLE: EtapesTypesEtapesStatuts.recevabiliteDeLaDemande.DEFAVORABLE,
+    },
+    mainStep: true,
+  },
+  RENDRE_AVIS_DE_MISE_EN_CONCURRENCE_AU_JORF: { db: EtapesTypesEtapesStatuts.avisDeMiseEnConcurrenceAuJORF, mainStep: true },
+  DEPOSER_DEMANDE_CONCURRENTE: { db: EtapesTypesEtapesStatuts.avisDeDemandeConcurrente, mainStep: false },
+  OUVRIR_PARTICIPATION_DU_PUBLIC: { db: EtapesTypesEtapesStatuts.ouvertureDeLaParticipationDuPublic, mainStep: true },
+  CLOTURER_PARTICIPATION_DU_PUBLIC: { db: EtapesTypesEtapesStatuts.clotureDeLaParticipationDuPublic, mainStep: true },
+  FAIRE_SAISINE_DES_SERVICES: { db: EtapesTypesEtapesStatuts.saisineDesServices, mainStep: true },
+  RENDRE_AVIS_ONF: { db: EtapesTypesEtapesStatuts.avisDeLOfficeNationalDesForets, mainStep: false },
+  RENDRE_AVIS_SERVICE_ADMINISTRATIF_CIVIL_LOCAL: { db: EtapesTypesEtapesStatuts.avisDunServiceAdministratifLocal, mainStep: false },
+  RENDRE_AVIS_AUTORITE_MILITAIRE: { db: EtapesTypesEtapesStatuts.avisDeLautoriteMilitaire, mainStep: false },
+  RENDRE_AVIS_DES_DTT: { db: EtapesTypesEtapesStatuts.avisDeLaDirectionDepartementaleDesTerritoiresEtDeLaMerDDT_M_, mainStep: false },
+  RENDRE_AVIS_PARC_NATUREL_REGIONAL: { db: EtapesTypesEtapesStatuts.avisDuParcNaturelRegional, mainStep: false },
+  RENDRE_AVIS_PARC_NATIONAL: { db: EtapesTypesEtapesStatuts.avisDuParcNational, mainStep: false },
+  RENDRE_AVIS_AGENCE_REGIONALE_SANTE_ARS: { db: EtapesTypesEtapesStatuts.avisDeLagenceRegionaleDeSante, mainStep: false },
+  RENDRE_AVIS_INSTITUT_NATIONAL_ORIGINE_ET_QUALITE_INAO: { db: EtapesTypesEtapesStatuts.avisDeLInstitutNationalDeLorigineEtDeLaQualite, mainStep: false },
+  RENDRE_AVIS_DIRECTION_REGIONALE_AFFAIRES_CULTURELLES: { db: EtapesTypesEtapesStatuts.avisDeDirectionRegionaleDesAffairesCulturelles, mainStep: false },
+  RENDRE_AVIS_DIRECTION_REGIONALE_FINANCES_PUBLIQUES: { db: EtapesTypesEtapesStatuts.avisDeLaDirectionRegionaleDesFinancesPubliques, mainStep: false },
+  RENDRE_AVIS_POLICE_EAU: { db: EtapesTypesEtapesStatuts.expertiseDREALOuDGTMServiceEau, mainStep: false },
+
+  RENDRE_AVIS_CDM: { db: EtapesTypesEtapesStatuts.avisDeLaCommissionDepartementaleDesMines_CDM_, mainStep: true },
+  RENDRE_RAPPORT_DREAL: { db: EtapesTypesEtapesStatuts.avisEtRapportDuDirecteurRegionalChargeDeLenvironnementDeLamenagementEtDuLogement, mainStep: true },
+  RENDRE_AVIS_PREFET: { db: EtapesTypesEtapesStatuts.avisDuPrefet, mainStep: true },
+  FAIRE_SAISINE_DES_COLLECTIVITES_LOCALES: { db: EtapesTypesEtapesStatuts.saisineDesCollectivitesLocales, mainStep: true },
+  RENDRE_AVIS_DU_MAIRE: { db: EtapesTypesEtapesStatuts.avisDunMaire, mainStep: true },
+  FAIRE_RAPPORT_ADMINISTRATION_CENTRALE: { db: EtapesTypesEtapesStatuts.consultationDesAdministrationsCentrales, mainStep: true },
+  FAIRE_SAISINE_CONSEIL_GENERAL_CHARGE_DES_MINES: { db: EtapesTypesEtapesStatuts.saisineDuConseilGeneralDeLeconomie_CGE_, mainStep: true },
+  FAIRE_RAPPORT_CONSEIL_GENERAL_CHARGE_DES_MINES: { db: EtapesTypesEtapesStatuts.rapportDuConseilGeneralDeLeconomie_CGE_, mainStep: true },
+  RENDRE_AVIS_CONSEIL_GENERAL_CHARGE_DES_MINES: { db: EtapesTypesEtapesStatuts.avisDuConseilGeneralDeLeconomie_CGE_, mainStep: true },
+  FAIRE_SAISINE_AUTORITE_SIGNATAIRE: { db: EtapesTypesEtapesStatuts.saisineDeLautoriteSignataire, mainStep: true },
+  RENDRE_DECISION_ADMINISTRATION_ACCEPTE: { db: { ACCEPTE: EtapesTypesEtapesStatuts.decisionDeLadministration.ACCEPTE }, mainStep: true },
+  RENDRE_DECISION_ADMINISTRATION_REJETE: { db: { REJETE: EtapesTypesEtapesStatuts.decisionDeLadministration.REJETE }, mainStep: true },
+  FAIRE_PUBLICATION_AU_JORF: { db: EtapesTypesEtapesStatuts.publicationDeDecisionAuJORF, mainStep: true },
+  NOTIFIER_PREFET: { db: EtapesTypesEtapesStatuts.notificationAuPrefet, mainStep: true },
+  NOTIFIER_DEMANDEUR: { db: EtapesTypesEtapesStatuts.notificationAuDemandeur, mainStep: true },
+  PUBLIER_DECISIONS_RECUEIL_ACTES_ADMINISTRATIFS: { db: EtapesTypesEtapesStatuts.publicationDeDecisionAuRecueilDesActesAdministratifs, mainStep: true },
+  PUBLIER_DANS_UN_JOURNAL_LOCAL_OU_NATIONAL: { db: EtapesTypesEtapesStatuts.publicationDansUnJournalLocalOuNational, mainStep: true },
+  NOTIFIER_COLLECTIVITES_LOCALES: { db: EtapesTypesEtapesStatuts.notificationDesCollectivitesLocales, mainStep: true },
+  RENDRE_DECISION_ANNULATION_PAR_JUGE_ADMINISTRATIF: { db: { REJETE: EtapesTypesEtapesStatuts.decisionDuJugeAdministratif.REJETE }, mainStep: true },
+  RENDRE_DECISION_ABROGATION: { db: EtapesTypesEtapesStatuts.abrogationDeLaDecision, mainStep: true },
+  RENDRE_DECISION_RETRAIT: { db: EtapesTypesEtapesStatuts.retraitDeLaDecision, mainStep: true },
+  DESISTER_PAR_LE_DEMANDEUR: { db: EtapesTypesEtapesStatuts.desistementDuDemandeur, mainStep: false },
+  CLASSER_SANS_SUITE: { db: EtapesTypesEtapesStatuts.classementSansSuite, mainStep: false },
+  MODIFIER_DEMANDE: { db: EtapesTypesEtapesStatuts.modificationDeLaDemande, mainStep: false },
+  DEMANDER_INFORMATIONS: { db: EtapesTypesEtapesStatuts.demandeDinformations, mainStep: false },
+  RECEVOIR_INFORMATIONS: { db: EtapesTypesEtapesStatuts.receptionDinformation, mainStep: false },
+} as const
+
+// Related to https://github.com/Microsoft/TypeScript/issues/12870
+export const EVENTS = Object.keys(trad) as Array<Extract<keyof typeof trad, string>>
+
+const SUPERFICIE_MAX_POUR_EXONERATION_AVIS_MISE_EN_CONCURRENCE_AU_JORF = 50
+
+export class PrmOctMachine extends CaminoMachine<PrmOctContext, XStateEvent> {
+  constructor() {
+    super(prmOctMachine, trad)
+  }
+
+  toPotentialCaminoXStateEvent(event: XStateEvent['type'], date: CaminoDate): XStateEvent[] {
+    switch (event) {
+      case 'RENDRE_AVIS_DE_MISE_EN_CONCURRENCE_AU_JORF':
+      case 'OUVRIR_PARTICIPATION_DU_PUBLIC':
+      case 'FAIRE_SAISINE_DES_SERVICES':
+      case 'RENDRE_AVIS_CDM':
+      case 'RENDRE_RAPPORT_DREAL':
+        return [{ type: event, date }]
+      case 'FAIRE_DEMANDE':
+        return [
+          { type: event, paysId: PAYS_IDS['Département de la Guyane'], surface: SUPERFICIE_MAX_POUR_EXONERATION_AVIS_MISE_EN_CONCURRENCE_AU_JORF + 1 },
+          { type: event, paysId: PAYS_IDS['Département de la Guyane'], surface: SUPERFICIE_MAX_POUR_EXONERATION_AVIS_MISE_EN_CONCURRENCE_AU_JORF - 1 },
+          { type: event, paysId: PAYS_IDS['Wallis-et-Futuna'], surface: 0 },
+          { type: event, paysId: PAYS_IDS['République Française'], surface: 0 },
+        ]
+      default:
+        // related to https://github.com/microsoft/TypeScript/issues/46497  https://github.com/microsoft/TypeScript/issues/40803 :(
+        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+        // @ts-ignore
+        return [{ type: event }]
+    }
+  }
+
+  eventFrom(etape: Etape): XStateEvent {
+    const entries = Object.entries(trad).filter((entry): entry is [Event, { db: DBEtat; mainStep: boolean }] => EVENTS.includes(entry[0]))
+
+    const entry = entries.find(([_key, { db: dbEtat }]) => {
+      return Object.values(dbEtat).some(dbEtatSingle => dbEtatSingle.etapeTypeId === etape.etapeTypeId && dbEtatSingle.etapeStatutId === etape.etapeStatutId)
+    })
+
+    if (entry) {
+      const eventFromEntry = entry[0]
+      switch (eventFromEntry) {
+        case 'RENDRE_AVIS_DE_MISE_EN_CONCURRENCE_AU_JORF':
+        case 'OUVRIR_PARTICIPATION_DU_PUBLIC':
+        case 'FAIRE_SAISINE_DES_SERVICES':
+        case 'RENDRE_AVIS_CDM':
+        case 'RENDRE_RAPPORT_DREAL':
+          return { type: eventFromEntry, date: etape.date }
+        case 'FAIRE_DEMANDE':
+          if (!etape.paysId) {
+            console.error(`paysId is mandatory in etape ${JSON.stringify(etape)}`)
+
+            return { type: eventFromEntry, paysId: 'FR', surface: etape.surface ?? 0 }
+          }
+
+          if (etape.paysId === 'GF' && etape.surface === null && etape.surface === undefined) {
+            throw new Error(`la surface pour la demande est obligatoire quand la demande est en Guyane  ${JSON.stringify(etape)}`)
+          }
+
+          return { type: eventFromEntry, paysId: etape.paysId, surface: etape.surface ?? 0 }
+        default:
+          // related to https://github.com/microsoft/TypeScript/issues/46497  https://github.com/microsoft/TypeScript/issues/40803 :(
+          // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+          // @ts-ignore
+          return { type: eventFromEntry }
+      }
+    }
+    throw new Error(`no event from ${JSON.stringify(etape)}`)
+  }
+}
+
+interface PrmOctContext extends CaminoCommonContext {
+  dateAvisMiseEnConcurrentJorf: CaminoDate | null
+  dateSaisineDesServices: CaminoDate | null
+  paysId: PaysId | null
+  surface: number | null
+}
+
+const peutOuvrirParticipationDuPublic = (context: PrmOctContext, event: OuvrirParticipationDuPublic): boolean => {
+  return estExempteDeLaMiseEnConcurrence(context) || (context.dateAvisMiseEnConcurrentJorf !== null && daysBetween(dateAddMonths(context.dateAvisMiseEnConcurrentJorf, 1), event.date) >= 0)
+}
+
+const peutRendreRapportDREAL = (context: PrmOctContext, event: RendreRapportDREAL): boolean => {
+  return isMetropole(context.paysId) && !!context.dateSaisineDesServices && daysBetween(dateAddMonths(context.dateSaisineDesServices, 1), event.date) >= 0
+}
+
+const peutRendreAvisCDM = (context: PrmOctContext, event: RendreAvisCDM): boolean => {
+  return isOutreMer(context.paysId) && !!context.dateSaisineDesServices && daysBetween(dateAddMonths(context.dateSaisineDesServices, 1), event.date) >= 0
+}
+
+const estExempteDeLaMiseEnConcurrence = (context: PrmOctContext): boolean => {
+  if (isGuyane(context.paysId)) {
+    if (context.surface === null) {
+      throw new Error('la surface est obligatoire quand on est en Guyane')
+    }
+
+    return context.surface < SUPERFICIE_MAX_POUR_EXONERATION_AVIS_MISE_EN_CONCURRENCE_AU_JORF
+  }
+
+  return false
+}
+
+const prmOctMachine = createMachine<PrmOctContext, XStateEvent>({
+  predictableActionArguments: true,
+  id: 'oct',
+  initial: 'demandeAFaire',
+  context: {
+    dateAvisMiseEnConcurrentJorf: null,
+    dateSaisineDesServices: null,
+    visibilite: 'confidentielle',
+    demarcheStatut: DemarchesStatutsIds.EnConstruction,
+    paysId: null,
+    surface: null,
+  },
+  on: {
+    MODIFIER_DEMANDE: {
+      actions: () => ({}),
+      cond: context => context.demarcheStatut === DemarchesStatutsIds.EnInstruction || context.demarcheStatut === DemarchesStatutsIds.Depose,
+    },
+    DEMANDER_INFORMATIONS: {
+      actions: () => ({}),
+      cond: context => context.demarcheStatut === DemarchesStatutsIds.EnInstruction || context.demarcheStatut === DemarchesStatutsIds.Depose,
+    },
+    RECEVOIR_INFORMATIONS: {
+      actions: () => ({}),
+      cond: context => context.demarcheStatut === DemarchesStatutsIds.EnInstruction || context.demarcheStatut === DemarchesStatutsIds.Depose,
+    },
+    DESISTER_PAR_LE_DEMANDEUR: {
+      target: 'done',
+      cond: context => context.demarcheStatut === DemarchesStatutsIds.EnInstruction || context.demarcheStatut === DemarchesStatutsIds.Depose,
+      actions: assign<CaminoCommonContext, { type: 'DESISTER_PAR_LE_DEMANDEUR' }>({
+        demarcheStatut: DemarchesStatutsIds.Desiste,
+        visibilite: 'publique',
+      }),
+    },
+    CLASSER_SANS_SUITE: {
+      target: 'done',
+      cond: context => context.demarcheStatut === DemarchesStatutsIds.EnInstruction,
+      actions: assign<CaminoCommonContext, { type: 'CLASSER_SANS_SUITE' }>({
+        demarcheStatut: DemarchesStatutsIds.ClasseSansSuite,
+        visibilite: 'publique',
+      }),
+    },
+  },
+  states: {
+    demandeAFaire: {
+      on: {
+        FAIRE_DEMANDE: {
+          target: 'depotDeLaDemandeAFaire',
+          actions: assign<PrmOctContext, FaireDemande>({
+            paysId: (_context, event) => {
+              return event.paysId
+            },
+            surface: (_context, event) => {
+              return event.surface
+            },
+          }),
+        },
+      },
+    },
+    depotDeLaDemandeAFaire: {
+      on: {
+        DEPOSER_DEMANDE: {
+          target: 'saisineDuPrefetAFaire',
+          actions: assign<CaminoCommonContext, { type: 'DEPOSER_DEMANDE' }>({
+            demarcheStatut: DemarchesStatutsIds.Depose,
+          }),
+        },
+      },
+    },
+    saisineDuPrefetAFaire: {
+      on: {
+        FAIRE_SAISINE_PREFET: 'recevabiliteDeLaDemandeAFaire',
+      },
+    },
+    recevabiliteDeLaDemandeAFaire: {
+      on: {
+        DEMANDER_COMPLEMENTS_POUR_RECEVABILITE: 'complementsPourRecevabiliteAFaire',
+        FAIRE_RECEVABILITE_DEMANDE_FAVORABLE: {
+          target: 'avisDeMiseEnConcurrenceAuJORFAFaire',
+          actions: assign<CaminoCommonContext, { type: 'FAIRE_RECEVABILITE_DEMANDE_FAVORABLE' }>({
+            demarcheStatut: DemarchesStatutsIds.EnInstruction,
+            visibilite: 'publique',
+          }),
+        },
+        FAIRE_RECEVABILITE_DEMANDE_DEFAVORABLE: 'recevabiliteDeLaDemandeAFaire',
+      },
+    },
+    complementsPourRecevabiliteAFaire: {
+      on: {
+        RECEVOIR_COMPLEMENTS_POUR_RECEVABILITE: 'recevabiliteDeLaDemandeAFaire',
+        FAIRE_RECEVABILITE_DEMANDE_FAVORABLE: {
+          target: 'avisDeMiseEnConcurrenceAuJORFAFaire',
+          actions: assign<CaminoCommonContext, { type: 'FAIRE_RECEVABILITE_DEMANDE_FAVORABLE' }>({
+            demarcheStatut: DemarchesStatutsIds.EnInstruction,
+            visibilite: 'publique',
+          }),
+        },
+        FAIRE_RECEVABILITE_DEMANDE_DEFAVORABLE: 'complementsPourRecevabiliteAFaire',
+      },
+    },
+    avisDeMiseEnConcurrenceAuJORFAFaire: {
+      always: {
+        cond: estExempteDeLaMiseEnConcurrence,
+        target: 'saisinesEtMiseEnConcurrence',
+      },
+      on: {
+        RENDRE_AVIS_DE_MISE_EN_CONCURRENCE_AU_JORF: {
+          target: 'saisinesEtMiseEnConcurrence',
+          actions: assign<PrmOctContext, RendreAvisMiseEnConcurrentJORF>({
+            dateAvisMiseEnConcurrentJorf: (_context, event) => {
+              return event.date
+            },
+          }),
+        },
+      },
+    },
+    saisinesEtMiseEnConcurrence: {
+      type: 'parallel',
+      states: {
+        saisinesEtAvisAFaire: {
+          initial: 'saisinesMachine',
+          states: {
+            saisinesMachine: {
+              type: 'parallel',
+              states: {
+                saisineDesCollectivitesLocalesMachine: {
+                  initial: 'saisineDesCollectivitesLocalesAFaire',
+                  states: {
+                    saisineDesCollectivitesLocalesAFaire: {
+                      always: {
+                        cond: (context: PrmOctContext) => !isGuyane(context.paysId),
+                        target: 'done',
+                      },
+                      on: {
+                        FAIRE_SAISINE_DES_COLLECTIVITES_LOCALES: 'avisDuMaireARendre',
+                      },
+                    },
+                    avisDuMaireARendre: {
+                      on: {
+                        RENDRE_AVIS_DU_MAIRE: 'done',
+                      },
+                    },
+                    done: { type: 'final' },
+                  },
+                },
+                saisineDesServicesMachine: {
+                  initial: 'saisineDesServicesAFaire',
+                  states: {
+                    saisineDesServicesAFaire: {
+                      on: {
+                        FAIRE_SAISINE_DES_SERVICES: {
+                          target: 'avisDesServicesARendre',
+                          actions: assign<PrmOctContext, FaireSaisineDesServices>({
+                            dateSaisineDesServices: (_context, event) => event.date,
+                          }),
+                        },
+                      },
+                    },
+                    avisDesServicesARendre: {
+                      type: 'parallel',
+
+                      states: {
+                        rendreAvisDrealAFaire: {
+                          on: {
+                            RENDRE_AVIS_CDM: { target: '#rapportDREALAFaire', cond: peutRendreAvisCDM },
+                            RENDRE_RAPPORT_DREAL: { target: '#avisPrefetARendre', cond: peutRendreRapportDREAL },
+                          },
+                        },
+                        avisServiceAdministratifCivilLocal: {
+                          initial: 'avisServiceAdministratifCivilLocalARendre',
+                          states: {
+                            avisServiceAdministratifCivilLocalARendre: {
+                              on: { RENDRE_AVIS_SERVICE_ADMINISTRATIF_CIVIL_LOCAL: 'avisServiceAdministratifCivilLocalRendu' },
+                            },
+                            avisServiceAdministratifCivilLocalRendu: { type: 'final' },
+                          },
+                        },
+                        avisAutoriteMilitaire: {
+                          initial: 'avisAutoriteMilitaireARendre',
+                          states: {
+                            avisAutoriteMilitaireARendre: {
+                              on: { RENDRE_AVIS_AUTORITE_MILITAIRE: 'avisAutoriteMilitaireRendu' },
+                            },
+                            avisAutoriteMilitaireRendu: { type: 'final' },
+                          },
+                        },
+                        avisDesDDT: {
+                          initial: 'avisDesDDTARendre',
+                          states: {
+                            avisDesDDTARendre: {
+                              on: {
+                                RENDRE_AVIS_DES_DTT: { target: 'avisDesDDTRendu', cond: (context: PrmOctContext) => !isGuyane(context.paysId) },
+                                RENDRE_AVIS_POLICE_EAU: { target: 'avisDesDDTRendu', cond: (context: PrmOctContext) => isGuyane(context.paysId) },
+                              },
+                            },
+                            avisDesDDTRendu: { type: 'final' },
+                          },
+                        },
+                        avisParcNaturelRegional: {
+                          initial: 'avisParcNaturelRegionalARendre',
+                          states: {
+                            avisParcNaturelRegionalARendre: {
+                              on: { RENDRE_AVIS_PARC_NATUREL_REGIONAL: 'avisParcNaturelRegionalRendu' },
+                            },
+                            avisParcNaturelRegionalRendu: { type: 'final' },
+                          },
+                        },
+                        avisParcNational: {
+                          initial: 'avisParcNationalARendre',
+                          states: {
+                            avisParcNationalARendre: {
+                              on: { RENDRE_AVIS_PARC_NATIONAL: 'avisParcNationalRendu' },
+                            },
+                            avisParcNationalRendu: { type: 'final' },
+                          },
+                        },
+                        avisAgenceRegionaleSanteARS: {
+                          initial: 'avisAgenceRegionaleSanteARSARendre',
+                          states: {
+                            avisAgenceRegionaleSanteARSARendre: {
+                              on: { RENDRE_AVIS_AGENCE_REGIONALE_SANTE_ARS: 'avisAgenceRegionaleSanteARSRendu' },
+                            },
+                            avisAgenceRegionaleSanteARSRendu: { type: 'final' },
+                          },
+                        },
+                        avisONF: {
+                          initial: 'avisONFARendre',
+                          states: {
+                            avisONFARendre: {
+                              on: { RENDRE_AVIS_ONF: 'avisONFRendu' },
+                            },
+                            avisONFRendu: { type: 'final' },
+                          },
+                        },
+                        avisInstitutNationalOrigineEtQualiteINAO: {
+                          initial: 'avisInstitutNationalOrigineEtQualiteINAOARendre',
+                          states: {
+                            avisInstitutNationalOrigineEtQualiteINAOARendre: {
+                              on: { RENDRE_AVIS_INSTITUT_NATIONAL_ORIGINE_ET_QUALITE_INAO: 'avisInstitutNationalOrigineEtQualiteINAORendu' },
+                            },
+                            avisInstitutNationalOrigineEtQualiteINAORendu: { type: 'final' },
+                          },
+                        },
+                        avisDirectionRegionaleAffairesCulturelles: {
+                          initial: 'avisDirectionRegionaleAffairesCulturellesARendre',
+                          states: {
+                            avisDirectionRegionaleAffairesCulturellesARendre: {
+                              on: { RENDRE_AVIS_DIRECTION_REGIONALE_AFFAIRES_CULTURELLES: 'avisDirectionRegionaleAffairesCulturellesRendu' },
+                            },
+                            avisDirectionRegionaleAffairesCulturellesRendu: { type: 'final' },
+                          },
+                        },
+                        avisDirectionRegionaleFinancesPubliques: {
+                          initial: 'avisDirectionRegionaleFinancesPubliquesARendre',
+                          states: {
+                            avisDirectionRegionaleFinancesPubliquesARendre: {
+                              on: { RENDRE_AVIS_DIRECTION_REGIONALE_FINANCES_PUBLIQUES: 'avisDirectionRegionaleFinancesPubliquesRendu' },
+                            },
+                            avisDirectionRegionaleFinancesPubliquesRendu: { type: 'final' },
+                          },
+                        },
+                      },
+                      onDone: 'avisDesServicesRendus',
+                    },
+                    avisDesServicesRendus: { type: 'final' },
+                  },
+                },
+              },
+              onDone: 'avisCommissionDepartementaleDesMinesEnGuyaneEtOutreMerOuRapportDeLaDREALARendre',
+            },
+            avisCommissionDepartementaleDesMinesEnGuyaneEtOutreMerOuRapportDeLaDREALARendre: {
+              always: [
+                {
+                  target: 'avisCommissionDepartementaleDesMinesEnGuyaneEtOutreMerARendre',
+                  cond: (context: PrmOctContext) => isOutreMer(context.paysId),
+                },
+                {
+                  target: 'rapportDREALAFaire',
+                  cond: (context: PrmOctContext) => isMetropole(context.paysId),
+                },
+              ],
+            },
+            avisCommissionDepartementaleDesMinesEnGuyaneEtOutreMerARendre: {
+              on: {
+                RENDRE_AVIS_CDM: 'rapportDREALAFaire',
+              },
+            },
+            rapportDREALAFaire: {
+              id: 'rapportDREALAFaire',
+              on: {
+                RENDRE_RAPPORT_DREAL: 'avisPrefetARendre',
+              },
+            },
+            avisPrefetARendre: {
+              id: 'avisPrefetARendre',
+              on: {
+                RENDRE_AVIS_PREFET: 'done',
+              },
+            },
+            done: { type: 'final' },
+          },
+        },
+        miseEnConcurrenceMachine: {
+          initial: 'participationDuPublicPasEncorePossible',
+          states: {
+            participationDuPublicPasEncorePossible: {
+              on: {
+                DEPOSER_DEMANDE_CONCURRENTE: { target: 'participationDuPublicPasEncorePossible', cond: context => !estExempteDeLaMiseEnConcurrence(context) },
+                OUVRIR_PARTICIPATION_DU_PUBLIC: { target: 'clotureParticipationDuPublicAFaire', cond: peutOuvrirParticipationDuPublic },
+              },
+            },
+            clotureParticipationDuPublicAFaire: {
+              on: {
+                CLOTURER_PARTICIPATION_DU_PUBLIC: 'done',
+              },
+            },
+            done: { type: 'final' },
+          },
+        },
+      },
+      onDone: 'rapportAdministrationCentraleAFaire',
+    },
+    rapportAdministrationCentraleAFaire: {
+      on: {
+        FAIRE_RAPPORT_ADMINISTRATION_CENTRALE: 'saisineDuConseilGeneralChargeDesMinesAFaire',
+      },
+    },
+    saisineDuConseilGeneralChargeDesMinesAFaire: {
+      on: {
+        FAIRE_SAISINE_CONSEIL_GENERAL_CHARGE_DES_MINES: 'rapportDuConseilGeneralDesMinesAFaire',
+      },
+    },
+    rapportDuConseilGeneralDesMinesAFaire: {
+      on: {
+        FAIRE_RAPPORT_CONSEIL_GENERAL_CHARGE_DES_MINES: 'avisDuConseilGeneralDesMinesARendre',
+      },
+    },
+    avisDuConseilGeneralDesMinesARendre: {
+      on: {
+        RENDRE_AVIS_CONSEIL_GENERAL_CHARGE_DES_MINES: 'saisineDeLAutoriteSignataireAFaire',
+      },
+    },
+    saisineDeLAutoriteSignataireAFaire: {
+      on: {
+        FAIRE_SAISINE_AUTORITE_SIGNATAIRE: 'decisionDeLAdministrationARendre',
+      },
+    },
+    decisionDeLAdministrationARendre: {
+      on: {
+        RENDRE_DECISION_ADMINISTRATION_ACCEPTE: {
+          target: 'publicationAuJORFAFaire',
+          actions: assign<PrmOctContext, { type: 'RENDRE_DECISION_ADMINISTRATION_ACCEPTE' }>({
+            demarcheStatut: DemarchesStatutsIds.Accepte,
+          }),
+        },
+        RENDRE_DECISION_ADMINISTRATION_REJETE: {
+          target: 'decisionsEtNotificationsRejetAFaire',
+          actions: assign<PrmOctContext, { type: 'RENDRE_DECISION_ADMINISTRATION_REJETE' }>({
+            demarcheStatut: DemarchesStatutsIds.Rejete,
+          }),
+        },
+      },
+    },
+    publicationAuJORFAFaire: {
+      on: {
+        FAIRE_PUBLICATION_AU_JORF: 'notificationsAFaire',
+      },
+    },
+    notificationsAFaire: {
+      type: 'parallel',
+      states: {
+        notificationDuPrefetMachine: {
+          initial: 'notificationDuPrefetAFaire',
+          states: {
+            notificationDuPrefetAFaire: {
+              on: { NOTIFIER_PREFET: 'notificationDuPrefetFaite' },
+            },
+            notificationDuPrefetFaite: { type: 'final' },
+          },
+        },
+        notificationDuDemandeurMachine: {
+          initial: 'notificationDuDemandeurAFaire',
+          states: {
+            notificationDuDemandeurAFaire: {
+              on: { NOTIFIER_DEMANDEUR: 'notificationDuDemandeurFaite' },
+            },
+            notificationDuDemandeurFaite: { type: 'final' },
+          },
+        },
+        publicationDecisionsRecueilActesAdministratifsMachine: {
+          initial: 'publicationDecisionsRecueilActesAdministratifsAFaire',
+          states: {
+            publicationDecisionsRecueilActesAdministratifsAFaire: {
+              on: {
+                PUBLIER_DECISIONS_RECUEIL_ACTES_ADMINISTRATIFS: 'publicationDecisionsRecueilActesAdministratifsFaite',
+              },
+            },
+            publicationDecisionsRecueilActesAdministratifsFaite: {
+              type: 'final',
+            },
+          },
+        },
+        publicationDansUnJournalLocalOuNationalMachine: {
+          initial: 'publicationDansUnJournalLocalOuNationalAFaire',
+          states: {
+            publicationDansUnJournalLocalOuNationalAFaire: {
+              on: {
+                PUBLIER_DANS_UN_JOURNAL_LOCAL_OU_NATIONAL: 'publicationDansUnJournalLocalOuNationalFaite',
+              },
+            },
+            publicationDansUnJournalLocalOuNationalFaite: { type: 'final' },
+          },
+        },
+        notificationDesCollectivitesLocalesMachine: {
+          initial: 'notificationDesCollectivitesLocalesAFaire',
+          states: {
+            notificationDesCollectivitesLocalesAFaire: {
+              on: {
+                NOTIFIER_COLLECTIVITES_LOCALES: 'notificationDesCollectivitesLocalesFaite',
+              },
+            },
+            notificationDesCollectivitesLocalesFaite: { type: 'final' },
+          },
+        },
+      },
+      onDone: 'done',
+    },
+    decisionsEtNotificationsRejetAFaire: {
+      type: 'parallel',
+      states: {
+        notificationsMachine: {
+          initial: 'notificationDuPrefetAFaire',
+          states: {
+            notificationDuPrefetAFaire: {
+              on: { NOTIFIER_PREFET: 'notificationDuDemandeurAFaire' },
+            },
+            notificationDuDemandeurAFaire: {
+              on: { NOTIFIER_DEMANDEUR: 'notificationDuDemandeurFaite' },
+            },
+            notificationDuDemandeurFaite: { type: 'final' },
+          },
+        },
+        decisionsMachine: {
+          initial: 'decisionARendre',
+          states: {
+            decisionARendre: {
+              on: {
+                RENDRE_DECISION_ANNULATION_PAR_JUGE_ADMINISTRATIF: 'done',
+                RENDRE_DECISION_ABROGATION: 'publicationAuJORFAFaire',
+                RENDRE_DECISION_RETRAIT: 'publicationAuJORFAFaire',
+              },
+            },
+            publicationAuJORFAFaire: {
+              on: {
+                FAIRE_PUBLICATION_AU_JORF: 'done',
+              },
+            },
+            done: { type: 'final' },
+          },
+        },
+      },
+      onDone: 'done',
+    },
+    done: { type: 'final' },
+  },
+})
diff --git a/packages/api/src/business/rules-demarches/prm/oct.test.ts b/packages/api/src/business/rules-demarches/prm/oct.test.ts
deleted file mode 100644
index 2c1384b62..000000000
--- a/packages/api/src/business/rules-demarches/prm/oct.test.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import { toCaminoDate } from 'camino-common/src/date.js'
-import { demarcheEtatsValidate } from '../_utils.test.js'
-import { describe, expect, test } from 'vitest'
-describe('vérifie l’arbre d’octroi d’une PRM', () => {
-  const octEtatsValidate = demarcheEtatsValidate('oct', 'prm', toCaminoDate('2020-01-01'))
-
-  test('ne peut pas créer une "rpu" après une "dex" rejetée', () => {
-    expect(
-      octEtatsValidate([
-        { typeId: 'mfr', date: toCaminoDate('2020-01-01') },
-        { typeId: 'mdp', date: toCaminoDate('2020-01-02') },
-        { typeId: 'spp', date: toCaminoDate('2020-01-03') },
-        { typeId: 'mcr', statutId: 'fav', date: toCaminoDate('2020-01-04') },
-        { typeId: 'anf', date: toCaminoDate('2020-01-05') },
-        { typeId: 'mec', date: toCaminoDate('2020-01-06') },
-        { typeId: 'ppu', date: toCaminoDate('2020-01-07') },
-        { typeId: 'ppc', date: toCaminoDate('2020-01-08') },
-        { typeId: 'scl', date: toCaminoDate('2020-01-07') },
-        { typeId: 'ssr', date: toCaminoDate('2020-01-07') },
-        { typeId: 'spo', date: toCaminoDate('2020-01-08') },
-        { typeId: 'apo', date: toCaminoDate('2020-01-09') },
-        { typeId: 'apd', date: toCaminoDate('2020-01-10') },
-        { typeId: 'app', date: toCaminoDate('2020-01-11') },
-        { typeId: 'scg', date: toCaminoDate('2020-01-12') },
-        { typeId: 'rcg', date: toCaminoDate('2020-01-13') },
-        { typeId: 'acg', date: toCaminoDate('2020-01-14') },
-        { typeId: 'sas', date: toCaminoDate('2020-01-15') },
-        { typeId: 'dex', statutId: 'rej', date: toCaminoDate('2020-01-16') },
-        { typeId: 'npp', date: toCaminoDate('2020-01-17') },
-        { typeId: 'mno', date: toCaminoDate('2020-01-18') },
-        { typeId: 'rpu', date: toCaminoDate('2020-01-19') },
-      ])
-    ).toMatchInlineSnapshot(`
-      [
-        "l’étape \\"rpu\\" n’est pas possible après \\"ssr\\", \\"scl\\", \\"spo\\", \\"apo\\", \\"npp\\", \\"mno\\"",
-      ]
-    `)
-  })
-
-  test('peut créer une "rpu" après une "dex" acceptée', () => {
-    expect(
-      octEtatsValidate([
-        { typeId: 'mfr', date: toCaminoDate('2020-01-01') },
-        { typeId: 'mdp', date: toCaminoDate('2020-01-02') },
-        { typeId: 'spp', date: toCaminoDate('2020-01-03') },
-        { typeId: 'mcr', statutId: 'fav', date: toCaminoDate('2020-01-04') },
-        { typeId: 'anf', date: toCaminoDate('2020-01-05') },
-        { typeId: 'mec', date: toCaminoDate('2020-01-06') },
-        { typeId: 'ppu', date: toCaminoDate('2020-01-07') },
-        { typeId: 'ppc', date: toCaminoDate('2020-01-08') },
-        { typeId: 'scl', date: toCaminoDate('2020-01-07') },
-        { typeId: 'ssr', date: toCaminoDate('2020-01-07') },
-        { typeId: 'spo', date: toCaminoDate('2020-01-08') },
-        { typeId: 'apo', date: toCaminoDate('2020-01-09') },
-        { typeId: 'apd', date: toCaminoDate('2020-01-10') },
-        { typeId: 'app', date: toCaminoDate('2020-01-11') },
-        { typeId: 'scg', date: toCaminoDate('2020-01-12') },
-        { typeId: 'rcg', date: toCaminoDate('2020-01-13') },
-        { typeId: 'acg', date: toCaminoDate('2020-01-14') },
-        { typeId: 'sas', date: toCaminoDate('2020-01-15') },
-        { typeId: 'dex', statutId: 'acc', date: toCaminoDate('2020-01-16') },
-        { typeId: 'dpu', statutId: 'acc', date: toCaminoDate('2020-01-17') },
-        { typeId: 'npp', date: toCaminoDate('2020-01-18') },
-        { typeId: 'mno', date: toCaminoDate('2020-01-19') },
-        { typeId: 'rpu', date: toCaminoDate('2020-01-19') },
-      ])
-    ).toHaveLength(0)
-  })
-
-  test('peut créer une participation du public (ppu) directement après une recevabilité de la demande fav (mcr)', () => {
-    expect(
-      octEtatsValidate([
-        { typeId: 'mfr', date: toCaminoDate('2020-01-01') },
-        { typeId: 'mdp', date: toCaminoDate('2020-01-02') },
-        { typeId: 'spp', date: toCaminoDate('2020-01-03') },
-        { typeId: 'mcr', statutId: 'fav', date: toCaminoDate('2020-01-04') },
-        { typeId: 'ppu', date: toCaminoDate('2020-01-07') },
-      ])
-    ).toHaveLength(0)
-  })
-
-  test('la saisine de la commission départementale des mines (spo) est optionnelle', () => {
-    expect(
-      octEtatsValidate([
-        { typeId: 'mfr', date: toCaminoDate('2020-01-01') },
-        { typeId: 'mdp', date: toCaminoDate('2020-01-02') },
-        { typeId: 'spp', date: toCaminoDate('2020-01-03') },
-        { typeId: 'mcr', statutId: 'fav', date: toCaminoDate('2020-01-04') },
-        { typeId: 'anf', date: toCaminoDate('2020-01-05') },
-        { typeId: 'mec', date: toCaminoDate('2020-01-06') },
-        { typeId: 'ppu', date: toCaminoDate('2020-01-07') },
-        { typeId: 'ppc', date: toCaminoDate('2020-01-08') },
-        { typeId: 'scl', date: toCaminoDate('2020-01-07') },
-        { typeId: 'ssr', date: toCaminoDate('2020-01-07') },
-        { typeId: 'apd', date: toCaminoDate('2020-01-09') },
-      ])
-    ).toHaveLength(0)
-  })
-})
diff --git a/packages/api/src/business/rules-demarches/prm/oct.ts b/packages/api/src/business/rules-demarches/prm/oct.ts
deleted file mode 100644
index 88ad2bfb0..000000000
--- a/packages/api/src/business/rules-demarches/prm/oct.ts
+++ /dev/null
@@ -1,201 +0,0 @@
-// https://cacoo.com/diagrams/mdAnl7m9V2ViBlxA/C4063
-
-import { IDemarcheDefinitionRestrictions } from '../definitions.js'
-
-const etatsDefinitionPrmOct: IDemarcheDefinitionRestrictions = {
-  mfr: {
-    justeApres: [[]],
-  },
-  mdp: {
-    justeApres: [[{ etapeTypeId: 'mfr' }]],
-  },
-  nis: {
-    apres: [[{ etapeTypeId: 'mdp' }]],
-    justeApres: [],
-    final: false,
-  },
-  mod: {
-    justeApres: [[]],
-    apres: [[{ etapeTypeId: 'mdp' }]],
-    avant: [[{ etapeTypeId: 'dex' }]],
-    final: false,
-  },
-  mif: {
-    justeApres: [[]],
-    apres: [[{ etapeTypeId: 'mdp' }]],
-    avant: [[{ etapeTypeId: 'dex' }]],
-    final: false,
-  },
-  rif: {
-    justeApres: [[{ etapeTypeId: 'mif' }]],
-    avant: [[{ etapeTypeId: 'sas' }]],
-    final: false,
-  },
-  spp: {
-    justeApres: [[{ etapeTypeId: 'mdp' }]],
-  },
-  mcr: {
-    separation: ['scg'],
-    justeApres: [[{ etapeTypeId: 'spp' }], [{ etapeTypeId: 'rco' }]],
-  },
-  mco: {
-    justeApres: [[{ etapeTypeId: 'mcr', statutId: 'def' }], [{ etapeTypeId: 'rco' }]],
-  },
-  rco: { justeApres: [[{ etapeTypeId: 'mco' }]] },
-  anf: {
-    justeApres: [[{ etapeTypeId: 'mcr', statutId: 'fav' }]],
-  },
-  mec: {
-    justeApres: [[{ etapeTypeId: 'anf' }]],
-  },
-  scl: {
-    separation: ['apo', 'spo', 'apd'],
-    avant: [[{ etapeTypeId: 'scl' }]],
-    justeApres: [[{ etapeTypeId: 'mcr', statutId: 'fav' }], [{ etapeTypeId: 'anf' }], [{ etapeTypeId: 'mec' }]],
-  },
-  ama: {
-    justeApres: [[{ etapeTypeId: 'scl' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-  },
-  aep: {
-    justeApres: [[{ etapeTypeId: 'scl' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-  },
-  acl: {
-    justeApres: [[{ etapeTypeId: 'scl' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-  },
-  ssr: {
-    separation: ['apo', 'spo', 'apd'],
-    avant: [[{ etapeTypeId: 'ssr' }]],
-    justeApres: [[{ etapeTypeId: 'mcr', statutId: 'fav' }], [{ etapeTypeId: 'anf' }], [{ etapeTypeId: 'mec' }]],
-  },
-  apl: {
-    justeApres: [[{ etapeTypeId: 'ssr' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-  },
-  apm: {
-    justeApres: [[{ etapeTypeId: 'ssr' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-  },
-  pnr: {
-    justeApres: [[{ etapeTypeId: 'ssr' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-  },
-  apn: {
-    justeApres: [[{ etapeTypeId: 'ssr' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-  },
-  ars: {
-    justeApres: [[{ etapeTypeId: 'ssr' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }]],
-  },
-  afp: {
-    justeApres: [[{ etapeTypeId: 'ssr' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }]],
-  },
-  aac: {
-    justeApres: [[{ etapeTypeId: 'ssr' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }]],
-  },
-  aof: {
-    justeApres: [[{ etapeTypeId: 'ssr' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-  },
-  aop: {
-    justeApres: [[{ etapeTypeId: 'ssr' }]],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-  },
-  spo: {
-    justeApres: [],
-    avant: [[{ etapeTypeId: 'apo' }], [{ etapeTypeId: 'spo' }], [{ etapeTypeId: 'apd' }]],
-    apres: [[{ etapeTypeId: 'scl' }, { etapeTypeId: 'ssr' }]],
-  },
-  apo: {
-    justeApres: [],
-    avant: [[{ etapeTypeId: 'apo' }]],
-    apres: [[{ etapeTypeId: 'scl' }, { etapeTypeId: 'ssr' }]],
-  },
-  apd: {
-    justeApres: [],
-    avant: [[{ etapeTypeId: 'apd' }]],
-    apres: [[{ etapeTypeId: 'scl' }, { etapeTypeId: 'ssr' }]],
-  },
-  app: { justeApres: [[{ etapeTypeId: 'apd' }]] },
-  ppu: {
-    justeApres: [[{ etapeTypeId: 'mcr', statutId: 'fav' }], [{ etapeTypeId: 'anf' }], [{ etapeTypeId: 'mec' }]],
-    avant: [[{ etapeTypeId: 'ppu' }]],
-  },
-  ppc: { justeApres: [[{ etapeTypeId: 'ppu' }]] },
-  scg: {
-    justeApres: [[{ etapeTypeId: 'app' }, { etapeTypeId: 'ppc' }]],
-  },
-  rcg: {
-    justeApres: [[{ etapeTypeId: 'scg' }]],
-  },
-  acg: { justeApres: [[{ etapeTypeId: 'rcg' }]] },
-  sas: { justeApres: [[{ etapeTypeId: 'acg' }]] },
-  dex: { justeApres: [[{ etapeTypeId: 'sas' }]] },
-  dpu: {
-    justeApres: [[{ etapeTypeId: 'dex', statutId: 'acc' }], [{ etapeTypeId: 'abd' }], [{ etapeTypeId: 'rtd' }]],
-  },
-  npp: {
-    justeApres: [[{ etapeTypeId: 'dex', statutId: 'rej' }], [{ etapeTypeId: 'dpu', statutId: 'acc' }]],
-    avant: [[{ etapeTypeId: 'abd' }], [{ etapeTypeId: 'rtd' }]],
-  },
-  mno: {
-    apres: [[{ etapeTypeId: 'npp' }]],
-    avant: [[{ etapeTypeId: 'mno' }]],
-    justeApres: [],
-  },
-  rpu: {
-    apres: [[{ etapeTypeId: 'dex', statutId: 'acc' }, { etapeTypeId: 'npp' }]],
-    avant: [[{ etapeTypeId: 'rpu' }]],
-    justeApres: [],
-  },
-  ncl: {
-    apres: [[{ etapeTypeId: 'dex', statutId: 'acc' }, { etapeTypeId: 'npp' }]],
-    avant: [[{ etapeTypeId: 'ncl' }]],
-    justeApres: [],
-  },
-  pqr: {
-    apres: [[{ etapeTypeId: 'dex', statutId: 'acc' }, { etapeTypeId: 'npp' }]],
-    avant: [[{ etapeTypeId: 'pqr' }]],
-    justeApres: [],
-  },
-  dim: {
-    justeApres: [[{ etapeTypeId: 'mdp' }]],
-    avant: [[{ etapeTypeId: 'dex' }]],
-  },
-  and: {
-    justeApres: [[{ etapeTypeId: 'dim' }], [{ etapeTypeId: 'dex' }]],
-    final: true,
-  },
-  abd: {
-    justeApres: [[{ etapeTypeId: 'dex' }]],
-    avant: [[{ etapeTypeId: 'and' }], [{ etapeTypeId: 'rtd' }]],
-  },
-  rtd: {
-    justeApres: [[{ etapeTypeId: 'dex' }]],
-    avant: [[{ etapeTypeId: 'and' }], [{ etapeTypeId: 'abd' }]],
-  },
-  des: {
-    justeApres: [[]],
-    avant: [[{ etapeTypeId: 'dex' }], [{ etapeTypeId: 'css' }], [{ etapeTypeId: 'dim' }]],
-    final: true,
-    apres: [[{ etapeTypeId: 'mdp' }]],
-  },
-  css: {
-    justeApres: [[]],
-    avant: [[{ etapeTypeId: 'dex' }], [{ etapeTypeId: 'des' }], [{ etapeTypeId: 'dim' }]],
-    final: true,
-    apres: [[{ etapeTypeId: 'mdp' }]],
-  },
-  edm: {
-    justeApres: [[]],
-    avant: [[{ etapeTypeId: 'mfr' }]],
-    apres: [[{ etapeTypeId: 'mfr' }]],
-  },
-}
-
-export { etatsDefinitionPrmOct }
diff --git a/packages/api/src/business/rules/__mocks__/titre-date-demande-find-demarches.ts b/packages/api/src/business/rules/__mocks__/titre-date-demande-find-demarches.ts
index 37f8dee28..0430a0b05 100644
--- a/packages/api/src/business/rules/__mocks__/titre-date-demande-find-demarches.ts
+++ b/packages/api/src/business/rules/__mocks__/titre-date-demande-find-demarches.ts
@@ -1,5 +1,5 @@
 import { ITitreDemarche } from '../../../types.js'
-import { newDemarcheId } from '../../../database/models/_format/id-create.js'
+import { newDemarcheId, newTitreId } from '../../../database/models/_format/id-create.js'
 
 const titreDemarcheOctEtapeMen = [
   {
@@ -24,7 +24,7 @@ const titreDemarcheOctEtapeMen = [
 const titreDemarcheOctSansEtapes = [
   {
     id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-    titreId: 'h-cx-courdemanges-1988',
+    titreId: newTitreId('h-cx-courdemanges-1988'),
     typeId: 'oct',
     statutId: 'acc',
     ordre: 1,
diff --git a/packages/api/src/business/rules/__mocks__/titre-demarche-date-fin-duree-find-demarches.ts b/packages/api/src/business/rules/__mocks__/titre-demarche-date-fin-duree-find-demarches.ts
index f7e35b4b8..5d28a1fa6 100644
--- a/packages/api/src/business/rules/__mocks__/titre-demarche-date-fin-duree-find-demarches.ts
+++ b/packages/api/src/business/rules/__mocks__/titre-demarche-date-fin-duree-find-demarches.ts
@@ -1,5 +1,5 @@
 import { ITitreDemarche } from '../../../types.js'
-import { newDemarcheId } from '../../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../../database/models/_format/id-create.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 
 const titreDemarchesOctDateFin = [
@@ -102,13 +102,13 @@ const titreDemarchesOctDateDebut = [
 const titreDemarchesOctDureeZero = [
   {
     id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-    titreId: 'h-cx-courdemanges-1988',
+    titreId: newTitreId('h-cx-courdemanges-1988'),
     typeId: 'oct',
     statutId: 'acc',
     ordre: 1,
     etapes: [
       {
-        id: 'h-cx-courdemanges-1988-oct01-dex01',
+        id: newEtapeId('h-cx-courdemanges-1988-oct01-dex01'),
         titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
         typeId: 'dex',
         statutId: 'acc',
@@ -124,13 +124,13 @@ const titreDemarchesOctDureeZero = [
 const titreDemarchesOctIhiDureeZero = [
   {
     id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
-    titreId: 'h-cx-courdemanges-1988',
+    titreId: newTitreId('h-cx-courdemanges-1988'),
     typeId: 'oct',
     statutId: 'acc',
     ordre: 1,
     etapes: [
       {
-        id: 'h-cx-courdemanges-1988-oct01-ihi01',
+        id: newEtapeId('h-cx-courdemanges-1988-oct01-ihi01'),
         titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
         typeId: 'ihi',
         statutId: 'acc',
@@ -566,13 +566,13 @@ const titreDemarchesRenPointsVideDex = [
 const titreDemarchesRenPointsVideNiDpuNiDex = [
   {
     id: newDemarcheId('h-cx-courdemanges-1988-ren01'),
-    titreId: 'h-cx-courdemanges-1988',
+    titreId: newTitreId('h-cx-courdemanges-1988'),
     typeId: 'ren',
     statutId: 'acc',
     ordre: 2,
     etapes: [
       {
-        id: 'h-cx-courdemanges-1988-ren01-mfr01',
+        id: newEtapeId('h-cx-courdemanges-1988-ren01-mfr01'),
         titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-ren01'),
         typeId: 'mfr',
         statutId: 'acc',
diff --git a/packages/api/src/business/rules/titre-activites-build.test.ts b/packages/api/src/business/rules/titre-activites-build.test.ts
index 6ce682c0f..9039dd2ee 100644
--- a/packages/api/src/business/rules/titre-activites-build.test.ts
+++ b/packages/api/src/business/rules/titre-activites-build.test.ts
@@ -4,7 +4,7 @@ import { titreActivitesBuild } from './titre-activites-build.js'
 
 import { describe, expect, test } from 'vitest'
 import { toCaminoDate } from 'camino-common/src/date.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create.js'
 import { ACTIVITES_TYPES_IDS } from 'camino-common/src/static/activitesTypes.js'
 describe("construction des activités d'un titre", () => {
   const aujourdhui = toCaminoDate('2021-01-01')
@@ -51,19 +51,22 @@ describe("construction des activités d'un titre", () => {
     const titreActivitesA = titreActivitesBuild(ACTIVITES_TYPES_IDS["rapport d'exploitation (permis et concessions M)"], [2018], aujourdhui, 'titre-id', 'pxm', [
       {
         id: newDemarcheId('demarche-id'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         statutId: 'acc',
         typeId: 'oct',
         demarcheDateDebut: toCaminoDate('2018-01-01'),
         demarcheDateFin: toCaminoDate('2018-12-31'),
         etapes: [
           {
-            id: 'etape-id',
+            id: newEtapeId('etape-id'),
             titreDemarcheId: newDemarcheId('demarche-id'),
             date: toCaminoDate('2018-01-01'),
             typeId: 'dpu',
             statutId: 'fai',
             substances: ['auru', 'nacl'],
+            surface: null,
+            ordre: 1,
+            communes: null,
           },
         ],
       },
diff --git a/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.test.ts b/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.test.ts
index 59491a137..4fbe6ff3d 100644
--- a/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.test.ts
+++ b/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.test.ts
@@ -1,14 +1,14 @@
 import { ITitreEtape } from '../../types.js'
 import { titreDemarcheAnnulationDateFinFind } from './titre-demarche-annulation-date-fin-find.js'
 import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId } from '../../database/models/_format/id-create.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { describe, expect, test } from 'vitest'
 describe("date de fin d'une démarche d'annulation", () => {
   test.each<EtapeTypeId>(['dex', 'dux', 'dim'])("retourne la date d'une démarche d'annulation si elle n'a pas de date de fin pour une %p", typeId => {
     const titreDemarcheAnnulationEtapes: ITitreEtape[] = [
       {
-        id: 'h-cx-courdemanges-1988-ret01-dex01',
+        id: newEtapeId('h-cx-courdemanges-1988-ret01-dex01'),
         titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-ret01'),
         typeId,
         statutId: 'acc',
@@ -22,7 +22,7 @@ describe("date de fin d'une démarche d'annulation", () => {
   test.each<EtapeTypeId>(['dex', 'dux', 'dim'])("retourne la date de fin d'une démarche d'annulation si elle existe pour une %p", typeId => {
     const titreDemarcheAnnulationEtapesDateFin: ITitreEtape[] = [
       {
-        id: 'h-cx-courdemanges-1988-ret01-dex01',
+        id: newEtapeId('h-cx-courdemanges-1988-ret01-dex01'),
         titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-ret01'),
         typeId,
         statutId: 'acc',
@@ -38,7 +38,7 @@ describe("date de fin d'une démarche d'annulation", () => {
     // TODO 2022-05-10, c'est étrange, on va à l'encontre de typescript ici. Soit le typage est faux, soit le test ne sert à rien
     const titreDemarcheAnnulationEtapesSansDate: ITitreEtape[] = [
       {
-        id: 'h-cx-courdemanges-1988-ret01-dex01',
+        id: newEtapeId('h-cx-courdemanges-1988-ret01-dex01'),
         titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-ret01'),
         typeId: 'dex',
         statutId: 'acc',
@@ -54,7 +54,7 @@ describe("date de fin d'une démarche d'annulation", () => {
   test("retourne la date de fin d'une ACO si elle existe", () => {
     const titreDemarcheACOFaitEtapesDateFin: ITitreEtape[] = [
       {
-        id: 'h-cx-courdemanges-1988-ret01-dex01',
+        id: newEtapeId('h-cx-courdemanges-1988-ret01-dex01'),
         titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-ret01'),
         typeId: 'aco',
         statutId: 'fai',
diff --git a/packages/api/src/business/rules/titre-demarche-public-find.test.ts b/packages/api/src/business/rules/titre-demarche-public-find.test.ts
index ae514e4bc..0f857fb47 100644
--- a/packages/api/src/business/rules/titre-demarche-public-find.test.ts
+++ b/packages/api/src/business/rules/titre-demarche-public-find.test.ts
@@ -2,7 +2,7 @@ import { ITitreEtape } from '../../types.js'
 
 import { titreDemarchePublicFind } from './titre-demarche-public-find.js'
 import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { describe, expect, test } from 'vitest'
 import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js'
@@ -10,6 +10,10 @@ const etapesBuild = (etapesProps: Partial<ITitreEtape>[]) =>
   etapesProps.map(
     (etapeProps, i) =>
       ({
+        id: newEtapeId(`${i}+1`),
+        communes: null,
+        surface: null,
+        contenu: null,
         ...etapeProps,
         ordre: i + 1,
       } as unknown as ITitreEtape)
@@ -18,7 +22,10 @@ const etapesBuild = (etapesProps: Partial<ITitreEtape>[]) =>
 describe("publicité d'une démarche", () => {
   test("une démarche sans étape n'est pas publique", () => {
     expect(
-      titreDemarchePublicFind({ id: newDemarcheId(), typeId: 'oct', etapes: [], titreId: 'titreId', demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01') }, 'arm')
+      titreDemarchePublicFind(
+        { id: newDemarcheId(), typeId: 'oct', etapes: [], titreId: newTitreId('titreId'), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01') },
+        'arm'
+      )
     ).toMatchObject({
       publicLecture: false,
       entreprisesLecture: false,
@@ -32,7 +39,7 @@ describe("publicité d'une démarche", () => {
           id: newDemarcheId(),
           typeId: 'oct',
           etapes: etapesBuild([{ typeId: 'dae' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
         },
@@ -50,7 +57,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'spp' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -66,7 +73,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'spp' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -82,7 +89,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'spp' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -98,7 +105,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'mfr' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -114,7 +121,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'dex', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arg'
       )
@@ -130,7 +137,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'css' }, { typeId: 'mfr' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -146,7 +153,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'mcr', date: toCaminoDate('2000-01-01') }, { typeId: 'css' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'axm'
       )
@@ -162,7 +169,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'sca', date: toCaminoDate('2000-01-01') }, { typeId: 'css' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -178,7 +185,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'des', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -194,7 +201,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'des', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'axm'
       )
@@ -210,7 +217,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'mcr' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'cxf'
       )
@@ -226,7 +233,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'mcr', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -242,7 +249,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'mcr' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'cxf'
       )
@@ -258,7 +265,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'anf' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -274,7 +281,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'apu' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -290,7 +297,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'ane' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -306,7 +313,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'ppu' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -322,7 +329,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'def', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -338,7 +345,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'aca', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -354,7 +361,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'sca', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -370,7 +377,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2021-01-01'),
           etapes: etapesBuild([{ typeId: 'dim', statutId: 'acc' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -389,7 +396,7 @@ describe("publicité d'une démarche", () => {
             { typeId: 'anf', statutId: 'fai' },
             { typeId: 'dim', statutId: 'rej' },
           ]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'cxf'
       )
@@ -405,7 +412,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'dex', statutId: 'rej' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -424,7 +431,7 @@ describe("publicité d'une démarche", () => {
             { typeId: 'mcr', date: toCaminoDate('2000-01-01') },
             { typeId: 'dex', statutId: 'rej' },
           ]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'axm'
       )
@@ -440,7 +447,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'dex', statutId: 'acc', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'axm'
       )
@@ -456,7 +463,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'dpu', statutId: 'acc' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -472,7 +479,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'dux' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -488,7 +495,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'dup' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -504,7 +511,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'rpu' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -520,7 +527,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2001-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'sco', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -536,7 +543,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'sco', date: toCaminoDate('2000-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -552,7 +559,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'and', statutId: 'fav' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -568,7 +575,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'and', statutId: 'fai' }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'pcc'
       )
@@ -584,7 +591,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'mdp', statutId: 'fai', date: toCaminoDate('2017-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -600,7 +607,7 @@ describe("publicité d'une démarche", () => {
             { typeId: 'mfr', statutId: 'fai', date: toCaminoDate('2020-01-01') },
             { typeId: 'mdp', statutId: 'fai', date: toCaminoDate('2020-01-02') },
           ]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -616,7 +623,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'mcr', date: toCaminoDate('2017-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -634,7 +641,7 @@ describe("publicité d'une démarche", () => {
             { typeId: 'mdp', statutId: 'fai', date: toCaminoDate('2020-01-02') },
             { typeId: 'mcr', statutId: 'fav', date: toCaminoDate('2020-01-03') },
           ]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -653,7 +660,7 @@ describe("publicité d'une démarche", () => {
             { typeId: 'mcr', date: toCaminoDate('2017-01-01') },
             { typeId: 'eof', date: toCaminoDate('2017-01-01') },
           ]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -671,7 +678,7 @@ describe("publicité d'une démarche", () => {
             { typeId: 'mcr', statutId: 'fav', date: toCaminoDate('2020-01-03') },
             { typeId: 'eof', statutId: 'fai', date: toCaminoDate('2020-01-05') },
           ]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -687,7 +694,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'css', date: toCaminoDate('2017-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -705,7 +712,7 @@ describe("publicité d'une démarche", () => {
             { typeId: 'mcr', statutId: 'fav', date: toCaminoDate('2020-01-03') },
             { typeId: 'css', statutId: 'fai', date: toCaminoDate('2020-01-05') },
           ]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -722,7 +729,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'des', date: toCaminoDate('2017-01-01') }]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -740,7 +747,7 @@ describe("publicité d'une démarche", () => {
             { typeId: 'mdp', statutId: 'fai', date: toCaminoDate('2020-01-02') },
             { typeId: 'des', statutId: 'fai', date: toCaminoDate('2020-01-05') },
           ]),
-          titreId: 'titreId',
+          titreId: newTitreId('titreId'),
         },
         'arm'
       )
@@ -758,7 +765,7 @@ describe("publicité d'une démarche", () => {
             demarcheDateFin: toCaminoDate('2021-01-01'),
             id: newDemarcheId(),
             etapes: etapesBuild([{ typeId: etapeTypeId }]),
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
           },
           'pcc'
         )
@@ -775,7 +782,7 @@ describe("publicité d'une démarche", () => {
           demarcheDateFin: toCaminoDate('2021-01-01'),
           id: newDemarcheId(),
           etapes: etapesBuild([{ typeId: 'ane' }]),
-          titreId: 'WQaZgPfDcQw9tFliMgBIDH3Z',
+          titreId: newTitreId('WQaZgPfDcQw9tFliMgBIDH3Z'),
         },
         'pcc'
       )
@@ -785,7 +792,14 @@ describe("publicité d'une démarche", () => {
   test('la demarche d’une prolongation déposée d’un PRM en survie provisoire est public ', () => {
     expect(
       titreDemarchePublicFind(
-        { id: newDemarcheId(), typeId: 'pr1', demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: null, etapes: etapesBuild([{ typeId: 'mfr' }, { typeId: 'mdp' }]), titreId: 'titreId' },
+        {
+          id: newDemarcheId(),
+          typeId: 'pr1',
+          demarcheDateDebut: toCaminoDate('2020-01-01'),
+          demarcheDateFin: null,
+          etapes: etapesBuild([{ typeId: 'mfr' }, { typeId: 'mdp' }]),
+          titreId: newTitreId('titreId'),
+        },
         'prm'
       )
     ).toMatchObject({ publicLecture: true })
@@ -794,7 +808,7 @@ describe("publicité d'une démarche", () => {
   test('la demarche d’une prolongation non déposée d’un PRM en survie provisoire n’est pas public ', () => {
     expect(
       titreDemarchePublicFind(
-        { id: newDemarcheId(), typeId: 'pr1', demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: null, etapes: etapesBuild([{ typeId: 'mfr' }]), titreId: 'titreId' },
+        { id: newDemarcheId(), typeId: 'pr1', demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: null, etapes: etapesBuild([{ typeId: 'mfr' }]), titreId: newTitreId('titreId') },
         'prm'
       )
     ).toMatchObject({ publicLecture: false })
diff --git a/packages/api/src/business/rules/titre-demarche-public-find.ts b/packages/api/src/business/rules/titre-demarche-public-find.ts
index 28b41b305..e9f155c30 100644
--- a/packages/api/src/business/rules/titre-demarche-public-find.ts
+++ b/packages/api/src/business/rules/titre-demarche-public-find.ts
@@ -3,15 +3,15 @@ import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
 import { getDomaineId, TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { getEtapesTDE } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index.js'
 import { ITitreEtape, ITitreDemarche } from '../../types.js'
-import { demarcheDefinitionFind, isDemarcheDefinitionMachine } from '../rules-demarches/definitions.js'
-import { toMachineEtapes } from '../rules-demarches/machine-common.js'
+import { demarcheDefinitionFind } from '../rules-demarches/definitions.js'
+import { titreEtapeForMachineValidator, toMachineEtapes } from '../rules-demarches/machine-common.js'
 import { titreEtapesSortAscByOrdre } from '../utils/titre-etapes-sort.js'
 import { titreInSurvieProvisoire } from './titre-statut-id-find.js'
 const titreDemarchePublicLectureFind = (
   publicLecture: boolean,
   demarcheTypeId: DemarcheTypeId,
   demarcheTypeEtapesTypes: readonly EtapeTypeId[],
-  titreEtape: ITitreEtape,
+  titreEtape: Pick<ITitreEtape, 'typeId' | 'statutId'>,
   demarche: Pick<ITitreDemarche, 'demarcheDateFin' | 'demarcheDateDebut'>,
   titreTypeId?: TitreTypeId
 ) => {
@@ -164,12 +164,10 @@ export const titreDemarchePublicFind = (titreDemarche: Pick<ITitreDemarche, 'tit
   if (titreDemarche.titreId === 'WQaZgPfDcQw9tFliMgBIDH3Z') {
     publicLecture = false
   } else {
-    // si il existe un arbre d’instructions pour cette démarche,
-    // on laisse l’arbre traiter l’unicité des étapes
     const demarcheDefinition = demarcheDefinitionFind(titreTypeId, titreDemarche.typeId, titreDemarcheEtapes, titreDemarche.id)
 
-    if (isDemarcheDefinitionMachine(demarcheDefinition)) {
-      publicLecture = demarcheDefinition.machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes)).publique
+    if (demarcheDefinition) {
+      publicLecture = demarcheDefinition.machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes.map(etape => titreEtapeForMachineValidator.parse(etape)))).publique
     } else {
       const demarcheTypeEtapesTypes = getEtapesTDE(titreTypeId, titreDemarche.typeId)
       publicLecture = titreDemarcheEtapes.reduce(
diff --git a/packages/api/src/business/rules/titre-demarche-statut-id-find.test.ts b/packages/api/src/business/rules/titre-demarche-statut-id-find.test.ts
index cf0e422ad..38d01362a 100644
--- a/packages/api/src/business/rules/titre-demarche-statut-id-find.test.ts
+++ b/packages/api/src/business/rules/titre-demarche-statut-id-find.test.ts
@@ -6,13 +6,14 @@ import { newDemarcheId } from '../../database/models/_format/id-create.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { describe, expect, test } from 'vitest'
 import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts.js'
-const etapesBuild = (etapesProps: Partial<ITitreEtape>[]) =>
+import { TitreEtapeForMachine } from '../rules-demarches/machine-common.js'
+const etapesBuild = (etapesProps: Partial<ITitreEtape>[]): TitreEtapeForMachine[] =>
   etapesProps.map(
     (etapeProps, i) =>
       ({
         ...etapeProps,
         ordre: i + 1,
-      } as unknown as ITitreEtape)
+      } as unknown as TitreEtapeForMachine)
   )
 
 describe("statut d'une démarche", () => {
@@ -60,7 +61,7 @@ describe("statut d'une démarche", () => {
   })
 
   test("une démarche d'octroi d'un titre PRM dont l'étape de rpu la plus récente est acceptée a le statut “accepté”", () => {
-    expect(titreDemarcheStatutIdFind('oct', etapesBuild([{ typeId: 'rpu', statutId: 'acc' }]), 'prm', newDemarcheId())).toEqual('acc')
+    expect(titreDemarcheStatutIdFind('oct', etapesBuild([{ typeId: 'rpu', date: toCaminoDate('2010-01-01'), statutId: 'acc' }]), 'prm', newDemarcheId())).toEqual('acc')
   })
 
   test("une démarche de prolongation dont l'étape de dpu la plus récente est acceptée a le statut “accepté”", () => {
diff --git a/packages/api/src/business/rules/titre-demarche-statut-id-find.ts b/packages/api/src/business/rules/titre-demarche-statut-id-find.ts
index 2c1108b4b..a58d5c9da 100644
--- a/packages/api/src/business/rules/titre-demarche-statut-id-find.ts
+++ b/packages/api/src/business/rules/titre-demarche-statut-id-find.ts
@@ -3,8 +3,8 @@ import { DemarcheId } from 'camino-common/src/demarche.js'
 
 import { titreEtapesSortDescByOrdre } from '../utils/titre-etapes-sort.js'
 import { titreEtapePublicationCheck } from './titre-etape-publication-check.js'
-import { demarcheDefinitionFind, isDemarcheDefinitionMachine } from '../rules-demarches/definitions.js'
-import { toMachineEtapes } from '../rules-demarches/machine-common.js'
+import { demarcheDefinitionFind } from '../rules-demarches/definitions.js'
+import { TitreEtapeForMachine, toMachineEtapes } from '../rules-demarches/machine-common.js'
 import { DemarcheStatutId, DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts.js'
 import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { DemarcheTypeId, TravauxIds } from 'camino-common/src/static/demarchesTypes.js'
@@ -293,12 +293,7 @@ const titreDemarcheTravauxStatutIdFind = (titreDemarcheEtapes: Pick<ITitreEtape,
  * @param titreTypeId - id du type de titre
  */
 
-export const titreDemarcheStatutIdFind = (
-  demarcheTypeId: DemarcheTypeId,
-  titreDemarcheEtapes: Pick<ITitreEtape, 'typeId' | 'date' | 'ordre' | 'statutId' | 'contenu'>[],
-  titreTypeId: TitreTypeId,
-  demarcheId: DemarcheId
-): DemarcheStatutId => {
+export const titreDemarcheStatutIdFind = (demarcheTypeId: DemarcheTypeId, titreDemarcheEtapes: TitreEtapeForMachine[], titreTypeId: TitreTypeId, demarcheId: DemarcheId): DemarcheStatutId => {
   // si la démarche ne contient pas d'étapes
   // -> le statut est indétrminé
   if (!titreDemarcheEtapes.length) return DemarchesStatutsIds.Indetermine
@@ -310,7 +305,7 @@ export const titreDemarcheStatutIdFind = (
 
   const demarcheDefinition = demarcheDefinitionFind(titreTypeId, demarcheTypeId, titreDemarcheEtapes, demarcheId)
 
-  if (isDemarcheDefinitionMachine(demarcheDefinition)) {
+  if (demarcheDefinition) {
     return demarcheDefinition.machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes)).demarcheStatut
   }
 
diff --git a/packages/api/src/business/rules/titre-etape-prop-find.test.ts b/packages/api/src/business/rules/titre-etape-prop-find.test.ts
index 7ffd1f2b4..0cd7ffa81 100644
--- a/packages/api/src/business/rules/titre-etape-prop-find.test.ts
+++ b/packages/api/src/business/rules/titre-etape-prop-find.test.ts
@@ -29,15 +29,23 @@ describe("valeur d'une propriété pour une étape", () => {
             etapes: [
               {
                 id: 'demarche-01-etape-01',
+                typeId: 'aac',
                 statutId: 'acc',
-                date: '1000-01-01',
+                date: toCaminoDate('1000-01-01'),
                 titulaires: [],
+                ordre: 1,
+                communes: null,
+                surface: null,
               },
               {
                 id: 'demarche-01-etape-02',
+                typeId: 'aac',
                 statutId: 'acc',
-                date: '1000-01-01',
+                date: toCaminoDate('1000-01-01'),
                 titulaires: [{ id: 'fr-xxxxxxxxx' }],
+                ordre: 1,
+                communes: null,
+                surface: null,
               },
             ],
           },
@@ -60,6 +68,11 @@ describe("valeur d'une propriété pour une étape", () => {
             etapes: [
               {
                 id: 'demarche-01-etape-01',
+                typeId: 'aac',
+                statutId: 'acc',
+                surface: 0,
+                ordre: 1,
+                communes: null,
                 date: '1000-01-01',
               },
             ],
@@ -71,8 +84,11 @@ describe("valeur d'une propriété pour une étape", () => {
               {
                 id: 'demarche-02-etape-01',
                 date: '1000-01-01',
+                typeId: 'aac',
                 statutId: 'acc',
                 surface: 0,
+                ordre: 1,
+                communes: null,
               },
             ],
           },
@@ -98,6 +114,10 @@ describe("valeur d'une propriété pour une étape", () => {
                 date: '1000-01-01',
                 statutId: 'acc',
                 titulaires: null,
+                typeId: 'aac',
+                surface: 0,
+                ordre: 1,
+                communes: null,
               },
             ],
           },
diff --git a/packages/api/src/business/rules/titre-phases-find.test.ts b/packages/api/src/business/rules/titre-phases-find.test.ts
index 81c568554..7cd0baca4 100644
--- a/packages/api/src/business/rules/titre-phases-find.test.ts
+++ b/packages/api/src/business/rules/titre-phases-find.test.ts
@@ -2,7 +2,7 @@ import { ITitreDemarche } from '../../types.js'
 import { DemarcheId } from 'camino-common/src/demarche.js'
 
 import { titrePhasesFind, TitreDemarchePhaseFind } from './titre-phases-find.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create.js'
 import { CaminoDate, toCaminoDate } from 'camino-common/src/date.js'
 import { describe, expect, test } from 'vitest'
 import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes'
@@ -20,7 +20,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'titreid',
+            titreId: newTitreId('titreid'),
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
             typeId: 'oct',
             statutId: 'acc',
@@ -59,7 +59,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
             typeId: 'oct',
             statutId: 'acc',
@@ -76,7 +76,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('h-ax-courdemanges-1988-oct01'),
             typeId: 'oct',
             statutId: 'acc',
@@ -107,7 +107,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('m-pr-courdemanges-1988-oct01'),
             typeId: 'oct',
             statutId: 'acc',
@@ -138,7 +138,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
             typeId: 'oct',
             statutId: 'acc',
@@ -179,7 +179,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
             typeId: 'oct',
             statutId: 'acc',
@@ -204,7 +204,7 @@ describe("phases d'une démarche", () => {
             ],
           },
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('h-cx-courdemanges-1988-pro01'),
             typeId: 'pro',
             statutId: 'acc',
@@ -248,7 +248,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
             typeId: 'oct',
             statutId: 'acc',
@@ -273,7 +273,7 @@ describe("phases d'une démarche", () => {
             ],
           },
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('h-cx-courdemanges-1988-ren01'),
             typeId: 'ren',
             statutId: 'acc',
@@ -311,7 +311,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('h-cx-courdemanges-1988-oct01'),
             typeId: 'oct',
             statutId: 'acc',
@@ -336,7 +336,7 @@ describe("phases d'une démarche", () => {
             ],
           },
           {
-            titreId: 'titreId',
+            titreId: newTitreId('titreId'),
             id: newDemarcheId('h-cx-courdemanges-1988-ren01'),
             typeId: 'ren',
             statutId: 'acc',
@@ -355,7 +355,7 @@ describe("phases d'une démarche", () => {
                 statutId: 'acc',
                 ordre: 1,
                 date: toCaminoDate('2019-01-02'),
-                points: [{ id: 'point' }],
+                points: [{ id: newEtapeId('point') }],
               },
             ],
           },
@@ -371,7 +371,7 @@ describe("phases d'une démarche", () => {
   })
 
   test('cas sans date de fin et avec plein de css', () => {
-    const titreId = 'titreId'
+    const titreId = newTitreId('titreId')
     const demarcheId1 = newDemarcheId('demarcheId1')
     const demarcheId2 = newDemarcheId('demarcheId2')
     const demarcheId3 = newDemarcheId('demarcheId3')
@@ -391,9 +391,9 @@ describe("phases d'une démarche", () => {
         typeId: 'mut',
         statutId: 'cls',
         etapes: [
-          { titreDemarcheId: demarcheId1, id: '3', ordre: 1, date: toCaminoDate('2016-12-28'), duree: 1920, surface: 5.51, typeId: 'mfr', statutId: 'fai' },
-          { titreDemarcheId: demarcheId1, id: '1', ordre: 2, date: toCaminoDate('2016-12-28'), typeId: 'mdp', statutId: 'fai' },
-          { titreDemarcheId: demarcheId1, id: '2', ordre: 3, date: toCaminoDate('2017-04-07'), typeId: 'css', statutId: 'fai' },
+          { titreDemarcheId: demarcheId1, id: newEtapeId('3'), ordre: 1, date: toCaminoDate('2016-12-28'), duree: 1920, surface: 5.51, typeId: 'mfr', statutId: 'fai' },
+          { titreDemarcheId: demarcheId1, id: newEtapeId('1'), ordre: 2, date: toCaminoDate('2016-12-28'), typeId: 'mdp', statutId: 'fai' },
+          { titreDemarcheId: demarcheId1, id: newEtapeId('2'), ordre: 3, date: toCaminoDate('2017-04-07'), typeId: 'css', statutId: 'fai' },
         ],
       },
       {
@@ -403,9 +403,9 @@ describe("phases d'une démarche", () => {
         typeId: 'pro',
         statutId: 'cls',
         etapes: [
-          { titreDemarcheId: demarcheId2, id: '4', ordre: 1, date: toCaminoDate('2016-12-28'), duree: 1920, surface: 5.51, typeId: 'mfr', statutId: 'fai' },
-          { titreDemarcheId: demarcheId2, id: '5', ordre: 2, date: toCaminoDate('2016-12-28'), typeId: 'mdp', statutId: 'fai' },
-          { titreDemarcheId: demarcheId2, id: '6', ordre: 3, date: toCaminoDate('2017-04-07'), typeId: 'css', statutId: 'fai' },
+          { titreDemarcheId: demarcheId2, id: newEtapeId('4'), ordre: 1, date: toCaminoDate('2016-12-28'), duree: 1920, surface: 5.51, typeId: 'mfr', statutId: 'fai' },
+          { titreDemarcheId: demarcheId2, id: newEtapeId('5'), ordre: 2, date: toCaminoDate('2016-12-28'), typeId: 'mdp', statutId: 'fai' },
+          { titreDemarcheId: demarcheId2, id: newEtapeId('6'), ordre: 3, date: toCaminoDate('2017-04-07'), typeId: 'css', statutId: 'fai' },
         ],
       },
       {
@@ -415,9 +415,9 @@ describe("phases d'une démarche", () => {
         typeId: 'dam',
         statutId: 'ins',
         etapes: [
-          { id: '7', titreDemarcheId: demarcheId3, ordre: 3, date: toCaminoDate('2014-12-23'), typeId: 'wpp', statutId: 'fai' },
-          { id: '8', titreDemarcheId: demarcheId3, ordre: 1, date: toCaminoDate('2013-08-01'), typeId: 'wfd', statutId: 'fai' },
-          { id: '9', titreDemarcheId: demarcheId3, ordre: 2, date: toCaminoDate('2014-08-25'), typeId: 'wre', statutId: 'fav' },
+          { id: newEtapeId('7'), titreDemarcheId: demarcheId3, ordre: 3, date: toCaminoDate('2014-12-23'), typeId: 'wpp', statutId: 'fai' },
+          { id: newEtapeId('8'), titreDemarcheId: demarcheId3, ordre: 1, date: toCaminoDate('2013-08-01'), typeId: 'wfd', statutId: 'fai' },
+          { id: newEtapeId('9'), titreDemarcheId: demarcheId3, ordre: 2, date: toCaminoDate('2014-08-25'), typeId: 'wre', statutId: 'fav' },
         ],
       },
       {
@@ -427,8 +427,8 @@ describe("phases d'une démarche", () => {
         typeId: 'mut',
         statutId: 'acc',
         etapes: [
-          { id: '10', titreDemarcheId: demarcheId4, ordre: 1, date: toCaminoDate('2002-12-24'), typeId: 'dex', statutId: 'acc' },
-          { titreDemarcheId: demarcheId4, id: '11', ordre: 2, date: toCaminoDate('2003-01-08'), typeId: 'dpu', statutId: 'acc' },
+          { id: newEtapeId('10'), titreDemarcheId: demarcheId4, ordre: 1, date: toCaminoDate('2002-12-24'), typeId: 'dex', statutId: 'acc' },
+          { titreDemarcheId: demarcheId4, id: newEtapeId('11'), ordre: 2, date: toCaminoDate('2003-01-08'), typeId: 'dpu', statutId: 'acc' },
         ],
       },
       {
@@ -438,8 +438,8 @@ describe("phases d'une démarche", () => {
         typeId: 'mut',
         statutId: 'acc',
         etapes: [
-          { id: '12', titreDemarcheId: demarcheId5, ordre: 1, date: toCaminoDate('2000-09-26'), typeId: 'dex', statutId: 'acc' },
-          { id: '13', titreDemarcheId: demarcheId5, ordre: 2, date: toCaminoDate('2000-10-06'), typeId: 'dpu', statutId: 'acc' },
+          { id: newEtapeId('12'), titreDemarcheId: demarcheId5, ordre: 1, date: toCaminoDate('2000-09-26'), typeId: 'dex', statutId: 'acc' },
+          { id: newEtapeId('13'), titreDemarcheId: demarcheId5, ordre: 2, date: toCaminoDate('2000-10-06'), typeId: 'dpu', statutId: 'acc' },
         ],
       },
       {
@@ -449,8 +449,8 @@ describe("phases d'une démarche", () => {
         typeId: 'mut',
         statutId: 'acc',
         etapes: [
-          { id: 'id', titreDemarcheId: demarcheId6, ordre: 1, date: toCaminoDate('1975-11-24'), typeId: 'dex', statutId: 'acc' },
-          { id: '15', titreDemarcheId: demarcheId6, ordre: 2, date: toCaminoDate('1975-11-27'), typeId: 'dpu', statutId: 'acc' },
+          { id: newEtapeId('id'), titreDemarcheId: demarcheId6, ordre: 1, date: toCaminoDate('1975-11-24'), typeId: 'dex', statutId: 'acc' },
+          { id: newEtapeId('15'), titreDemarcheId: demarcheId6, ordre: 2, date: toCaminoDate('1975-11-27'), typeId: 'dpu', statutId: 'acc' },
         ],
       },
       {
@@ -461,8 +461,8 @@ describe("phases d'une démarche", () => {
 
         statutId: 'acc',
         etapes: [
-          { id: '16', titreDemarcheId: demarcheId7, ordre: 1, date: toCaminoDate('1970-11-16'), typeId: 'dex', statutId: 'acc' },
-          { id: '17', titreDemarcheId: demarcheId7, ordre: 2, date: toCaminoDate('1970-11-19'), typeId: 'dpu', statutId: 'acc' },
+          { id: newEtapeId('16'), titreDemarcheId: demarcheId7, ordre: 1, date: toCaminoDate('1970-11-16'), typeId: 'dex', statutId: 'acc' },
+          { id: newEtapeId('17'), titreDemarcheId: demarcheId7, ordre: 2, date: toCaminoDate('1970-11-19'), typeId: 'dpu', statutId: 'acc' },
         ],
       },
       {
@@ -472,8 +472,8 @@ describe("phases d'une démarche", () => {
         typeId: 'mut',
         statutId: 'acc',
         etapes: [
-          { id: '18', titreDemarcheId: demarcheId8, ordre: 2, date: toCaminoDate('1949-08-31'), typeId: 'dpu', statutId: 'acc' },
-          { id: '19', titreDemarcheId: demarcheId8, ordre: 1, date: toCaminoDate('1949-08-23'), typeId: 'dex', statutId: 'acc' },
+          { id: newEtapeId('18'), titreDemarcheId: demarcheId8, ordre: 2, date: toCaminoDate('1949-08-31'), typeId: 'dpu', statutId: 'acc' },
+          { id: newEtapeId('19'), titreDemarcheId: demarcheId8, ordre: 1, date: toCaminoDate('1949-08-23'), typeId: 'dex', statutId: 'acc' },
         ],
       },
       {
@@ -483,8 +483,8 @@ describe("phases d'une démarche", () => {
         typeId: 'exp',
         statutId: 'acc',
         etapes: [
-          { id: '20', titreDemarcheId: demarcheId9, ordre: 1, date: toCaminoDate('1889-02-27'), typeId: 'dex', statutId: 'acc' },
-          { id: '21', titreDemarcheId: demarcheId9, ordre: 2, date: toCaminoDate('1889-02-27'), typeId: 'dpu', statutId: 'acc' },
+          { id: newEtapeId('20'), titreDemarcheId: demarcheId9, ordre: 1, date: toCaminoDate('1889-02-27'), typeId: 'dex', statutId: 'acc' },
+          { id: newEtapeId('21'), titreDemarcheId: demarcheId9, ordre: 2, date: toCaminoDate('1889-02-27'), typeId: 'dpu', statutId: 'acc' },
         ],
       },
       {
@@ -494,8 +494,8 @@ describe("phases d'une démarche", () => {
         typeId: 'exp',
         statutId: 'acc',
         etapes: [
-          { id: '22', titreDemarcheId: demarcheId10, ordre: 2, date: toCaminoDate('1879-11-14'), typeId: 'dpu', statutId: 'acc' },
-          { id: '23', titreDemarcheId: demarcheId10, ordre: 1, date: toCaminoDate('1879-07-26'), typeId: 'dex', statutId: 'acc' },
+          { id: newEtapeId('22'), titreDemarcheId: demarcheId10, ordre: 2, date: toCaminoDate('1879-11-14'), typeId: 'dpu', statutId: 'acc' },
+          { id: newEtapeId('23'), titreDemarcheId: demarcheId10, ordre: 1, date: toCaminoDate('1879-07-26'), typeId: 'dex', statutId: 'acc' },
         ],
       },
       {
@@ -505,8 +505,8 @@ describe("phases d'une démarche", () => {
         typeId: 'oct',
         statutId: 'acc',
         etapes: [
-          { id: '24', titreDemarcheId: demarcheId11, ordre: 1, date: toCaminoDate('1858-03-24'), typeId: 'dex', statutId: 'acc' },
-          { id: '25', titreDemarcheId: demarcheId11, ordre: 2, date: toCaminoDate('1858-03-24'), typeId: 'dpu', statutId: 'acc' },
+          { id: newEtapeId('24'), titreDemarcheId: demarcheId11, ordre: 1, date: toCaminoDate('1858-03-24'), typeId: 'dex', statutId: 'acc' },
+          { id: newEtapeId('25'), titreDemarcheId: demarcheId11, ordre: 2, date: toCaminoDate('1858-03-24'), typeId: 'dpu', statutId: 'acc' },
         ],
       },
     ]
@@ -521,7 +521,7 @@ describe("phases d'une démarche", () => {
   })
 
   test('cas de survie provisoire avec la prolongation en classement sans suite après la fin de l’octroi', () => {
-    const titreId = 'titreId'
+    const titreId = newTitreId('titreId')
     const demarcheIdOctroi = newDemarcheId('demarcheIdOctroi')
     const demarcheIdProlongation = newDemarcheId('demarcheIdProlongation')
     const demarches: ITitreDemarche[] = [
@@ -532,9 +532,9 @@ describe("phases d'une démarche", () => {
         typeId: 'pro',
         statutId: 'cls',
         etapes: [
-          { titreDemarcheId: demarcheIdProlongation, id: '2', ordre: 3, date: toCaminoDate('2011-04-07'), typeId: 'css', statutId: 'fai' },
-          { titreDemarcheId: demarcheIdProlongation, id: '1', ordre: 2, date: toCaminoDate('2008-12-28'), typeId: 'mdp', statutId: 'fai' },
-          { titreDemarcheId: demarcheIdProlongation, id: '3', ordre: 1, date: toCaminoDate('2008-12-28'), duree: 60, typeId: 'mfr', statutId: 'fai' },
+          { titreDemarcheId: demarcheIdProlongation, id: newEtapeId('2'), ordre: 3, date: toCaminoDate('2011-04-07'), typeId: 'css', statutId: 'fai' },
+          { titreDemarcheId: demarcheIdProlongation, id: newEtapeId('1'), ordre: 2, date: toCaminoDate('2008-12-28'), typeId: 'mdp', statutId: 'fai' },
+          { titreDemarcheId: demarcheIdProlongation, id: newEtapeId('3'), ordre: 1, date: toCaminoDate('2008-12-28'), duree: 60, typeId: 'mfr', statutId: 'fai' },
         ],
       },
       {
@@ -544,8 +544,8 @@ describe("phases d'une démarche", () => {
         typeId: 'oct',
         statutId: 'acc',
         etapes: [
-          { id: '24', titreDemarcheId: demarcheIdOctroi, ordre: 1, date: toCaminoDate('2000-03-24'), typeId: 'dex', statutId: 'acc', duree: 120 },
-          { id: '25', titreDemarcheId: demarcheIdOctroi, ordre: 2, date: toCaminoDate('2000-03-24'), typeId: 'dpu', statutId: 'acc' },
+          { id: newEtapeId('24'), titreDemarcheId: demarcheIdOctroi, ordre: 1, date: toCaminoDate('2000-03-24'), typeId: 'dex', statutId: 'acc', duree: 120 },
+          { id: newEtapeId('25'), titreDemarcheId: demarcheIdOctroi, ordre: 2, date: toCaminoDate('2000-03-24'), typeId: 'dpu', statutId: 'acc' },
         ],
       },
     ]
@@ -564,7 +564,7 @@ describe("phases d'une démarche", () => {
   })
 
   test('un octroi rejeté ne génère pas de phase', () => {
-    const titreId = 'titreId'
+    const titreId = newTitreId('titreId')
     const demarcheIdOctroi = newDemarcheId('demarcheIdOctroi')
     const demarches: ITitreDemarche[] = [
       {
@@ -574,8 +574,8 @@ describe("phases d'une démarche", () => {
         typeId: 'oct',
         statutId: 'acc',
         etapes: [
-          { id: '24', titreDemarcheId: demarcheIdOctroi, ordre: 1, date: toCaminoDate('2000-03-24'), typeId: 'dex', statutId: 'acc', duree: 120 },
-          { id: '25', titreDemarcheId: demarcheIdOctroi, ordre: 2, date: toCaminoDate('2000-03-24'), typeId: 'dpu', statutId: 'rej' },
+          { id: newEtapeId('24'), titreDemarcheId: demarcheIdOctroi, ordre: 1, date: toCaminoDate('2000-03-24'), typeId: 'dex', statutId: 'acc', duree: 120 },
+          { id: newEtapeId('25'), titreDemarcheId: demarcheIdOctroi, ordre: 2, date: toCaminoDate('2000-03-24'), typeId: 'dpu', statutId: 'rej' },
         ],
       },
     ]
@@ -588,13 +588,13 @@ describe("phases d'une démarche", () => {
     const demarches: ITitreDemarche[] = [
       {
         id: newDemarcheId('demarcheId1'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'oct',
         statutId: 'acc',
         ordre: 1,
         etapes: [
           {
-            id: 'demarcheId1etapeId2',
+            id: newEtapeId('demarcheId1etapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -602,7 +602,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('1970-09-17'),
           },
           {
-            id: 'demarcheId1etapeId1',
+            id: newEtapeId('demarcheId1etapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dex',
             statutId: 'acc',
@@ -613,14 +613,14 @@ describe("phases d'une démarche", () => {
       },
       {
         id: newDemarcheId('demarcheId2'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'mut',
         statutId: 'acc',
         ordre: 2,
         slug: 'm-cx-pontaubert-1970-mut01',
         etapes: [
           {
-            id: 'demarcheId2EtapeId2',
+            id: newEtapeId('demarcheId2EtapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId2'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -630,7 +630,7 @@ describe("phases d'une démarche", () => {
             duree: 600,
           },
           {
-            id: 'demarcheId2EtapeId1',
+            id: newEtapeId('demarcheId2EtapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId2'),
             typeId: 'dex',
             statutId: 'acc',
@@ -642,13 +642,13 @@ describe("phases d'une démarche", () => {
       },
       {
         id: newDemarcheId('demarcheId3'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'ren',
         statutId: 'acc',
         ordre: 3,
         etapes: [
           {
-            id: 'demarcheId3etapeId1',
+            id: newEtapeId('demarcheId3etapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'mfr',
             statutId: 'fai',
@@ -656,7 +656,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2019-10-22'),
           },
           {
-            id: 'demarcheId3etapeId2',
+            id: newEtapeId('demarcheId3etapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'mdp',
             statutId: 'fai',
@@ -664,7 +664,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2019-11-20'),
           },
           {
-            id: 'demarcheId3etapeId5',
+            id: newEtapeId('demarcheId3etapeId5'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'dex',
             statutId: 'acc',
@@ -672,7 +672,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2022-05-09'),
           },
           {
-            id: 'demarcheId3etapeId6',
+            id: newEtapeId('demarcheId3etapeId6'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -680,7 +680,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2022-05-09'),
           },
           {
-            id: 'demarcheId3etapeId3',
+            id: newEtapeId('demarcheId3etapeId3'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'apd',
             statutId: 'fav',
@@ -688,7 +688,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2020-05-11'),
           },
           {
-            id: 'demarcheId3etapeId4',
+            id: newEtapeId('demarcheId3etapeId4'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'app',
             statutId: 'fav',
@@ -718,13 +718,13 @@ describe("phases d'une démarche", () => {
     const demarches: ITitreDemarche[] = [
       {
         id: newDemarcheId('demarcheId1'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'oct',
         statutId: 'acc',
         ordre: 1,
         etapes: [
           {
-            id: 'demarcheId1etapeId2',
+            id: newEtapeId('demarcheId1etapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -732,7 +732,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('1970-09-17'),
           },
           {
-            id: 'demarcheId1etapeId1',
+            id: newEtapeId('demarcheId1etapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dex',
             statutId: 'acc',
@@ -743,13 +743,13 @@ describe("phases d'une démarche", () => {
       },
       {
         id: newDemarcheId('demarcheId2'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'mut',
         statutId: 'acc',
         ordre: 2,
         etapes: [
           {
-            id: 'demarcheId2EtapeId2',
+            id: newEtapeId('demarcheId2EtapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId2'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -759,7 +759,7 @@ describe("phases d'une démarche", () => {
             duree: 600,
           },
           {
-            id: 'demarcheId2EtapeId1',
+            id: newEtapeId('demarcheId2EtapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId2'),
             typeId: 'dex',
             statutId: 'acc',
@@ -771,13 +771,13 @@ describe("phases d'une démarche", () => {
       },
       {
         id: newDemarcheId('demarcheId3'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'ren',
         statutId: 'acc',
         ordre: 3,
         etapes: [
           {
-            id: 'demarcheId3etapeId1',
+            id: newEtapeId('demarcheId3etapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'mfr',
             statutId: 'fai',
@@ -785,7 +785,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2019-10-22'),
           },
           {
-            id: 'demarcheId3etapeId2',
+            id: newEtapeId('demarcheId3etapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'mdp',
             statutId: 'fai',
@@ -793,7 +793,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2019-11-20'),
           },
           {
-            id: 'demarcheId3etapeId3',
+            id: newEtapeId('demarcheId3etapeId3'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'apd',
             statutId: 'fav',
@@ -801,7 +801,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2020-05-11'),
           },
           {
-            id: 'demarcheId3etapeId5',
+            id: newEtapeId('demarcheId3etapeId5'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'dim',
             statutId: 'acc',
@@ -809,7 +809,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2022-05-09'),
           },
           {
-            id: 'demarcheId3etapeId4',
+            id: newEtapeId('demarcheId3etapeId4'),
             titreDemarcheId: newDemarcheId('demarcheId3'),
             typeId: 'app',
             statutId: 'fav',
@@ -839,13 +839,13 @@ describe("phases d'une démarche", () => {
     const demarches: ITitreDemarche[] = [
       {
         id: newDemarcheId('demarcheId1'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'oct',
         statutId: 'acc',
         ordre: 1,
         etapes: [
           {
-            id: 'demarcheId1etapeId2',
+            id: newEtapeId('demarcheId1etapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -853,7 +853,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('1968-01-24'),
           },
           {
-            id: 'demarcheId1etapeId1',
+            id: newEtapeId('demarcheId1etapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dex',
             statutId: 'acc',
@@ -864,13 +864,13 @@ describe("phases d'une démarche", () => {
       },
       {
         id: newDemarcheId('demarcheId2'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: DEMARCHES_TYPES_IDS.ExtensionDePerimetre,
         statutId: 'acc',
         ordre: 2,
         etapes: [
           {
-            id: 'demarcheId2EtapeId2',
+            id: newEtapeId('demarcheId2EtapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId2'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -879,7 +879,7 @@ describe("phases d'une démarche", () => {
             dateFin: toCaminoDate('2031-09-13'),
           },
           {
-            id: 'demarcheId2EtapeId1',
+            id: newEtapeId('demarcheId2EtapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId2'),
             typeId: 'dex',
             statutId: 'acc',
@@ -908,13 +908,13 @@ describe("phases d'une démarche", () => {
     const demarches: ITitreDemarche[] = [
       {
         id: newDemarcheId('demarcheId1'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'oct',
         statutId: 'acc',
         ordre: 1,
         etapes: [
           {
-            id: 'demarcheId1etapeId2',
+            id: newEtapeId('demarcheId1etapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -923,7 +923,7 @@ describe("phases d'une démarche", () => {
             duree: 60,
           },
           {
-            id: 'demarcheId1etapeId1',
+            id: newEtapeId('demarcheId1etapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dex',
             statutId: 'acc',
@@ -934,13 +934,13 @@ describe("phases d'une démarche", () => {
       },
       {
         id: newDemarcheId('demarcheId2'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: DEMARCHES_TYPES_IDS.Prolongation1,
         statutId: DemarchesStatutsIds.EnConstruction,
         ordre: 2,
         etapes: [
           {
-            id: 'demarcheId2EtapeId2',
+            id: newEtapeId('demarcheId2EtapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId2'),
             typeId: 'mfr',
             statutId: 'fai',
@@ -970,13 +970,13 @@ describe("phases d'une démarche", () => {
     const demarches: ITitreDemarche[] = [
       {
         id: newDemarcheId('demarcheId1'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'oct',
         statutId: 'acc',
         ordre: 1,
         etapes: [
           {
-            id: 'demarcheId1etapeId2',
+            id: newEtapeId('demarcheId1etapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -985,7 +985,7 @@ describe("phases d'une démarche", () => {
             duree: 60,
           },
           {
-            id: 'demarcheId1etapeId1',
+            id: newEtapeId('demarcheId1etapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dex',
             statutId: 'acc',
@@ -996,13 +996,13 @@ describe("phases d'une démarche", () => {
       },
       {
         id: newDemarcheId('demarcheId2'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: DEMARCHES_TYPES_IDS.Prolongation1,
         statutId: DemarchesStatutsIds.EnConstruction,
         ordre: 2,
         etapes: [
           {
-            id: 'demarcheId2EtapeId2',
+            id: newEtapeId('demarcheId2EtapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId2'),
             typeId: 'mfr',
             statutId: ETAPES_STATUTS.EN_CONSTRUCTION,
@@ -1028,13 +1028,13 @@ describe("phases d'une démarche", () => {
     const demarches: ITitreDemarche[] = [
       {
         id: newDemarcheId('demarcheId1'),
-        titreId: 'titreId',
+        titreId: newTitreId('titreId'),
         typeId: 'oct',
         statutId: 'acc',
         ordre: 1,
         etapes: [
           {
-            id: 'demarcheId1etapeId3',
+            id: newEtapeId('demarcheId1etapeId3'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dpu',
             statutId: 'rej',
@@ -1042,7 +1042,7 @@ describe("phases d'une démarche", () => {
             date: toCaminoDate('2018-11-11'),
           },
           {
-            id: 'demarcheId1etapeId2',
+            id: newEtapeId('demarcheId1etapeId2'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dpu',
             statutId: 'acc',
@@ -1051,7 +1051,7 @@ describe("phases d'une démarche", () => {
             duree: 60,
           },
           {
-            id: 'demarcheId1etapeId1',
+            id: newEtapeId('demarcheId1etapeId1'),
             titreDemarcheId: newDemarcheId('demarcheId1'),
             typeId: 'dex',
             statutId: 'acc',
@@ -1072,7 +1072,7 @@ describe("phases d'une démarche", () => {
   })
 
   test("2 démarches avec des phases en cours ne génère qu'une seule phase en modification en instance", () => {
-    const titreId = 'titreId'
+    const titreId = newTitreId('titreId')
     const demarcheId1 = newDemarcheId('demarcheId1')
     const demarcheId2 = newDemarcheId('demarcheId2')
     const demarcheId3 = newDemarcheId('demarcheId3')
@@ -1374,7 +1374,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'nJ10z3Z74xi9OTh4oG6YXQBo',
+            titreId: newTitreId('nJ10z3Z74xi9OTh4oG6YXQBo'),
             statutId: 'acc',
             ordre: 1,
             typeId: 'oct',
@@ -1405,7 +1405,7 @@ describe("phases d'une démarche", () => {
             ],
           },
           {
-            titreId: 'EW9cDeM6PfXS4TPznkjsNZVO',
+            titreId: newTitreId('EW9cDeM6PfXS4TPznkjsNZVO'),
             statutId: 'rej',
             ordre: 2,
             typeId: 'pr1',
@@ -1437,7 +1437,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'o3RzmZvqZcKMNmaE3nwXdvkE',
+            titreId: newTitreId('o3RzmZvqZcKMNmaE3nwXdvkE'),
             statutId: 'acc',
             ordre: 1,
             typeId: 'oct',
@@ -1468,7 +1468,7 @@ describe("phases d'une démarche", () => {
             ],
           },
           {
-            titreId: 'Mef8FKNlX0WtohaO9wGOMQZs',
+            titreId: newTitreId('Mef8FKNlX0WtohaO9wGOMQZs'),
             statutId: 'des',
             ordre: 2,
             typeId: 'pr1',
@@ -1503,7 +1503,7 @@ describe("phases d'une démarche", () => {
       titrePhasesFind(
         [
           {
-            titreId: 'nJ10z3Z74xi9OTh4oG6YXQBo',
+            titreId: newTitreId('nJ10z3Z74xi9OTh4oG6YXQBo'),
             statutId: 'acc',
             ordre: 1,
             typeId: 'oct',
@@ -1534,7 +1534,7 @@ describe("phases d'une démarche", () => {
             ],
           },
           {
-            titreId: 'EW9cDeM6PfXS4TPznkjsNZVO',
+            titreId: newTitreId('EW9cDeM6PfXS4TPznkjsNZVO'),
             statutId: 'rej',
             ordre: 2,
             typeId: 'pr1',
diff --git a/packages/api/src/business/rules/titre-prop-etape-find.test.ts b/packages/api/src/business/rules/titre-prop-etape-find.test.ts
index 5b4cd9cb8..4952c614c 100644
--- a/packages/api/src/business/rules/titre-prop-etape-find.test.ts
+++ b/packages/api/src/business/rules/titre-prop-etape-find.test.ts
@@ -1,7 +1,7 @@
 import { ITitreDemarche, IPropId, ITitreEtape, ITitrePoint, ICommune } from '../../types.js'
 
 import { titreContenuTitreEtapeFind, titrePropTitreEtapeFind } from './titre-prop-etape-find.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { describe, expect, test } from 'vitest'
 import { TitresStatutIds } from 'camino-common/src/static/titresStatuts.js'
@@ -23,7 +23,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1989-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1989-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1989-oct01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -32,7 +32,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 points: [1, 2, 3] as unknown as ITitrePoint[],
               },
               {
-                id: 'h-cx-courdemanges-1989-oct01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1989-oct01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1989-oct01'),
                 typeId: 'dex',
                 statutId: 'acc',
@@ -48,7 +48,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             ordre: 2,
             etapes: [
               {
-                id: 'h-cx-courdemanges-1989-mut01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1989-mut01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1989-mut01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -56,7 +56,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 ordre: 2,
               },
               {
-                id: 'h-cx-courdemanges-1989-mut01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1989-mut01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1989-mut01'),
                 typeId: 'dex',
                 date: toCaminoDate('1989-02-02'),
@@ -83,7 +83,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1988-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -92,7 +92,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 points: [],
               },
               {
-                id: 'h-cx-courdemanges-1988-oct01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1988-oct01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'),
                 typeId: 'dex',
                 date: toCaminoDate('1989-01-01'),
@@ -119,7 +119,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1986-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1986-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-oct01'),
                 typeId: 'dpu',
                 date: toCaminoDate('1986-01-02'),
@@ -127,7 +127,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 ordre: 2,
               },
               {
-                id: 'h-cx-courdemanges-1986-oct01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1986-oct01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-oct01'),
                 typeId: 'dex',
                 statutId: 'acc',
@@ -143,7 +143,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             ordre: 2,
             etapes: [
               {
-                id: 'h-cx-courdemanges-1986-mut01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1986-mut01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-mut01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -152,7 +152,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 points: [1, 2, 3] as unknown as ITitrePoint[],
               },
               {
-                id: 'h-cx-courdemanges-1986-mut01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1986-mut01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-mut01'),
                 typeId: 'dex',
                 statutId: 'acc',
@@ -179,7 +179,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1986-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1986-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-oct01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -187,7 +187,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 date: toCaminoDate('1986-01-02'),
               },
               {
-                id: 'h-cx-courdemanges-1986-oct01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1986-oct01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-oct01'),
                 typeId: 'dex',
                 statutId: 'acc',
@@ -203,7 +203,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             ordre: 2,
             etapes: [
               {
-                id: 'h-cx-courdemanges-1986-mut01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1986-mut01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-mut01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -212,7 +212,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 date: toCaminoDate('1986-02-02'),
               },
               {
-                id: 'h-cx-courdemanges-1986-mut01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1986-mut01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-mut01'),
                 typeId: 'dex',
                 statutId: 'acc',
@@ -240,7 +240,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             ordre: 2,
             etapes: [
               {
-                id: 'h-cx-courdemanges-1985-mut01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1985-mut01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1985-mut01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -249,7 +249,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 points: [1, 2, 3] as unknown as ITitrePoint[],
               },
               {
-                id: 'h-cx-courdemanges-1985-mut01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1985-mut01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1985-mut01'),
                 typeId: 'dex',
                 date: toCaminoDate('1985-01-01'),
@@ -264,7 +264,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'ins',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1985-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1985-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1985-oct01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -273,7 +273,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 points: [1, 2, 3] as unknown as ITitrePoint[],
               },
               {
-                id: 'h-cx-courdemanges-1985-oct01-dex01',
+                id: newEtapeId('h-cx-courdemanges-1985-oct01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1985-oct01'),
                 typeId: 'dex',
                 statutId: 'acc',
@@ -300,7 +300,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1984-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1984-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1984-oct01'),
                 typeId: 'dpu',
                 statutId: 'rej',
@@ -309,7 +309,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 points: [1, 2, 3] as unknown as undefined,
               },
               {
-                id: newDemarcheId('h-cx-courdemanges-1984-oct01-dex01'),
+                id: newEtapeId('h-cx-courdemanges-1984-oct01-dex01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1984-oct01'),
                 date: toCaminoDate('1984-01-01'),
                 typeId: 'dex',
@@ -336,7 +336,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1983-oct01-mfr01',
+                id: newEtapeId('h-cx-courdemanges-1983-oct01-mfr01'),
                 date: toCaminoDate('1983-01-01'),
                 titreDemarcheId: newDemarcheId(newDemarcheId('h-cx-courdemanges-1983-oct01')),
                 typeId: 'mfr',
@@ -344,7 +344,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
                 ordre: 1,
                 points: [
                   {
-                    id: 'id',
+                    id: newEtapeId('id'),
                     titreEtapeId: 'h-cx-courdemanges-1983-oct01-mfr01',
                     groupe: 1,
                     contour: 1,
@@ -374,7 +374,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'ins',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-pro01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-pro01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-pro01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -390,7 +390,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'),
                 typeId: 'dpu',
                 date: toCaminoDate('1981-01-01'),
@@ -417,7 +417,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'ins',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-pro01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-pro01-dpu01'),
                 titreDemarcheId: newDemarcheId(newDemarcheId('h-cx-courdemanges-1981-pro01')),
                 date: '1981-01-01',
                 typeId: ETAPES_TYPES.publicationDeDecisionAuJORF,
@@ -432,7 +432,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'),
                 typeId: 'dpu',
                 date: toCaminoDate('1981-01-01'),
@@ -459,7 +459,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'ins',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-mut01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-mut01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-mut01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -475,7 +475,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'),
                 typeId: 'dpu',
                 date: toCaminoDate('1981-01-01'),
@@ -505,7 +505,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
               ordre: 2,
               etapes: [
                 {
-                  id: 'h-cx-courdemanges-1981-pro01-dpu01',
+                  id: newEtapeId('h-cx-courdemanges-1981-pro01-dpu01'),
                   date: toCaminoDate('1981-01-01'),
                   titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-pro01'),
                   typeId: 'aac',
@@ -525,7 +525,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
               ordre: 1,
               etapes: [
                 {
-                  id: 'h-cx-courdemanges-1981-oct01-dpu01',
+                  id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'),
                   titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'),
                   typeId: 'dpu',
                   statutId: 'acc',
@@ -558,7 +558,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             ordre: 2,
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-pro01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-pro01-dpu01'),
                 date: toCaminoDate('1981-01-01'),
                 titreDemarcheId: newDemarcheId(newDemarcheId('h-cx-courdemanges-1981-pro01')),
                 typeId: 'aac',
@@ -579,7 +579,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             ordre: 1,
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId(newDemarcheId('h-cx-courdemanges-1981-oct01')),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -611,7 +611,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1982-oct01-mfr01',
+                id: newEtapeId('h-cx-courdemanges-1982-oct01-mfr01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1982-oct01'),
                 typeId: 'mfr',
                 statutId: 'aco',
@@ -645,7 +645,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             demarcheDateFin: toCaminoDate('2018-12-31'),
             etapes: [
               {
-                id: 'h-cx-courdemanges-1982-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1982-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1982-oct01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -675,7 +675,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1982-amo01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1982-amo01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1982-amo01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -712,7 +712,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-amo01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-amo01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-amo01'),
                 typeId: 'dpu',
                 statutId: 'acc',
@@ -728,7 +728,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-pro01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-pro01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-pro01'),
                 typeId: 'dpu',
                 date: toCaminoDate('1981-01-01'),
@@ -743,7 +743,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => {
             statutId: 'acc',
             etapes: [
               {
-                id: 'h-cx-courdemanges-1981-oct01-dpu01',
+                id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'),
                 titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'),
                 date: toCaminoDate('1981-01-01'),
                 typeId: 'dpu',
@@ -764,7 +764,7 @@ describe("id de l'étape qui a un contenu", () => {
     const etape1 = titreContenuTitreEtapeFind(
       currentDate,
       { sectionId: 'arm', elementId: 'mecanisee' },
-      [{ id: newDemarcheId('demarche-id'), etapes: [{ id: 'etape-id' }] }] as ITitreDemarche[],
+      [{ id: newDemarcheId('demarche-id'), etapes: [{ id: newEtapeId('etape-id') }] }] as ITitreDemarche[],
       'val'
     )
 
@@ -775,7 +775,7 @@ describe("id de l'étape qui a un contenu", () => {
         {
           id: newDemarcheId('demarche-id'),
           statutId: 'acc',
-          etapes: [{ id: 'etape-id', statutId: 'fai' }],
+          etapes: [{ id: newEtapeId('etape-id'), statutId: 'fai' }],
         },
       ] as ITitreDemarche[],
       'val'
@@ -789,13 +789,13 @@ describe("id de l'étape qui a un contenu", () => {
       [
         {
           id: newDemarcheId('demarche-id'),
-          titreId: 'titre-id',
+          titreId: newTitreId('titre-id'),
           typeId: 'pro',
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2020-01-02'),
           etapes: [
             {
-              id: 'etape-id',
+              id: newEtapeId('etape-id'),
               titreDemarcheId: newDemarcheId('demarche-id'),
               typeId: 'dpu',
               date: toCaminoDate('2020-01-01'),
@@ -820,11 +820,11 @@ describe("id de l'étape qui a un contenu", () => {
       [
         {
           id: newDemarcheId('demarche-id'),
-          titreId: 'titre-id',
+          titreId: newTitreId('titre-id'),
           typeId: 'oct',
           etapes: [
             {
-              id: 'etape-id',
+              id: newEtapeId('etape-id'),
               titreDemarcheId: newDemarcheId('demarche-id'),
               typeId: 'dpu',
               date: toCaminoDate('2020-01-03'),
@@ -835,11 +835,11 @@ describe("id de l'étape qui a un contenu", () => {
         },
         {
           id: newDemarcheId('demarche-id-2'),
-          titreId: 'titre-id',
+          titreId: newTitreId('titre-id'),
           typeId: 'pro',
           etapes: [
             {
-              id: 'etape-id-2',
+              id: newEtapeId('etape-id-2'),
               titreDemarcheId: newDemarcheId('demarche-id'),
               typeId: 'dex',
               date: toCaminoDate('2020-01-01'),
@@ -857,11 +857,11 @@ describe("id de l'étape qui a un contenu", () => {
       [
         {
           id: newDemarcheId('demarche-id'),
-          titreId: 'titre-id',
+          titreId: newTitreId('titre-id'),
           typeId: 'pro',
           etapes: [
             {
-              id: 'etape-id',
+              id: newEtapeId('etape-id'),
               titreDemarcheId: newDemarcheId('demarche-id'),
               typeId: 'dpu',
               date: toCaminoDate('2020-01-01'),
@@ -885,11 +885,11 @@ describe("id de l'étape qui a un contenu", () => {
       [
         {
           id: newDemarcheId('demarche-id'),
-          titreId: 'titre-id',
+          titreId: newTitreId('titre-id'),
           typeId: 'oct',
           etapes: [
             {
-              id: 'etape-id',
+              id: newEtapeId('etape-id'),
               titreDemarcheId: newDemarcheId('demarche-id'),
               typeId: 'mfr',
               date: toCaminoDate('2020-01-03'),
@@ -911,11 +911,11 @@ describe("id de l'étape qui a un contenu", () => {
       [
         {
           id: newDemarcheId('demarche-id'),
-          titreId: 'titre-id',
+          titreId: newTitreId('titre-id'),
           typeId: 'oct',
           etapes: [
             {
-              id: 'etape-id',
+              id: newEtapeId('etape-id'),
               titreDemarcheId: newDemarcheId('demarche-id'),
               typeId: 'mfr',
               date: toCaminoDate('2020-01-03'),
diff --git a/packages/api/src/business/titre-etape-update.ts b/packages/api/src/business/titre-etape-update.ts
index 1276c507f..331238c40 100644
--- a/packages/api/src/business/titre-etape-update.ts
+++ b/packages/api/src/business/titre-etape-update.ts
@@ -1,5 +1,6 @@
 import { titreDemarcheGet } from '../database/queries/titres-demarches.js'
 import type { DemarcheId } from 'camino-common/src/demarche.js'
+import type { EtapeId } from 'camino-common/src/etape.js'
 
 import { titresActivitesUpdate } from './processes/titres-activites-update.js'
 import { titresDemarchesPublicUpdate } from './processes/titres-demarches-public-update.js'
@@ -24,7 +25,7 @@ import { titresEtapesDepotCreate } from './processes/titres-demarches-depot-crea
 import type { UserNotNull } from 'camino-common/src/roles.js'
 import type { Pool } from 'pg'
 
-const titreEtapeUpdate = async (pool: Pool, titreEtapeId: string | null, titreDemarcheId: DemarcheId, user: UserNotNull) => {
+const titreEtapeUpdate = async (pool: Pool, titreEtapeId: EtapeId | null, titreDemarcheId: DemarcheId, user: UserNotNull) => {
   try {
     console.info()
     console.info('- - -')
@@ -42,13 +43,13 @@ const titreEtapeUpdate = async (pool: Pool, titreEtapeId: string | null, titreDe
       throw new Error(`la démarche ${titreDemarche} n'existe pas`)
     }
 
-    const titresEtapesOrdreUpdated = await titresEtapesOrdreUpdate(user, titreDemarcheId)
+    const titresEtapesOrdreUpdated = await titresEtapesOrdreUpdate(pool, user, titreDemarcheId)
 
     const titresEtapesHeritagePropsUpdated = await titresEtapesHeritagePropsUpdate(user, [titreDemarcheId])
-    const titresEtapesHeritageContenuUpdated = await titresEtapesHeritageContenuUpdate(user, titreDemarcheId)
+    const titresEtapesHeritageContenuUpdated = await titresEtapesHeritageContenuUpdate(pool, user, titreDemarcheId)
 
     const titreId = titreDemarche.titreId
-    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate(titreId)
+    const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate(pool, titreId)
     const titresDemarchesOrdreUpdated = await titresDemarchesOrdreUpdate([titreId])
     const [titresDemarchesDatesUpdated = []] = await titresDemarchesDatesUpdate(pool, [titreId])
     const titresDemarchesPublicUpdated = await titresDemarchesPublicUpdate([titreId])
diff --git a/packages/api/src/business/utils/props-titre-etapes-ids-find.test.ts b/packages/api/src/business/utils/props-titre-etapes-ids-find.test.ts
index 0c39e2138..c968c8b5b 100644
--- a/packages/api/src/business/utils/props-titre-etapes-ids-find.test.ts
+++ b/packages/api/src/business/utils/props-titre-etapes-ids-find.test.ts
@@ -1,5 +1,5 @@
 import { contenusTitreEtapesIdsFind } from './props-titre-etapes-ids-find.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newTitreId } from '../../database/models/_format/id-create.js'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { describe, test, expect } from 'vitest'
 
@@ -12,7 +12,7 @@ describe("liste des propriétés et les étapes qui en sont à l'origine", () =>
         [
           {
             id: newDemarcheId('demarche-id'),
-            titreId: 'titre-id',
+            titreId: newTitreId('titre-id'),
             typeId: 'oct',
             statutId: 'acc',
             etapes: [],
diff --git a/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts b/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts
index cfec1515a..3687e31e3 100644
--- a/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts
+++ b/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts
@@ -3,6 +3,7 @@ import { titreDemarcheStatutIdFind } from '../rules/titre-demarche-statut-id-fin
 import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { titrePhasesFind } from '../rules/titre-phases-find.js'
 import { CaminoDate } from 'camino-common/src/date.js'
+import { titreEtapeForMachineValidator } from '../rules-demarches/machine-common.js'
 
 /**
  * Filtre les étapes antérieures à une date
@@ -31,7 +32,8 @@ export const titreDemarchesEtapesRebuild = (date: CaminoDate, titreDemarches: IT
 
       titreDemarche.etapes = titreEtapesFiltered
 
-      titreDemarche.statutId = titreDemarcheStatutIdFind(titreDemarche.typeId, titreDemarche.etapes, titreTypeId, titreDemarche.id)
+      const etapes = titreDemarche.etapes.map(etape => titreEtapeForMachineValidator.parse(etape))
+      titreDemarche.statutId = titreDemarcheStatutIdFind(titreDemarche.typeId, etapes, titreTypeId, titreDemarche.id)
 
       acc.push(titreDemarche)
     }
diff --git a/packages/api/src/business/utils/titre-etape-heritage-contenu-find.ts b/packages/api/src/business/utils/titre-etape-heritage-contenu-find.ts
index 6079e6e7e..a188ce3d9 100644
--- a/packages/api/src/business/utils/titre-etape-heritage-contenu-find.ts
+++ b/packages/api/src/business/utils/titre-etape-heritage-contenu-find.ts
@@ -3,7 +3,12 @@ import { IContenuValeur, Index, ITitreEtape } from '../../types.js'
 import { DeepReadonly } from 'camino-common/src/typescript-tools.js'
 import { Section } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.js'
 
-export const heritageContenuFind = (sectionId: string, elementId: string, titreEtape: Pick<ITitreEtape, 'contenu' | 'heritageContenu'>, prevTitreEtape?: ITitreEtape | null) => {
+export const heritageContenuFind = (
+  sectionId: string,
+  elementId: string,
+  titreEtape: Pick<ITitreEtape, 'contenu' | 'heritageContenu'>,
+  prevTitreEtape?: Pick<ITitreEtape, 'id' | 'contenu' | 'heritageContenu'> | null
+) => {
   let hasChanged = false
   let value = (titreEtape.contenu && titreEtape.contenu[sectionId] && titreEtape.contenu[sectionId][elementId]) as IContenuValeur
 
@@ -45,7 +50,7 @@ export const heritageContenuFind = (sectionId: string, elementId: string, titreE
 }
 
 export const titreEtapeHeritageContenuFind = (
-  titreEtapes: ITitreEtape[],
+  titreEtapes: Omit<ITitreEtape, 'titreDemarcheId'>[],
   titreEtape: Pick<ITitreEtape, 'id' | 'contenu' | 'heritageContenu'>,
   etapeSectionsDictionary: Index<DeepReadonly<Section[]>>
 ) => {
diff --git a/packages/api/src/business/utils/titre-etape-heritage-props-find.test.ts b/packages/api/src/business/utils/titre-etape-heritage-props-find.test.ts
index 45d323c11..f5ec08b6c 100644
--- a/packages/api/src/business/utils/titre-etape-heritage-props-find.test.ts
+++ b/packages/api/src/business/utils/titre-etape-heritage-props-find.test.ts
@@ -4,6 +4,7 @@ import { titreEtapeHeritagePropsFind, titreEtapePropsIds } from './titre-etape-h
 
 import { objectClone } from '../../tools/index.js'
 import { describe, test, expect } from 'vitest'
+import { newEtapeId } from '../../database/models/_format/id-create.js'
 
 /* eslint-disable @typescript-eslint/ban-ts-comment */
 
@@ -44,7 +45,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
     titreEtape.heritageProps![propId].actif = true
     // @ts-ignore
     titreEtape[propId] = etapeValeur
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
 
     const titreEtapeNew = objectClone(titreEtape) as ITitreEtape
     // @ts-ignore
@@ -70,7 +71,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
 
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
     titreEtape.heritageProps!.titulaires.actif = true
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
 
     expect(titreEtapeHeritagePropsFind(titreEtape, titreEtapePrecedente)).toEqual({
@@ -93,7 +94,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
 
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
     titreEtape.heritageProps![propId].actif = true
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
     // @ts-ignore
     titreEtape[propId] = [{ id: 'haha' }, { id: 'toto' }]
@@ -121,7 +122,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
 
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
     titreEtape.heritageProps!.substances.actif = true
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
     titreEtape.substances = ['nacl', 'arge']
 
@@ -148,7 +149,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
     titreEtape.heritageProps!.titulaires.actif = true
     titreEtape.titulaires = [{ id: 'haha' }, { id: 'toto' }] as IEntreprise[]
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
 
     const titreEtapeNew = objectClone(titreEtape) as ITitreEtape
@@ -172,7 +173,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
     } as ITitreEtape
 
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
 
     const titreEtapeNew = objectClone(titreEtape) as ITitreEtape
@@ -197,7 +198,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
 
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
     titreEtape.heritageProps!.points.actif = true
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
 
     expect(titreEtapeHeritagePropsFind(titreEtape, titreEtapePrecedente)).toEqual({
@@ -222,7 +223,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
 
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
     titreEtape.heritageProps!.points.actif = true
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtape.points = [
       { id: '3', coordonnees: { x: 1, y: 2 } },
       { id: '4', coordonnees: { x: 2, y: 4 } },
@@ -253,7 +254,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
     titreEtape.heritageProps!.surface.actif = true
     titreEtape.incertitudes = {}
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
 
     const newTitreEtape = objectClone(titreEtape) as ITitreEtape
@@ -278,7 +279,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
     titreEtape.heritageProps!.surface.actif = true
     titreEtape.incertitudes = { surface: true }
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
 
     const newTitreEtape = objectClone(titreEtape) as ITitreEtape
@@ -304,7 +305,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
     const titreEtape = objectClone(titreEtapePrecedente) as ITitreEtape
     titreEtape.heritageProps!.surface.actif = true
     titreEtape.incertitudes = null
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
 
     const newTitreEtape = objectClone(titreEtape) as ITitreEtape
@@ -328,7 +329,7 @@ describe('retourne l’étape en fonction de son héritage', () => {
 
     const titreEtape = objectClone(titreEtapePrecedente)
     titreEtape.heritageProps!.surface.actif = true
-    titreEtape.id = 'titreEtapeId'
+    titreEtape.id = newEtapeId('titreEtapeId')
     titreEtape.incertitudes = { date: true }
 
     titreEtapePropsIds.forEach(prop => (titreEtape.heritageProps![prop].etapeId = titreEtapePrecedente.id))
diff --git a/packages/api/src/business/utils/titre-etapes-sort.test.ts b/packages/api/src/business/utils/titre-etapes-sort.test.ts
index 8862ef586..2341121f6 100644
--- a/packages/api/src/business/utils/titre-etapes-sort.test.ts
+++ b/packages/api/src/business/utils/titre-etapes-sort.test.ts
@@ -1,22 +1,21 @@
-import { ITitreEtape } from '../../types.js'
-
 import { titreEtapesSortAscByDate, titreEtapesSortAscByOrdre, titreEtapesSortDescByOrdre } from './titre-etapes-sort.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId } from '../../database/models/_format/id-create.js'
 import { vi, describe, test, expect } from 'vitest'
 import { toCaminoDate } from 'camino-common/src/date.js'
 import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes.js'
 import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes.js'
 import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes.js'
+import { TitreEtapeForMachine } from '../rules-demarches/machine-common.js'
 
 const titreEtapesSortedDescResult = [
   { typeId: 'dpu', ordre: 2, date: '1988-03-11' },
   { typeId: 'dex', ordre: 1, date: '1988-03-06' },
-] as ITitreEtape[]
+] as TitreEtapeForMachine[]
 
 const titreEtapesSortedAsc = [
   { typeId: 'dex', ordre: 1, date: '1988-03-06' },
   { typeId: 'dpu', ordre: 2, date: '1988-03-11' },
-] as ITitreEtape[]
+] as TitreEtapeForMachine[]
 
 const titreEtapesSortedDesc = titreEtapesSortedAsc.slice().reverse()
 
@@ -49,22 +48,26 @@ describe('trie les étapes', () => {
   })
 
   test('des étapes avec les mêmes dates organisées par ordre décroissant sont triées par ordre croissant', () => {
-    const titreEtapesMemesDatesOrdreDesc: Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'titreDemarcheId'>[] = [
+    const titreEtapesMemesDatesOrdreDesc: TitreEtapeForMachine[] = [
       {
-        id: '1',
+        id: newEtapeId('1'),
         typeId: 'dex',
         ordre: 2,
         date: toCaminoDate('1988-03-06'),
-        titreDemarcheId: newDemarcheId(),
         statutId: 'fai',
+        communes: [],
+        contenu: {},
+        surface: null,
       },
       {
-        id: '2',
+        id: newEtapeId('2'),
         typeId: 'dpu',
         ordre: 1,
         date: toCaminoDate('1988-03-06'),
-        titreDemarcheId: newDemarcheId(),
         statutId: 'fav',
+        communes: [],
+        contenu: {},
+        surface: null,
       },
     ]
 
@@ -75,30 +78,36 @@ describe('trie les étapes', () => {
 
   test('des étapes avec les mêmes dates sont triées par ordre de type croissant', () => {
     const titreDemarcheId = newDemarcheId('1')
-    const titreEtapesMemesDatesOrdreEtapesTypesDesc: Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'titreDemarcheId'>[] = [
+    const titreEtapesMemesDatesOrdreEtapesTypesDesc: TitreEtapeForMachine[] = [
       {
-        id: '1',
+        id: newEtapeId('1'),
         typeId: ETAPES_TYPES.initiationDeLaDemarcheDeRetrait,
         ordre: 2,
         date: toCaminoDate('1988-03-06'),
-        titreDemarcheId,
         statutId: 'fav',
+        communes: [],
+        contenu: {},
+        surface: null,
       },
       {
-        id: '2',
+        id: newEtapeId('2'),
         typeId: ETAPES_TYPES.classementSansSuite,
         ordre: 2,
         date: toCaminoDate('1988-03-06'),
-        titreDemarcheId,
         statutId: 'fav',
+        communes: [],
+        contenu: {},
+        surface: null,
       },
       {
-        id: '3',
+        id: newEtapeId('3'),
         typeId: ETAPES_TYPES.decisionAdministrative,
         ordre: 2,
         date: toCaminoDate('1988-03-06'),
-        titreDemarcheId,
         statutId: 'fav',
+        communes: [],
+        contenu: {},
+        surface: null,
       },
     ]
     expect(titreEtapesSortAscByDate(titreEtapesMemesDatesOrdreEtapesTypesDesc, titreDemarcheId, DEMARCHES_TYPES_IDS.Retrait, TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX)).toMatchObject([
@@ -107,47 +116,53 @@ describe('trie les étapes', () => {
         ordre: 2,
         date: '1988-03-06',
         statutId: 'fav',
-        titreDemarcheId,
       },
       {
         typeId: ETAPES_TYPES.decisionAdministrative,
         ordre: 2,
         date: '1988-03-06',
         statutId: 'fav',
-        titreDemarcheId,
       },
       {
         typeId: ETAPES_TYPES.classementSansSuite,
         ordre: 2,
         date: '1988-03-06',
         statutId: 'fav',
-        titreDemarcheId,
       },
     ])
   })
 
   test('tri selon l’arbre si les étapes ont la même date', () => {
-    const etapes: Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'titreDemarcheId'>[] = [
+    const etapes: TitreEtapeForMachine[] = [
       {
-        id: '1',
+        id: newEtapeId('1'),
         typeId: 'pfd',
+        ordre: 1,
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        communes: [],
+        contenu: {},
+        surface: null,
       },
       {
-        id: '2',
+        id: newEtapeId('2'),
         typeId: 'mfr',
+        ordre: 2,
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        communes: [],
+        contenu: {},
+        surface: null,
       },
       {
-        id: '3',
+        id: newEtapeId('3'),
         typeId: 'mdp',
+        ordre: 3,
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        surface: null,
+        communes: [],
+        contenu: {},
       },
     ]
 
@@ -158,29 +173,38 @@ describe('trie les étapes', () => {
   })
 
   test("retourne une erreur si le type d'étape est absent dans la définition", () => {
-    const etapes: Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'titreDemarcheId'>[] = [
+    const etapes: TitreEtapeForMachine[] = [
       {
-        id: '1',
+        id: newEtapeId('1'),
         typeId: 'mcr',
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        surface: null,
+        ordre: 1,
+        communes: [],
+        contenu: null,
       },
       {
         // eslint-disable-next-line @typescript-eslint/ban-ts-comment
         // @ts-ignore
         typeId: 'bof',
-        id: '2',
+        id: newEtapeId('2'),
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        surface: null,
+        ordre: 2,
+        communes: [],
+        contenu: null,
       },
       {
-        id: '3',
+        id: newEtapeId('3'),
         typeId: 'vfd',
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        surface: null,
+        ordre: 3,
+        communes: [],
+        contenu: null,
       },
     ]
 
@@ -190,42 +214,57 @@ describe('trie les étapes', () => {
   })
 
   test('utilise l’id pour trier des étapes totalement identiques', () => {
-    const secondMcd: Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'titreDemarcheId'> = {
-      id: 'mcd2',
+    const secondMcd: TitreEtapeForMachine = {
+      id: newEtapeId('mcd2'),
       typeId: 'mcd',
       date: toCaminoDate('2020-01-01'),
       statutId: 'fai',
-      titreDemarcheId: newDemarcheId(),
+      surface: null,
+      ordre: 5,
+      contenu: {},
+      communes: [],
     }
 
-    const etapes: Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'titreDemarcheId'>[] = [
+    const etapes: TitreEtapeForMachine[] = [
       {
-        id: 'mfr',
+        id: newEtapeId('mfr'),
+        ordre: 1,
         typeId: 'mfr',
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        surface: null,
+        contenu: {},
+        communes: [],
       },
       {
-        id: 'mdp',
+        id: newEtapeId('mdp'),
+        ordre: 2,
         typeId: 'mdp',
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        surface: null,
+        contenu: {},
+        communes: [],
       },
       {
-        id: 'mcd',
+        id: newEtapeId('mcd'),
+        ordre: 3,
         typeId: 'mcd',
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        surface: null,
+        contenu: {},
+        communes: [],
       },
       {
-        id: 'rcd',
+        id: newEtapeId('rcd'),
+        ordre: 4,
         typeId: 'rcd',
         date: toCaminoDate('2020-01-01'),
         statutId: 'fai',
-        titreDemarcheId: newDemarcheId(),
+        surface: null,
+        contenu: {},
+        communes: [],
       },
       secondMcd,
     ]
diff --git a/packages/api/src/business/utils/titre-etapes-sort.ts b/packages/api/src/business/utils/titre-etapes-sort.ts
index d173378b3..efab1ddc2 100644
--- a/packages/api/src/business/utils/titre-etapes-sort.ts
+++ b/packages/api/src/business/utils/titre-etapes-sort.ts
@@ -1,6 +1,6 @@
 import { ITitreEtape } from '../../types.js'
-import { demarcheDefinitionFind, IDemarcheDefinitionRestrictions, isDemarcheDefinitionMachine } from '../rules-demarches/definitions.js'
-import { toMachineEtapes } from '../rules-demarches/machine-common.js'
+import { demarcheDefinitionFind } from '../rules-demarches/definitions.js'
+import { TitreEtapeForMachine, toMachineEtapes } from '../rules-demarches/machine-common.js'
 import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js'
 import { getEtapesTDE } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index.js'
@@ -13,19 +13,12 @@ export const titreEtapesSortDescByOrdre = <T extends Pick<ITitreEtape, 'ordre'>>
 export const titreEtapesSortAscByOrdre = <T extends Pick<ITitreEtape, 'ordre'>>(titreEtapes: T[]): T[] => titreEtapes.slice().sort((a, b) => a.ordre! - b.ordre!)
 
 // classe les étapes selon leur dates, ordre et etapesTypes.ordre le cas échéant
-export const titreEtapesSortAscByDate = <T extends Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'titreDemarcheId'>>(
-  titreEtapes: T[],
-  demarcheId: DemarcheId,
-  demarcheTypeId: DemarcheTypeId,
-  titreTypeId: TitreTypeId
-): T[] => {
-  let demarcheDefinitionRestrictions = undefined as IDemarcheDefinitionRestrictions | undefined
-
+export const titreEtapesSortAscByDate = <T extends TitreEtapeForMachine>(titreEtapes: T[], demarcheId: DemarcheId, demarcheTypeId: DemarcheTypeId, titreTypeId: TitreTypeId): T[] => {
   const demarcheDefinition = demarcheDefinitionFind(titreTypeId, demarcheTypeId, titreEtapes, demarcheId)
-  if (isDemarcheDefinitionMachine(demarcheDefinition)) {
+  if (demarcheDefinition) {
     const etapes = demarcheDefinition.machine.orderMachine(toMachineEtapes(titreEtapes))
     if (!demarcheDefinition.machine.isEtapesOk(etapes)) {
-      console.error(`impossible de trouver un ordre pour la démarche '${titreEtapes[0]?.titreDemarcheId}' où ces étapes sont valides ${JSON.stringify(etapes)}`)
+      console.error(`impossible de trouver un ordre pour la démarche '${demarcheId}' où ces étapes sont valides ${JSON.stringify(etapes)}`)
     }
 
     const result: T[] = []
@@ -39,8 +32,6 @@ export const titreEtapesSortAscByDate = <T extends Pick<ITitreEtape, 'id' | 'ord
 
     return result
   } else {
-    demarcheDefinitionRestrictions = demarcheDefinition?.restrictions
-
     return titreEtapes.slice().sort((a, b) => {
       const dateA = new Date(a.date)
       const dateB = new Date(b.date)
@@ -48,50 +39,6 @@ export const titreEtapesSortAscByDate = <T extends Pick<ITitreEtape, 'id' | 'ord
       if (dateA < dateB) return -1
       if (dateA > dateB) return 1
 
-      // si les deux étapes ont la même date
-
-      // on utilise l'arbre pour trouver quelle étape provoque l’autre
-
-      if (demarcheDefinition && demarcheDefinitionRestrictions) {
-        const bRestriction = demarcheDefinitionRestrictions[b.typeId]
-
-        if (!bRestriction) {
-          console.error(`${demarcheId}: impossible de trier l’étape car son type ${b.typeId} n’existe pas dans les définitions`)
-
-          return -1
-        }
-
-        const aRestriction = demarcheDefinitionRestrictions[a.typeId]
-
-        if (!aRestriction) {
-          console.error(`${demarcheId}: impossible de trier l’étape car son type ${a.typeId} n’existe pas dans les définitions`)
-
-          return -1
-        }
-
-        const bJusteApresA = bRestriction.justeApres.flat(2).find(b => b.etapeTypeId === a.typeId)
-
-        const aJusteApresB = aRestriction.justeApres.flat(2).find(a => a.etapeTypeId === b.typeId)
-
-        if (bJusteApresA && !aJusteApresB) {
-          return -1
-        }
-
-        if (aJusteApresB && !bJusteApresA) {
-          return 1
-        }
-
-        if (aRestriction.final) {
-          return 1
-        }
-
-        if (bRestriction.final) {
-          return -1
-        }
-      }
-
-      // on utilise l'ordre du type d'étape
-
       const etapes = getEtapesTDE(titreTypeId, demarcheTypeId)
 
       const aTypeIndex = etapes.findIndex(e => e === a.typeId)
diff --git a/packages/api/src/business/utils/titre-slug-and-relations-update.ts b/packages/api/src/business/utils/titre-slug-and-relations-update.ts
index 945afd601..c82bab9df 100644
--- a/packages/api/src/business/utils/titre-slug-and-relations-update.ts
+++ b/packages/api/src/business/utils/titre-slug-and-relations-update.ts
@@ -16,6 +16,7 @@ import { titrePointReferenceUpdate, titrePointUpdate } from '../../database/quer
 import { titreActiviteUpdate } from '../../database/queries/titres-activites.js'
 import { UserNotNull } from 'camino-common/src/roles'
 import { getDomaineId, getTitreTypeType } from 'camino-common/src/static/titresTypes.js'
+import { TitreId } from 'camino-common/src/titres.js'
 
 const titreSlugFind = (titre: ITitre) => {
   const { typeId, nom } = titre
@@ -48,7 +49,7 @@ const titreActiviteSlugFind = (titreActivite: ITitreActivite, titre: ITitre) =>
 interface ITitreRelation<T extends string | DemarcheId = string> {
   name: string
   slugFind: (...args: any[]) => string
-  update: ((id: T, element: { slug: string }, user: UserNotNull) => Promise<{ id: T }>) | ((id: T, element: { slug: string }, user: UserNotNull, titreId: string) => Promise<{ id: T }>)
+  update: ((id: T, element: { slug: string }, user: UserNotNull) => Promise<{ id: T }>) | ((id: T, element: { slug: string }, user: UserNotNull, titreId: TitreId) => Promise<{ id: T }>)
   relations?: ITitreRelation[]
 }
 
@@ -61,6 +62,7 @@ const titreRelations: (ITitreRelation<DemarcheId> | ITitreRelation)[] = [
       {
         name: 'etapes',
         slugFind: titreDemarcheEtapeSlugFind,
+        // @ts-ignore
         update: titreEtapeUpdate,
         relations: [
           {
@@ -86,7 +88,7 @@ const titreRelations: (ITitreRelation<DemarcheId> | ITitreRelation)[] = [
   },
 ]
 
-const relationsSlugsUpdate = async (parent: any, relations: (ITitreRelation<DemarcheId> | ITitreRelation)[], titreId: string): Promise<boolean> => {
+const relationsSlugsUpdate = async (parent: any, relations: (ITitreRelation<DemarcheId> | ITitreRelation)[], titreId: TitreId): Promise<boolean> => {
   let hasChanged = false
   for (const relation of relations) {
     for (const element of parent[relation.name]) {
diff --git a/packages/api/src/business/validations/titre-demarche-etat-validate.test.ts b/packages/api/src/business/validations/titre-demarche-etat-validate.test.ts
index 5f16aac3d..44fd7a786 100644
--- a/packages/api/src/business/validations/titre-demarche-etat-validate.test.ts
+++ b/packages/api/src/business/validations/titre-demarche-etat-validate.test.ts
@@ -1,16 +1,16 @@
 import { IDemarcheType, ITitre, ITitreEtape, ITitreType } from '../../types.js'
 
 import { titreDemarcheUpdatedEtatValidate } from './titre-demarche-etat-validate.js'
-import { newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newEtapeId } from '../../database/models/_format/id-create.js'
 import { EtapesTypesEtapesStatuts } from 'camino-common/src/static/etapesTypesEtapesStatuts.js'
-import { describe, test, expect } from 'vitest'
+import { describe, test, expect, vi } from 'vitest'
 import { toCaminoDate } from 'camino-common/src/date.js'
+import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
 
-const currentDate = toCaminoDate('2023-04-06')
+console.warn = vi.fn()
 describe('teste titreDemarcheUpdatedEtatValidate', () => {
   test('ajoute une étape à une démarche vide', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct' } as IDemarcheType,
       {
         typeId: 'arm',
@@ -20,7 +20,7 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
         } as unknown as ITitreType,
         demarches: [{ typeId: 'oct' }],
       } as ITitre,
-      { typeId: 'mfr', date: '2030-01-01' } as ITitreEtape,
+      { typeId: 'mfr', date: '2030-01-01' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
       newDemarcheId(),
       null
     )
@@ -30,7 +30,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
 
   test('ajoute une étape à une démarche qui contient déjà une étape', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct' } as IDemarcheType,
       {
         typeId: 'arm',
@@ -40,10 +39,10 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
         } as unknown as ITitreType,
         demarches: [{ typeId: 'pro' }, { typeId: 'oct' }],
       } as ITitre,
-      { typeId: 'mdp', statutId: 'fai', date: '2022-05-04' } as ITitreEtape,
+      { id: newEtapeId(), typeId: 'mdp', statutId: 'fai', date: toCaminoDate('2022-05-04'), communes: null, contenu: null, ordre: 1, surface: null },
       newDemarcheId(),
 
-      [{ id: '1', typeId: 'mfr', statutId: 'fai', date: '2022-05-03' }] as ITitreEtape[]
+      [{ id: newEtapeId('1'), typeId: 'mfr', statutId: 'fai', date: toCaminoDate('2022-05-03'), communes: null, contenu: null, ordre: 1, surface: null }]
     )
 
     expect(valid).toHaveLength(0)
@@ -51,7 +50,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
 
   test('modifie une étape à une démarche', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct' } as IDemarcheType,
       {
         typeId: 'arm',
@@ -62,17 +60,21 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
         demarches: [{ typeId: 'oct' }],
       } as ITitre,
       {
-        id: '1',
+        id: newEtapeId('1'),
         typeId: 'mfr',
         statutId: 'fai',
-        date: '2022-05-04',
-      } as ITitreEtape,
+        date: toCaminoDate('2022-05-04'),
+        communes: null,
+        contenu: null,
+        ordre: 1,
+        surface: null,
+      },
       newDemarcheId(),
 
       [
-        { id: '1', typeId: 'mfr', date: '2022-05-03', statutId: 'fai' },
-        { id: '2', typeId: 'mdp', date: '2022-05-04', statutId: 'fai' },
-      ] as ITitreEtape[]
+        { id: newEtapeId('1'), typeId: 'mfr', date: toCaminoDate('2022-05-03'), statutId: 'fai', communes: null, contenu: null, ordre: 1, surface: null },
+        { id: newEtapeId('2'), typeId: 'mdp', date: toCaminoDate('2022-05-04'), statutId: 'fai', communes: null, contenu: null, ordre: 2, surface: null },
+      ]
     )
 
     expect(valid).toHaveLength(0)
@@ -80,7 +82,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
 
   test('l’ajout d’une étape d’une démarche historique est valide', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct' } as IDemarcheType,
       {
         typeId: 'arm',
@@ -90,10 +91,10 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
         } as unknown as ITitreType,
         demarches: [{ typeId: 'oct' }],
       } as ITitre,
-      { id: '1', typeId: 'mfr' } as ITitreEtape,
+      { id: '1', typeId: 'mfr' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
       newDemarcheId(),
 
-      [{ id: '1', typeId: 'mfr', date: '2000-01-01' }] as ITitreEtape[],
+      [{ id: '1', typeId: 'mfr', date: '2000-01-01' }] as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>[],
       false
     )
 
@@ -102,7 +103,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
 
   test('l’ajout d’une étape d’une démarche sans étape est valide', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct' } as IDemarcheType,
       {
         typeId: 'arm',
@@ -112,10 +112,10 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
         } as unknown as ITitreType,
         demarches: [{ typeId: 'oct' }],
       } as ITitre,
-      { id: '1', typeId: 'mfr' } as ITitreEtape,
+      { id: '1', typeId: 'mfr' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
       newDemarcheId(),
 
-      [] as ITitreEtape[]
+      []
     )
 
     expect(valid).toHaveLength(0)
@@ -124,7 +124,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
   test("retourne une erreur si la démarche en cours de modification n'existe pas", () => {
     expect(() =>
       titreDemarcheUpdatedEtatValidate(
-        currentDate,
         { id: 'oct' } as IDemarcheType,
         {
           typeId: 'arm',
@@ -134,16 +133,15 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
           } as unknown as ITitreType,
           demarches: [{ typeId: 'pro' }],
         } as ITitre,
-        { id: '1', typeId: 'mfr' } as ITitreEtape,
+        { id: '1', typeId: 'mfr' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
         newDemarcheId(),
 
-        [] as ITitreEtape[]
+        []
       )
     ).toThrow()
 
     expect(() =>
       titreDemarcheUpdatedEtatValidate(
-        currentDate,
         { id: 'oct' } as IDemarcheType,
         {
           typeId: 'arm',
@@ -152,17 +150,16 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
             contenuIds: [],
           } as unknown as ITitreType,
         } as ITitre,
-        { id: '1', typeId: 'mfr' } as ITitreEtape,
+        { id: '1', typeId: 'mfr' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
         newDemarcheId(),
 
-        [] as ITitreEtape[]
+        []
       )
     ).toThrow()
   })
 
   test('supprime une étape', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct' } as IDemarcheType,
       {
         typeId: 'arm',
@@ -172,19 +169,18 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
         } as unknown as ITitreType,
         demarches: [{ typeId: 'oct' }],
       } as ITitre,
-      { id: '1', typeId: 'mfr' } as ITitreEtape,
+      { id: '1', typeId: 'mfr' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
       newDemarcheId(),
 
-      [{ id: '1', typeId: 'mfr' }] as ITitreEtape[],
+      [{ id: '1', typeId: 'mfr' }] as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>[],
       true
     )
 
     expect(valid).toHaveLength(0)
   })
 
-  test("ajoute une étape sans statut à une démarche sans arbre d'instruction", () => {
+  test('ajoute une étape sans statut à une démarche sans machine', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct', nom: 'oct' } as IDemarcheType,
       {
         typeId: 'arm',
@@ -203,16 +199,15 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
           },
         ],
       } as ITitre,
-      { typeId: 'mfr', date: '1030-01-01' } as ITitreEtape,
+      { typeId: 'mfr', date: '1030-01-01' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
       newDemarcheId()
     )
 
     expect(valid).toHaveLength(0)
   })
 
-  test("ajoute une étape à une démarche sans arbre d'instruction", () => {
+  test('ajoute une étape à une démarche sans machine', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct', nom: 'oct' } as IDemarcheType,
       {
         typeId: 'arm',
@@ -231,7 +226,7 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
           },
         ],
       } as ITitre,
-      { typeId: 'mfr', date: '1030-01-01', statutId: 'fai' } as ITitreEtape,
+      { typeId: 'mfr', date: '1030-01-01', statutId: 'fai' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
       newDemarcheId()
     )
 
@@ -240,7 +235,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
 
   test('ajoute une demande en construction à une démarche vide', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct' } as IDemarcheType,
       {
         typeId: 'axm',
@@ -250,7 +244,7 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
         } as unknown as ITitreType,
         demarches: [{ typeId: 'oct' }],
       } as ITitre,
-      { typeId: 'mfr', statutId: 'aco', date: '2030-01-01' } as ITitreEtape,
+      { typeId: 'mfr', statutId: 'aco', date: '2030-01-01' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
       newDemarcheId()
     )
 
@@ -259,7 +253,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
 
   test('ajoute une demande en construction à une démarche qui contient déjà une étape', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct' } as IDemarcheType,
       {
         typeId: 'axm',
@@ -269,10 +262,10 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
         } as unknown as ITitreType,
         demarches: [{ typeId: 'oct' }],
       } as ITitre,
-      { typeId: 'mfr', statutId: 'aco' } as ITitreEtape,
+      { typeId: 'mfr', statutId: 'aco' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
       newDemarcheId(),
 
-      [{ id: '1', typeId: 'dae', statutId: 'exe' }] as ITitreEtape[]
+      [{ id: '1', typeId: 'dae', statutId: 'exe' }] as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>[]
     )
 
     expect(valid).toHaveLength(0)
@@ -280,7 +273,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
 
   test('modifie une demande en construction à une démarche', () => {
     const valid = titreDemarcheUpdatedEtatValidate(
-      currentDate,
       { id: 'oct' } as IDemarcheType,
       {
         typeId: 'axm',
@@ -290,13 +282,13 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
         } as unknown as ITitreType,
         demarches: [{ typeId: 'oct' }],
       } as ITitre,
-      { id: '1', typeId: 'mfr', statutId: 'aco' } as ITitreEtape,
+      { id: '1', typeId: 'mfr', statutId: 'aco' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
       newDemarcheId(),
 
       [
         { id: '1', typeId: 'mfr', statutId: 'aco' },
         { id: '2', typeId: 'dae' },
-      ] as ITitreEtape[]
+      ] as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>[]
     )
 
     expect(valid).toHaveLength(0)
@@ -305,7 +297,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
   test('ne peut pas ajouter une 2ème demande en construction à une démarche', () => {
     expect(
       titreDemarcheUpdatedEtatValidate(
-        currentDate,
         { id: 'oct' } as IDemarcheType,
         {
           typeId: 'axm',
@@ -315,13 +306,13 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
           } as unknown as ITitreType,
           demarches: [{ typeId: 'oct' }],
         } as ITitre,
-        { id: '3', typeId: 'mfr', statutId: 'aco' } as ITitreEtape,
+        { id: '3', typeId: 'mfr', statutId: 'aco' } as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>,
         newDemarcheId(),
 
         [
           { id: '1', typeId: 'mfr', statutId: 'aco' },
           { id: '2', typeId: 'dae' },
-        ] as ITitreEtape[]
+        ] as Pick<Required<ITitreEtape>, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId' | 'communes'>[]
       )
     ).toContain('il y a déjà une demande en construction')
   })
@@ -329,7 +320,6 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
   test('ne peut pas ajouter étape de type inconnu sur une machine', () => {
     expect(
       titreDemarcheUpdatedEtatValidate(
-        currentDate,
         { id: 'oct' } as IDemarcheType,
         {
           typeId: 'axm',
@@ -340,26 +330,38 @@ describe('teste titreDemarcheUpdatedEtatValidate', () => {
           demarches: [{ typeId: 'oct' }],
         } as ITitre,
         {
-          typeId: 'aaa',
-          date: '2022-01-01',
+          typeId: 'aaa' as EtapeTypeId,
+          date: toCaminoDate('2022-01-01'),
           statutId: 'fai',
-        } as unknown as ITitreEtape,
+          communes: null,
+          contenu: null,
+          ordre: 1,
+          surface: null,
+        },
         newDemarcheId(),
 
         [
           {
-            id: '1',
+            id: newEtapeId('1'),
             typeId: EtapesTypesEtapesStatuts.demande.EN_CONSTRUCTION.etapeTypeId,
             statutId: EtapesTypesEtapesStatuts.demande.EN_CONSTRUCTION.etapeStatutId,
-            date: '2021-01-01',
+            date: toCaminoDate('2021-01-01'),
+            communes: null,
+            contenu: null,
+            ordre: 1,
+            surface: null,
           },
           {
-            id: '2',
+            id: newEtapeId('2'),
             typeId: EtapesTypesEtapesStatuts.decisionDeLaMissionAutoriteEnvironnementale_ExamenAuCasParCasDuProjet_.REQUIS.etapeTypeId,
             statutId: EtapesTypesEtapesStatuts.decisionDeLaMissionAutoriteEnvironnementale_ExamenAuCasParCasDuProjet_.REQUIS.etapeStatutId,
-            date: '2021-01-02',
+            date: toCaminoDate('2021-01-02'),
+            communes: null,
+            contenu: null,
+            ordre: 1,
+            surface: null,
           },
-        ] as ITitreEtape[]
+        ]
       )
     ).toContain('la démarche n’est pas valide')
   })
diff --git a/packages/api/src/business/validations/titre-demarche-etat-validate.ts b/packages/api/src/business/validations/titre-demarche-etat-validate.ts
index bb44560ee..430fed690 100644
--- a/packages/api/src/business/validations/titre-demarche-etat-validate.ts
+++ b/packages/api/src/business/validations/titre-demarche-etat-validate.ts
@@ -1,19 +1,12 @@
 // valide la date et la position de l'étape en fonction des autres étapes
-import type { ITitre, ITitreEtape, IDemarcheType, ITitreDemarche } from '../../types.js'
-
-import { demarcheDefinitionFind, IDemarcheDefinitionRestrictions, isDemarcheDefinitionMachine } from '../rules-demarches/definitions.js'
-import { contenusTitreEtapesIdsFind } from '../utils/props-titre-etapes-ids-find.js'
-import { titreEtapesSortAscByDate } from '../utils/titre-etapes-sort.js'
-import { titreEtapeEtatValidate } from './titre-etape-etat-validate.js'
-import { objectClone } from '../../tools/index.js'
-import { toMachineEtapes } from '../rules-demarches/machine-common.js'
+import type { ITitre, ITitreEtape, IDemarcheType } from '../../types.js'
+
+import { demarcheDefinitionFind } from '../rules-demarches/definitions.js'
+import { titreEtapeForMachineValidator, toMachineEtapes } from '../rules-demarches/machine-common.js'
 import { titreEtapeTypeAndStatusValidate } from './titre-etape-type-and-status-validate.js'
-import { contenuFormat } from '../../api/rest/titre-contenu.js'
-import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js'
-import { CaminoDate } from 'camino-common/src/date.js'
 import { DemarcheId } from 'camino-common/src/demarche.js'
 
-const titreDemarcheEtapesBuild = <T extends Pick<ITitreEtape, 'id'>>(titreEtape: T, suppression: boolean, titreDemarcheEtapes?: T[] | null): T[] => {
+const titreDemarcheEtapesBuild = <T extends Pick<Partial<ITitreEtape>, 'id'>>(titreEtape: T, suppression: boolean, titreDemarcheEtapes?: T[] | null): T[] => {
   if (!titreDemarcheEtapes?.length) {
     return [titreEtape]
   }
@@ -41,56 +34,14 @@ const titreDemarcheEtapesBuild = <T extends Pick<ITitreEtape, 'id'>>(titreEtape:
   return titreEtapes
 }
 
-// vérifie que  la démarche est valide par rapport aux définitions des types d'étape
-export const titreDemarcheEtatValidate = (
-  date: CaminoDate,
-  demarcheDefinitionRestrictions: IDemarcheDefinitionRestrictions,
-  demarcheTypeId: DemarcheTypeId,
-  titreDemarche: ITitreDemarche,
-  titreEtapes: Pick<ITitreEtape, 'id' | 'ordre' | 'typeId' | 'statutId' | 'date' | 'contenu' | 'titreDemarcheId'>[],
-  titre: ITitre
-) => {
-  // Si on tente d’insérer ou de modifier une étape, il faut regarder
-  // qu’on puisse la mettre avec son nouveau etapeTypeId à la nouvelle date souhaitée
-  // et que les étapes après celle-ci soient toujours possibles
-
-  titreEtapes = titreEtapesSortAscByDate(titreEtapes, titreDemarche.id, demarcheTypeId, titre.typeId)
-
-  // on copie la démarche car on va les modifier en ajoutant les étapes une à une
-  const demarche = objectClone(titreDemarche)
-
-  for (let i = 0; i < titreEtapes.length; i++) {
-    // On doit recalculer les sections de titre pour chaque étape,
-    // car elles ont peut-être été modifiées après l’étape en cours
-    const etapes = titreEtapes.slice(0, i)
-    demarche.etapes = etapes
-
-    const contenusTitreEtapesIds = contenusTitreEtapesIdsFind(date, titre.titreStatutId!, [demarche], titre.type!.contenuIds)
-
-    let contenu = null
-    if (contenusTitreEtapesIds) {
-      contenu = contenuFormat({ demarches: [demarche], contenusTitreEtapesIds })
-    }
-
-    const titreEtapeErrors = titreEtapeEtatValidate(demarcheDefinitionRestrictions, titreEtapes[i].typeId!, etapes, contenu)
-
-    if (titreEtapeErrors.length) {
-      return titreEtapeErrors
-    }
-  }
-
-  return []
-}
-
 // vérifie que la modification de la démarche
 // est valide par rapport aux définitions des types d'étape
 export const titreDemarcheUpdatedEtatValidate = (
-  date: CaminoDate,
   demarcheType: IDemarcheType,
   titre: ITitre,
-  titreEtape: Pick<ITitreEtape, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId'>,
+  titreEtape: Pick<Partial<ITitreEtape>, 'id'> & Pick<ITitreEtape, 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'communes' | 'surface'>,
   demarcheId: DemarcheId,
-  titreDemarcheEtapes?: Pick<ITitreEtape, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'titreDemarcheId'>[] | null,
+  titreDemarcheEtapes?: Pick<ITitreEtape, 'id' | 'statutId' | 'typeId' | 'date' | 'ordre' | 'contenu' | 'communes' | 'surface'>[] | null,
   suppression = false
 ): string[] => {
   let titreDemarcheEtapesNew = titreDemarcheEtapesBuild(titreEtape, suppression, titreDemarcheEtapes)
@@ -102,7 +53,7 @@ export const titreDemarcheUpdatedEtatValidate = (
   if (!titreDemarche) {
     throw new Error('le titre ne contient pas la démarche en cours de modification')
   }
-  // pas de validation pour les démarches qui n'ont pas d'arbre d’instructions
+  // pas de validation pour les démarches qui n'ont pas de machine
   if (!demarcheDefinition) {
     if (!titreEtape.statutId) {
       return []
@@ -135,31 +86,15 @@ export const titreDemarcheUpdatedEtatValidate = (
   }
 
   // vérifie que toutes les étapes existent dans l’arbre
-  if (isDemarcheDefinitionMachine(demarcheDefinition)) {
-    try {
-      const ok = demarcheDefinition.machine.isEtapesOk(demarcheDefinition.machine.orderMachine(toMachineEtapes(titreDemarcheEtapesNew)))
-      if (!ok) {
-        titreDemarchesErrors.push('la démarche n’est pas valide')
-      }
-    } catch (e) {
-      console.warn('une erreur est survenue', e)
+  try {
+    const etapes = titreDemarcheEtapesNew.map(etape => titreEtapeForMachineValidator.omit({ id: true }).partial({ ordre: true }).parse(etape))
+    const ok = demarcheDefinition.machine.isEtapesOk(demarcheDefinition.machine.orderMachine(toMachineEtapes(etapes)))
+    if (!ok) {
       titreDemarchesErrors.push('la démarche n’est pas valide')
     }
-  } else {
-    if (titreEtape.statutId) {
-      // le type d'étape correspond à la démarche et au type de titre
-      const titreEtapeTypeAndStatusErrors = titreEtapeTypeAndStatusValidate(titreEtape.typeId, titreEtape.statutId, titreDemarche.type!.etapesTypes, titreDemarche.type!.nom)
-      titreDemarchesErrors.push(...titreEtapeTypeAndStatusErrors)
-    }
-    const etapeTypeIdsValid = Object.keys(demarcheDefinition.restrictions)
-
-    const etapeInconnue = titreDemarcheEtapesNew.find(etape => !etapeTypeIdsValid.includes(etape.typeId!))
-    if (etapeInconnue) {
-      return [`l’étape ${etapeInconnue.typeId} n’existe pas dans l’arbre`]
-    }
-
-    // On vérifie que la nouvelle démarche respecte son arbre d’instructions
-    titreDemarchesErrors.push(...titreDemarcheEtatValidate(date, demarcheDefinition.restrictions, demarcheType.id, titreDemarche, titreDemarcheEtapesNew, titre))
+  } catch (e) {
+    console.warn('une erreur est survenue', e)
+    titreDemarchesErrors.push('la démarche n’est pas valide')
   }
 
   return titreDemarchesErrors
diff --git a/packages/api/src/business/validations/titre-etape-etat-validate.test.ts b/packages/api/src/business/validations/titre-etape-etat-validate.test.ts
deleted file mode 100644
index 381d7a3aa..000000000
--- a/packages/api/src/business/validations/titre-etape-etat-validate.test.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-import { ITitreEtape } from '../../types.js'
-
-import { etapesSuivantesEnAttenteGet, titreEtapeTypeIdRestrictionsFind } from './titre-etape-etat-validate.js'
-import { etatInformationsGet } from '../rules-demarches/etat-cycles.js'
-import { describe, test, expect } from 'vitest'
-describe('teste etapesSuivantesEnAttenteGet', () => {
-  test('retourne les 2 dernières étapes des chemins parallèles', () => {
-    const etapes = [{ typeId: 'mfr' }, { typeId: 'mdp' }] as ITitreEtape[]
-    const etapesEnAttente = etapesSuivantesEnAttenteGet(etapes, etapes, [], {
-      mfr: { justeApres: [] },
-      mdp: { justeApres: [] },
-      mno: {
-        justeApres: [[{ etapeTypeId: 'mfr' }, { etapeTypeId: 'mdp' }]],
-      },
-    })
-    expect(etapesEnAttente).toHaveLength(2)
-    expect(etapesEnAttente[0]).toEqual({ typeId: 'mfr' })
-    expect(etapesEnAttente[1]).toEqual({ typeId: 'mdp' })
-  })
-
-  test('retourne la dernière étape après la fusion de 2 chemins parallèles', () => {
-    const etapes = [{ typeId: 'mfr' }, { typeId: 'mcp' }, { typeId: 'mno' }] as ITitreEtape[]
-    const etapesEnAttente = etapesSuivantesEnAttenteGet(etapes, etapes, [], {
-      mfr: { justeApres: [] },
-      mcp: { justeApres: [] },
-      mno: {
-        justeApres: [[{ etapeTypeId: 'mfr' }, { etapeTypeId: 'mcp' }]],
-      },
-    })
-    expect(etapesEnAttente).toHaveLength(1)
-    expect(etapesEnAttente[0]).toEqual({ typeId: 'mno' })
-  })
-  test('retourne l’étape sur le premier chemin et l’étape sur le chemin commun', () => {
-    const etapes = [{ typeId: 'ide' }, { typeId: 'mno' }] as ITitreEtape[]
-    const etapesEnAttente = etapesSuivantesEnAttenteGet(etapes, etapes, [], {
-      ide: { separation: ['css'], justeApres: [] },
-      mno: {
-        justeApres: [[{ etapeTypeId: 'ide' }]],
-      },
-      mfr: {
-        justeApres: [[{ etapeTypeId: 'ide' }]],
-      },
-      css: {
-        justeApres: [[{ etapeTypeId: 'mno' }, { etapeTypeId: 'mfr' }]],
-      },
-    })
-    expect(etapesEnAttente).toHaveLength(2)
-    expect(etapesEnAttente[0]).toEqual({ typeId: 'ide' })
-    expect(etapesEnAttente[1]).toEqual({ typeId: 'mno' })
-  })
-  test('retourne l’étape sur la dernière étape sur le chemin commun', () => {
-    const etapes = [{ typeId: 'ide' }, { typeId: 'mno' }, { typeId: 'mfr' }, { typeId: 'css' }] as ITitreEtape[]
-    const etapesEnAttente = etapesSuivantesEnAttenteGet(etapes, etapes, [], {
-      ide: { separation: ['css'], justeApres: [] },
-      mno: {
-        justeApres: [[{ etapeTypeId: 'ide' }]],
-      },
-      mfr: {
-        justeApres: [[{ etapeTypeId: 'ide' }]],
-      },
-      css: {
-        justeApres: [[{ etapeTypeId: 'mno' }, { etapeTypeId: 'mfr' }]],
-      },
-    })
-    expect(etapesEnAttente).toHaveLength(1)
-    expect(etapesEnAttente[0]).toEqual({ typeId: 'css' })
-  })
-  test('retourne seulement l’étape "rif" dés qu’une demande d’info a commencé', () => {
-    const etapes = [{ typeId: 'vfd' }, { typeId: 'mif-mcr' }] as ITitreEtape[]
-    const etapesEnAttente = etapesSuivantesEnAttenteGet(etapes, etapes, [], {
-      vfd: { justeApres: [] },
-      ...etatInformationsGet('mif-mcr', 'rif-mcr', {
-        etapeTypeId: 'mcr',
-        separation: ['eof'],
-        justeApres: [[{ etapeTypeId: 'vfd' }]],
-      }),
-    })
-    expect(etapesEnAttente).toHaveLength(1)
-    expect(etapesEnAttente[0]).toEqual({ typeId: 'mif-mcr' })
-  })
-
-  test('retourne la dernière étape sur le chemin commun à la fin du démarche', () => {
-    const etapes = [{ typeId: 'dex' }, { typeId: 'mno' }] as ITitreEtape[]
-    const etapesEnAttente = etapesSuivantesEnAttenteGet(etapes, etapes, [], {
-      dex: { justeApres: [], separation: [] },
-      mno: {
-        justeApres: [[{ etapeTypeId: 'dex' }]],
-      },
-      mfr: {
-        justeApres: [[{ etapeTypeId: 'dex' }]],
-      },
-      mcp: {
-        justeApres: [[{ etapeTypeId: 'dex' }]],
-      },
-    })
-    expect(etapesEnAttente).toHaveLength(2)
-    expect(etapesEnAttente[0]).toEqual({ typeId: 'dex' })
-  })
-})
-
-describe('teste titreEtapeTypeIdRestrictionsFind', () => {
-  test('émet une erreur si l’étape est inconnue', () => {
-    // @ts-ignore
-    expect(() => titreEtapeTypeIdRestrictionsFind({ dex: { justeApres: [], separation: [] } }, 'aaa')).toThrowError()
-  })
-})
diff --git a/packages/api/src/business/validations/titre-etape-etat-validate.ts b/packages/api/src/business/validations/titre-etape-etat-validate.ts
deleted file mode 100644
index 7c5a50ae0..000000000
--- a/packages/api/src/business/validations/titre-etape-etat-validate.ts
+++ /dev/null
@@ -1,182 +0,0 @@
-// valide la date et la position de l'étape en fonction des autres étapes
-import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
-import { ITitreEtape, IContenu, Index } from '../../types.js'
-
-import { ITitreCondition, IContenuElementCondition, IEtapeTypeIdCondition, IDemarcheDefinitionRestrictions, IDemarcheDefinitionRestrictionsProps } from '../rules-demarches/definitions.js'
-
-const contenuConditionMatch = (condition: IContenuElementCondition, obj: Index<any> | null, keys: string[] | null = null) => {
-  // si les conditions sont testées plusieurs fois, (dans une boucle par ex)
-  // alors les clés de l'objet de condition peuvent être passées optionnellement
-  // pour ne pas les recalculer à chaque fois
-  const conditionKeys = keys || Object.keys(condition)
-
-  return conditionKeys.every(k => {
-    const contenuElementCondition = condition[k]
-
-    let contenuValeur = obj ? obj[k] : undefined
-    if (!contenuValeur) {
-      if (typeof contenuElementCondition?.valeur === 'number') {
-        contenuValeur = 0
-      } else if (typeof contenuElementCondition?.valeur === 'boolean') {
-        contenuValeur = false
-      }
-    }
-
-    switch (contenuElementCondition?.operation) {
-      case 'NOT_EQUAL':
-        return contenuElementCondition.valeur !== contenuValeur
-      default:
-        return contenuElementCondition?.valeur === contenuValeur
-    }
-  })
-}
-
-const sameContenuCheck = (conditionTitre: ITitreCondition, contenu: IContenu | null) =>
-  conditionTitre.contenu && Object.keys(conditionTitre.contenu).every(key => contenuConditionMatch(conditionTitre.contenu[key], contenu ? contenu[key] : null))
-
-const titreEtapeTypeIdRestrictionsFind = (demarcheDefinitionRestrictions: IDemarcheDefinitionRestrictions, etapeTypeId: EtapeTypeId) => {
-  const etapeTypeIdDefinitions = demarcheDefinitionRestrictions[etapeTypeId]
-
-  if (etapeTypeIdDefinitions) {
-    return etapeTypeIdDefinitions
-  }
-
-  throw new Error(`l’étape ${etapeTypeId} n’existe pas dans cet arbre d’instructions`)
-}
-
-const etapesEnAttenteGet = (etapeTypeIdDefinitions: IDemarcheDefinitionRestrictions, titreDemarcheEtapes: ITitreEtape[]) => {
-  return etapesSuivantesEnAttenteGet(titreDemarcheEtapes, titreDemarcheEtapes, [], etapeTypeIdDefinitions)
-}
-
-const etapesSuivantesEnAttenteGet = (
-  titreDemarcheEtapes: ITitreEtape[],
-  titreDemarcheEtapesSuivantes: ITitreEtape[],
-  etapesEnAttente: ITitreEtape[],
-  etapeTypeIdDefinitions: IDemarcheDefinitionRestrictions
-): ITitreEtape[] => {
-  if (!titreDemarcheEtapesSuivantes || !titreDemarcheEtapesSuivantes.length) {
-    return etapesEnAttente
-  }
-
-  const etapeCourante = titreDemarcheEtapesSuivantes.slice(0, 1)[0]
-  const etapesSuivantes = titreDemarcheEtapesSuivantes.slice(1)
-
-  if (!etapesEnAttente || !etapesEnAttente.length) {
-    return etapesSuivantesEnAttenteGet(titreDemarcheEtapes, etapesSuivantes, [etapeCourante], etapeTypeIdDefinitions)
-  }
-
-  const etapeCouranteConditions = etapeTypeIdDefinitions[etapeCourante.typeId] as IDemarcheDefinitionRestrictionsProps
-
-  // on cherche quelles étapes en attente ont permis d’atteindre cette étape
-  if (etapeCouranteConditions.justeApres) {
-    etapesEnAttente.forEach(etape => {
-      const predicatCheck = etapeCouranteConditions!.justeApres!.flat().find(c => c?.etapeTypeId === etape.typeId)
-
-      if (predicatCheck) {
-        // si cette étape a permis d’atteindre l’étape courante, alors on la remplace dans les étapes en attente
-        etapesEnAttente = etapesEnAttente.filter(e => {
-          const etapeSeparationHas = etapeTypeIdDefinitions[e.typeId]
-
-          if (etapeSeparationHas && etapeSeparationHas.separation) {
-            return !etapeSeparationHas.separation!.includes(etapeCourante.typeId!)
-          }
-
-          return e.typeId !== etape.typeId
-        })
-      }
-    })
-  }
-
-  if (etapeCouranteConditions.apres) {
-    titreDemarcheEtapes.forEach(etape => {
-      const predicatCheck = etapeCouranteConditions.apres!.flat().find(c => c?.etapeTypeId === etape.typeId)
-
-      if (predicatCheck) {
-        if ((etapeCouranteConditions.justeApres.length && etapeCouranteConditions.justeApres[0].length) || !etapeCouranteConditions.final) {
-          etapesEnAttente = etapesEnAttente.filter(
-            e =>
-              !etapeCouranteConditions.justeApres
-                .flatMap(d => d)
-                .map(a => a.etapeTypeId)
-                .includes(e.typeId!)
-          )
-        } else {
-          // Si c’est une étape sans de « justeAprès », c’est que c’est une interruption de la démarche
-          etapesEnAttente = []
-        }
-      }
-    })
-  }
-  etapesEnAttente.push(etapeCourante)
-
-  return etapesSuivantesEnAttenteGet(titreDemarcheEtapes, etapesSuivantes, etapesEnAttente, etapeTypeIdDefinitions)
-}
-
-const etapeTypeIdConditionsCheck = (contenu: IContenu | null, titreEtapesEnAttente: ITitreEtape[], conditions: IEtapeTypeIdCondition[][], titreDemarcheEtapes: ITitreEtape[]) =>
-  conditions.some(condition =>
-    condition.every(c => {
-      if (c.titre && !sameContenuCheck(c.titre, contenu)) {
-        return false
-      }
-
-      if (c.contextCheck && !c.contextCheck(titreDemarcheEtapes)) {
-        return false
-      }
-
-      return titreEtapesEnAttente.find(etape => {
-        let result = true
-
-        if (c.etapeTypeId) {
-          result = result && c.etapeTypeId === etape.typeId
-        }
-        if (c.statutId) {
-          result = result && c.statutId === etape.statutId
-        }
-
-        return result
-      })
-    })
-  )
-
-const etapesEnAttenteToString = (titreEtapesEnAttente: ITitreEtape[]) =>
-  titreEtapesEnAttente
-    .map(t => (t.type ? t.type.nom : t.typeId))
-    .map(t => `"${t}"`)
-    .join(', ')
-
-const titreEtapeEtatValidate = (etapeTypeIdDefinitions: IDemarcheDefinitionRestrictions, etapeTypeId: EtapeTypeId, titreDemarcheEtapes: ITitreEtape[], contenu: IContenu | null) => {
-  const errors = []
-  const titreEtapesEnAttente = etapesEnAttenteGet(etapeTypeIdDefinitions, titreDemarcheEtapes)
-
-  if (titreEtapesEnAttente.find(e => e.typeId === etapeTypeId)) {
-    errors.push(`l’étape "${etapeTypeId}" ne peut-être effecutée 2 fois d’affilée`)
-  }
-
-  const titreEtapeRestrictions = titreEtapeTypeIdRestrictionsFind(etapeTypeIdDefinitions, etapeTypeId)
-
-  const { avant, apres, justeApres } = titreEtapeRestrictions
-
-  if (!errors.length && avant && etapeTypeIdConditionsCheck(contenu, titreDemarcheEtapes, avant, titreDemarcheEtapes)) {
-    errors.push(`l’étape "${etapeTypeId}" n’est plus possible après ${etapesEnAttenteToString(titreEtapesEnAttente)}`)
-  }
-
-  if (!errors.length && apres && !etapeTypeIdConditionsCheck(contenu, titreDemarcheEtapes, apres, titreDemarcheEtapes)) {
-    errors.push(`l’étape "${etapeTypeId}" n’est pas possible après ${etapesEnAttenteToString(titreEtapesEnAttente)}`)
-  }
-
-  if (!errors.length && justeApres.length && !etapeTypeIdConditionsCheck(contenu, titreEtapesEnAttente, justeApres, titreDemarcheEtapes)) {
-    errors.push(`l’étape "${etapeTypeId}" n’est pas possible juste après ${etapesEnAttenteToString(titreEtapesEnAttente)}`)
-  }
-
-  if (!errors.length) {
-    if (!justeApres.length || justeApres.some(c => !c.length)) {
-      if (titreDemarcheEtapes.map(e => e.typeId).includes(etapeTypeId)) {
-        errors.push(`l’étape "${etapeTypeId}" existe déjà`)
-      }
-    }
-  }
-
-  return errors
-}
-
-export { titreEtapeEtatValidate, etapesSuivantesEnAttenteGet, titreEtapeTypeIdRestrictionsFind }
diff --git a/packages/api/src/business/validations/titre-etape-updation-validate.test.ts b/packages/api/src/business/validations/titre-etape-updation-validate.test.ts
index 44d67aafd..7582620ec 100644
--- a/packages/api/src/business/validations/titre-etape-updation-validate.test.ts
+++ b/packages/api/src/business/validations/titre-etape-updation-validate.test.ts
@@ -6,9 +6,7 @@ import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
 import { userSuper } from '../../database/user-super.js'
 import { describe, test, expect } from 'vitest'
-import { toCaminoDate } from 'camino-common/src/date.js'
 
-const currentDate = toCaminoDate('2023-04-06')
 describe('valide l’étape avant de l’enregistrer', () => {
   test.each<[SubstanceLegaleId[], EtapeTypeId, TitreTypeId, boolean]>([
     [[], 'mfr', 'arm', true],
@@ -124,7 +122,7 @@ describe('valide l’étape avant de l’enregistrer', () => {
       typeId: 'arm',
     } as unknown as ITitre
 
-    let errors = titreEtapeUpdationValidate(currentDate, titreEtape, titreDemarche, titre, [], [], [], [], [], [], userSuper)
+    let errors = titreEtapeUpdationValidate(titreEtape, titreDemarche, titre, [], [], [], [], [], [], userSuper)
     expect(errors).not.toContain("une autorisation de recherche ne peut pas inclure d'amodiataires")
     expect(errors).not.toContain("une autorisation d'exploitation ne peut pas inclure d'amodiataires")
 
@@ -133,7 +131,7 @@ describe('valide l’étape avant de l’enregistrer', () => {
       amodiataires: [{ id: 'foo', nom: 'bar', operateur: true }],
     } as unknown as ITitreEtape
 
-    errors = titreEtapeUpdationValidate(currentDate, titreEtape, titreDemarche, titre, [], [], [], [], [], [], userSuper)
+    errors = titreEtapeUpdationValidate(titreEtape, titreDemarche, titre, [], [], [], [], [], [], userSuper)
     expect(errors).toContain("une autorisation de recherche ne peut pas inclure d'amodiataires")
 
     // // AXM
@@ -147,7 +145,7 @@ describe('valide l’étape avant de l’enregistrer', () => {
       typeId: 'axm',
     } as unknown as ITitre
 
-    errors = titreEtapeUpdationValidate(currentDate, titreEtape, titreDemarche, titre, [], [], [], [], [], [], userSuper)
+    errors = titreEtapeUpdationValidate(titreEtape, titreDemarche, titre, [], [], [], [], [], [], userSuper)
     expect(errors).not.toContain("une autorisation d'exploitation ne peut pas inclure d'amodiataires")
     expect(errors).not.toContain("une autorisation de recherche ne peut pas inclure d'amodiataires")
 
@@ -156,7 +154,7 @@ describe('valide l’étape avant de l’enregistrer', () => {
       amodiataires: [{ id: 'foo', nom: 'bar', operateur: true }],
     } as unknown as ITitreEtape
 
-    errors = titreEtapeUpdationValidate(currentDate, titreEtape, titreDemarche, titre, [], [], [], [], [], [], userSuper)
+    errors = titreEtapeUpdationValidate(titreEtape, titreDemarche, titre, [], [], [], [], [], [], userSuper)
     expect(errors).toContain("une autorisation d'exploitation ne peut pas inclure d'amodiataires")
   })
 })
diff --git a/packages/api/src/business/validations/titre-etape-updation-validate.ts b/packages/api/src/business/validations/titre-etape-updation-validate.ts
index ae3b28ba4..3d2803446 100644
--- a/packages/api/src/business/validations/titre-etape-updation-validate.ts
+++ b/packages/api/src/business/validations/titre-etape-updation-validate.ts
@@ -16,7 +16,6 @@ import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { DocumentType, DocumentsTypes } from 'camino-common/src/static/documentsTypes.js'
 import { User } from 'camino-common/src/roles.js'
 import { SDOMZoneId } from 'camino-common/src/static/sdom.js'
-import { CaminoDate } from 'camino-common/src/date.js'
 import { getSections, Section } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.js'
 import { DeepReadonly } from 'camino-common/src/typescript-tools.js'
 const numberProps = ['duree', 'surface'] as unknown as [keyof ITitreEtape]
@@ -24,7 +23,6 @@ const numberProps = ['duree', 'surface'] as unknown as [keyof ITitreEtape]
 const dateProps = ['date', 'dateDebut', 'dateFin'] as unknown as [keyof ITitreEtape]
 
 export const titreEtapeUpdationValidate = (
-  date: CaminoDate,
   titreEtape: ITitreEtape,
   titreDemarche: ITitreDemarche,
   titre: ITitre,
@@ -123,7 +121,7 @@ export const titreEtapeUpdationValidate = (
     return errors
   }
 
-  return titreEtapeUpdationBusinessValidate(date, titreEtape, titreDemarche, titre)
+  return titreEtapeUpdationBusinessValidate(titreEtape, titreDemarche, titre)
 }
 
 export const titreEtapeCompleteValidate = (
@@ -208,11 +206,11 @@ export const titreEtapeCompleteValidate = (
   return errors
 }
 
-const titreEtapeUpdationBusinessValidate = (date: CaminoDate, titreEtape: ITitreEtape, titreDemarche: ITitreDemarche, titre: ITitre) => {
+const titreEtapeUpdationBusinessValidate = (titreEtape: ITitreEtape, titreDemarche: ITitreDemarche, titre: ITitre) => {
   const errors = []
   // 1. la date de l'étape est possible
   // en fonction de l'ordre des types d'étapes de la démarche
-  const demarcheUpdatedErrors = titreDemarcheUpdatedEtatValidate(date, titreDemarche.type!, titre, titreEtape, titreDemarche.id, titreDemarche.etapes!)
+  const demarcheUpdatedErrors = titreDemarcheUpdatedEtatValidate(titreDemarche.type!, titre, titreEtape, titreDemarche.id, titreDemarche.etapes!)
   if (demarcheUpdatedErrors.length) {
     errors.push(...demarcheUpdatedErrors)
   }
diff --git a/packages/api/src/business/validations/titre-links-validate.ts b/packages/api/src/business/validations/titre-links-validate.ts
index 32672d4ee..ed10d5ed7 100644
--- a/packages/api/src/business/validations/titre-links-validate.ts
+++ b/packages/api/src/business/validations/titre-links-validate.ts
@@ -1,7 +1,8 @@
+import { TitreId } from 'camino-common/src/titres.js'
 import { ITitre, ITitreDemarche } from '../../types.js'
 import { getLinkConfig } from 'camino-common/src/permissions/titres.js'
 
-export const checkTitreLinks = (titre: Pick<ITitre, 'typeId'>, titreFromIds: string[], titresFrom: ITitre[], demarches: ITitreDemarche[]) => {
+export const checkTitreLinks = (titre: Pick<ITitre, 'typeId'>, titreFromIds: TitreId[], titresFrom: ITitre[], demarches: ITitreDemarche[]) => {
   const linkConfig = getLinkConfig(titre.typeId, demarches)
   if (!linkConfig) {
     throw new Error('ce titre ne peut pas être lié à d’autres titres')
diff --git a/packages/api/src/database/models/_format/id-create.ts b/packages/api/src/database/models/_format/id-create.ts
index 9d07f3475..e04d74a1f 100644
--- a/packages/api/src/database/models/_format/id-create.ts
+++ b/packages/api/src/database/models/_format/id-create.ts
@@ -3,6 +3,8 @@ import { CaminoDate } from 'camino-common/src/date.js'
 import { DocumentId, documentIdValidator } from 'camino-common/src/entreprise.js'
 import { DocumentTypeId } from 'camino-common/src/static/documentsTypes.js'
 import { randomBytes } from 'node:crypto'
+import { TitreId } from 'camino-common/src/titres.js'
+import { EtapeId } from 'camino-common/src/etape.js'
 
 export const idGenerate = <T extends string = string>(): T => randomBytes(12).toString('hex') as T
 
@@ -12,6 +14,14 @@ export const newDemarcheId = (value: string = idGenerate()): DemarcheId => {
   return value as DemarcheId
 }
 
+export const newTitreId = (value: string = idGenerate()): TitreId => {
+  return value as TitreId
+}
+
+export const newEtapeId = (value: string = idGenerate()): EtapeId => {
+  return value as EtapeId
+}
+
 export const newDocumentId = (date: CaminoDate, documentTypeId: DocumentTypeId): DocumentId => {
   const hash = randomBytes(4).toString('hex')
 
diff --git a/packages/api/src/database/models/_format/titre-etape-heritage.ts b/packages/api/src/database/models/_format/titre-etape-heritage.ts
index 64b2a91c9..10bebfbd4 100644
--- a/packages/api/src/database/models/_format/titre-etape-heritage.ts
+++ b/packages/api/src/database/models/_format/titre-etape-heritage.ts
@@ -1,6 +1,7 @@
 import { IHeritageProps, IFields, IHeritageContenu } from '../../../types.js'
 import { userSuper } from '../../user-super.js'
 import { titreEtapeGet } from '../../queries/titres-etapes.js'
+import { newEtapeId } from './id-create.js'
 
 const heritagePropsFormat = async (heritageProps: IHeritageProps) => {
   for (const propId of Object.keys(heritageProps)) {
@@ -12,7 +13,7 @@ const heritagePropsFormat = async (heritageProps: IHeritageProps) => {
         fields[propId] = { id: {} }
       }
 
-      const titreEtape = await titreEtapeGet(heritageProps[propId].etapeId!, { fields }, userSuper)
+      const titreEtape = await titreEtapeGet(newEtapeId(heritageProps[propId].etapeId!), { fields }, userSuper)
 
       heritageProps[propId].etape = titreEtape
     }
@@ -27,7 +28,7 @@ const heritageContenuFormat = async (heritageContenu: IHeritageContenu) => {
     if (heritageContenu[sectionId]) {
       for (const elementId of Object.keys(heritageContenu[sectionId])) {
         if (heritageContenu[sectionId][elementId].etapeId) {
-          const titreEtape = await titreEtapeGet(heritageContenu[sectionId][elementId].etapeId!, { fields }, userSuper)
+          const titreEtape = await titreEtapeGet(newEtapeId(heritageContenu[sectionId][elementId].etapeId!), { fields }, userSuper)
 
           heritageContenu[sectionId][elementId].etape = titreEtape
         }
diff --git a/packages/api/src/database/queries/journaux.ts b/packages/api/src/database/queries/journaux.ts
index 984f47ee0..b3c6feb7c 100644
--- a/packages/api/src/database/queries/journaux.ts
+++ b/packages/api/src/database/queries/journaux.ts
@@ -8,6 +8,7 @@ import { fieldsFormat } from './graph/fields-format.js'
 import options from './_options.js'
 import { IJournauxQueryParams } from '../../api/graphql/resolvers/journaux.js'
 import { User } from 'camino-common/src/roles'
+import { TitreId } from 'camino-common/src/titres.js'
 
 const diffPatcher = create({
   // on filtre certaines proprietés qu’on ne souhaite pas voir apparaitre dans les journaux
@@ -91,7 +92,7 @@ export const upsertJournalCreate = async <T extends Model>(
   options: UpsertGraphOptions,
   relations: RelationExpression<T>,
   userId: string,
-  titreId: string
+  titreId: TitreId
 ): Promise<T> => {
   const oldValue = id ? await model.query().findById(id).withGraphFetched(relations).returning('*') : undefined
 
diff --git a/packages/api/src/database/queries/permissions/documents.test.integration.ts b/packages/api/src/database/queries/permissions/documents.test.integration.ts
index e859d510e..26d861680 100644
--- a/packages/api/src/database/queries/permissions/documents.test.integration.ts
+++ b/packages/api/src/database/queries/permissions/documents.test.integration.ts
@@ -10,7 +10,7 @@ import Document from '../../models/documents.js'
 import { documentCreate, documentGet } from '../documents.js'
 import { etapeTypeDocumentTypeUsedCheck } from './documents.js'
 import { Knex } from 'knex'
-import { newDemarcheId, newDocumentId } from '../../models/_format/id-create.js'
+import { newDemarcheId, newDocumentId, newEtapeId, newTitreId } from '../../models/_format/id-create.js'
 import { getCurrent, toCaminoDate } from 'camino-common/src/date.js'
 import { expect, test, describe, afterAll, beforeAll, vi } from 'vitest'
 import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts.js'
@@ -45,7 +45,7 @@ describe('documentSupprimer', () => {
     })
 
     await TitresEtapes.query().insertGraph({
-      id: 'titreEtapeId',
+      id: newEtapeId('titreEtapeId'),
       typeId: 'dpu',
       titreDemarcheId: newDemarcheId('titreDemarcheId'),
       date: toCaminoDate('2022-01-01'),
@@ -57,7 +57,7 @@ describe('documentSupprimer', () => {
       id: documentId,
       typeId: 'dec',
       date: toCaminoDate('2023-01-12'),
-      titreEtapeId: 'titreEtapeId',
+      titreEtapeId: newEtapeId('titreEtapeId'),
     })
 
     const documentRes = await documentGet(documentId, {}, userSuper)
@@ -88,7 +88,7 @@ describe('documentSupprimer', () => {
     await TitresActivites.query().insertGraph({
       id: 'titreActiviteId',
       typeId: 'grx',
-      titreId: '',
+      titreId: newTitreId(''),
       date: getCurrent(),
       activiteStatutId,
       periodeId: 1,
@@ -129,7 +129,7 @@ describe('etapeTypeDocumentTypeUsedCheck', () => {
     })
 
     await TitresEtapes.query().insertGraph({
-      id: 'titreEtapeId',
+      id: newEtapeId('titreEtapeId'),
       typeId: 'dpu',
       titreDemarcheId: newDemarcheId('titreDemarcheId'),
       date: toCaminoDate('2022-01-01'),
@@ -141,7 +141,7 @@ describe('etapeTypeDocumentTypeUsedCheck', () => {
       id: documentId,
       typeId: 'dec',
       date: toCaminoDate('2023-01-12'),
-      titreEtapeId: 'titreEtapeId',
+      titreEtapeId: newEtapeId('titreEtapeId'),
     })
 
     const check = await etapeTypeDocumentTypeUsedCheck('dpu', 'dec')
@@ -162,7 +162,7 @@ describe('etapeTypeDocumentTypeUsedCheck', () => {
     })
 
     await TitresEtapes.query().insertGraph({
-      id: 'titreEtapeId',
+      id: newEtapeId('titreEtapeId'),
       typeId: 'dpu',
       titreDemarcheId: newDemarcheId('titreDemarcheId'),
       date: toCaminoDate('2022-01-01'),
@@ -174,7 +174,7 @@ describe('etapeTypeDocumentTypeUsedCheck', () => {
       id: documentId,
       typeId: 'arr',
       date: toCaminoDate('2023-01-12'),
-      titreEtapeId: 'titreEtapeId',
+      titreEtapeId: newEtapeId('titreEtapeId'),
     })
 
     const check = await etapeTypeDocumentTypeUsedCheck('dpu', 'dec')
diff --git a/packages/api/src/database/queries/permissions/titres-demarches.test.integration.ts b/packages/api/src/database/queries/permissions/titres-demarches.test.integration.ts
index af7d0e050..da9f46939 100644
--- a/packages/api/src/database/queries/permissions/titres-demarches.test.integration.ts
+++ b/packages/api/src/database/queries/permissions/titres-demarches.test.integration.ts
@@ -1,7 +1,7 @@
 import { dbManager } from '../../../../tests/db-manager.js'
 
 import Titres from '../../models/titres.js'
-import { idGenerate, newDemarcheId } from '../../models/_format/id-create.js'
+import { newDemarcheId, newTitreId } from '../../models/_format/id-create.js'
 import { userSuper } from '../../user-super.js'
 import TitresDemarches from '../../models/titres-demarches.js'
 import { titreDemarcheSuppressionSelectQuery, titresDemarchesQueryModify } from './titres-demarches.js'
@@ -51,7 +51,7 @@ describe('titresDemarchesQueryModify', () => {
       [{ role: 'defaut' }, false],
       [undefined, false],
     ])('un utilisateur $user peut supprimer $suppression une démarche qui n’a pas d’étape', async (user, suppression) => {
-      const titreId = idGenerate()
+      const titreId = newTitreId()
       await Titres.query().insert([
         {
           id: titreId,
@@ -107,7 +107,7 @@ describe('titresDemarchesQueryModify', () => {
       [{ role: 'defaut' }, false],
       [undefined, false],
     ])('un utilisateur $role peut supprimer une démarche qui a au moins une étape', async (user, suppression) => {
-      const titreId = idGenerate()
+      const titreId = newTitreId()
       await Titres.query().insert([
         {
           id: titreId,
@@ -157,7 +157,7 @@ describe('titresDemarchesQueryModify', () => {
   })
   describe('titresDemarchesArchive', () => {
     test('Vérifie si le statut archivé masque la démarche du titre', async () => {
-      const titreId = idGenerate()
+      const titreId = newTitreId()
       await Titres.query().insert([
         {
           id: titreId,
diff --git a/packages/api/src/database/queries/permissions/titres-etapes.test.integration.ts b/packages/api/src/database/queries/permissions/titres-etapes.test.integration.ts
index 7a2538454..41ca6abde 100644
--- a/packages/api/src/database/queries/permissions/titres-etapes.test.integration.ts
+++ b/packages/api/src/database/queries/permissions/titres-etapes.test.integration.ts
@@ -1,7 +1,7 @@
 import { dbManager } from '../../../../tests/db-manager.js'
 
 import Titres from '../../models/titres.js'
-import { idGenerate, newDemarcheId } from '../../models/_format/id-create.js'
+import { newDemarcheId, newEtapeId, newTitreId } from '../../models/_format/id-create.js'
 import { userSuper } from '../../user-super.js'
 import TitresEtapes from '../../models/titres-etapes.js'
 import { titresEtapesQueryModify } from './titres-etapes.js'
@@ -22,7 +22,7 @@ afterAll(async () => {
 describe('titresEtapesQueryModify', () => {
   describe('titresEtapesArchive', () => {
     test("Vérifie si le statut archivé masque l'étape de la démarche", async () => {
-      const titreId = idGenerate()
+      const titreId = newTitreId()
       await Titres.query().insert([
         {
           id: titreId,
@@ -41,8 +41,8 @@ describe('titresEtapesQueryModify', () => {
         titreId,
         archive: false,
       })
-      const titreEtapeId = idGenerate()
-      const archivedTitreEtapeId = idGenerate()
+      const titreEtapeId = newEtapeId()
+      const archivedTitreEtapeId = newEtapeId()
       await TitresEtapes.query().insert([
         {
           id: titreEtapeId,
diff --git a/packages/api/src/database/queries/permissions/titres.test.integration.ts b/packages/api/src/database/queries/permissions/titres.test.integration.ts
index c3800462c..a39a91d5f 100644
--- a/packages/api/src/database/queries/permissions/titres.test.integration.ts
+++ b/packages/api/src/database/queries/permissions/titres.test.integration.ts
@@ -3,7 +3,7 @@ import { IEntreprise, ITitre, ITitreDemarche } from '../../../types.js'
 import { dbManager } from '../../../../tests/db-manager.js'
 
 import Titres from '../../models/titres.js'
-import { idGenerate } from '../../models/_format/id-create.js'
+import { idGenerate, newDemarcheId, newEtapeId, newTitreId } from '../../models/_format/id-create.js'
 import { titresArmEnDemandeQuery, titresConfidentielSelect, titresModificationSelectQuery, titresQueryModify, titresVisibleByEntrepriseQuery } from './titres.js'
 import { userSuper } from '../../user-super.js'
 import { AdministrationRole } from 'camino-common/src/roles.js'
@@ -15,6 +15,7 @@ import { DemarcheStatutId } from 'camino-common/src/static/demarchesStatuts.js'
 import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts.js'
 import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
 import { testBlankUser, TestUser } from 'camino-common/src/tests-utils'
+import { toCaminoDate } from 'camino-common/src/date.js'
 
 console.info = vi.fn()
 console.error = vi.fn()
@@ -39,7 +40,9 @@ describe('titresQueryModify', () => {
         nom: 'monEntrepriseNom',
       } as IEntreprise
 
-      const etapeId = idGenerate()
+      const id = newTitreId()
+      const demarcheId = newDemarcheId()
+      const etapeId = newEtapeId()
 
       const mockTitre: Omit<ITitre, 'id'> = {
         nom: 'titre1',
@@ -48,11 +51,14 @@ describe('titresQueryModify', () => {
         propsTitreEtapesIds: { titulaires: etapeId },
         demarches: [
           {
+            id: demarcheId,
+            titreId: id,
             typeId: 'oct',
             etapes: [
               {
                 id: etapeId,
-                date: '2020-01-01',
+                titreDemarcheId: demarcheId,
+                date: toCaminoDate('2020-01-01'),
                 typeId: 'mfr',
                 statutId: 'fai',
                 titulaires: withTitulaire ? [mockEntreprise1] : [],
@@ -174,9 +180,9 @@ describe('titresQueryModify', () => {
         nom: 'monEntrepriseNom',
       } as IEntreprise
 
-      const etapeId = idGenerate()
-
-      const id = idGenerate()
+      const etapeId = newEtapeId()
+      const demarcheId = newDemarcheId()
+      const id = newTitreId()
 
       const mockTitre: ITitre = {
         id,
@@ -188,12 +194,15 @@ describe('titresQueryModify', () => {
         propsTitreEtapesIds: { titulaires: etapeId },
         demarches: [
           {
+            id: demarcheId,
+            titreId: id,
             typeId: 'oct',
             statutId: 'ins',
             etapes: [
               {
                 id: etapeId,
-                date: '2020-01-01',
+                titreDemarcheId: demarcheId,
+                date: toCaminoDate('2020-01-01'),
                 typeId: 'mcr',
                 statutId: 'fav',
                 titulaires: withTitulaire ? [mockEntreprise1] : [],
@@ -294,8 +303,8 @@ describe('titresQueryModify', () => {
 
   describe('titresArchive', () => {
     test('Vérifie si le statut archivé masque le titre', async () => {
-      const archivedTitreId = idGenerate()
-      const titreId = idGenerate()
+      const archivedTitreId = newTitreId()
+      const titreId = newTitreId()
       await Titres.query().insert([
         {
           id: archivedTitreId,
diff --git a/packages/api/src/database/queries/titres-activites.test.integration.ts b/packages/api/src/database/queries/titres-activites.test.integration.ts
index 3f8ac8869..e39bffe13 100644
--- a/packages/api/src/database/queries/titres-activites.test.integration.ts
+++ b/packages/api/src/database/queries/titres-activites.test.integration.ts
@@ -1,7 +1,7 @@
 import { titresActivitesGet } from './titres-activites.js'
 import TitresActivites from '../models/titres-activites.js'
 import { dbManager } from '../../../tests/db-manager.js'
-import { idGenerate } from '../models/_format/id-create.js'
+import { newTitreId } from '../models/_format/id-create.js'
 import Titres from '../models/titres.js'
 import { UserNotNull } from 'camino-common/src/roles.js'
 import { beforeAll, expect, afterAll, test, describe, vi } from 'vitest'
@@ -19,11 +19,11 @@ describe('teste les requêtes sur les activités', () => {
   test('vérifie que le filtrage fonctionne pour les administrations', async () => {
     await TitresActivites.query().delete()
 
-    const titreId = idGenerate()
+    const titreId = newTitreId()
 
     await Titres.query().insert({
       id: titreId,
-      nom: idGenerate(),
+      nom: titreId,
       titreStatutId: 'val',
       typeId: 'arm',
     })
diff --git a/packages/api/src/database/queries/titres-etapes.ts b/packages/api/src/database/queries/titres-etapes.ts
index b4a143021..71c5df1d9 100644
--- a/packages/api/src/database/queries/titres-etapes.ts
+++ b/packages/api/src/database/queries/titres-etapes.ts
@@ -8,6 +8,8 @@ import TitresEtapesJustificatifs from '../models/titres-etapes-justificatifs.js'
 import { titresEtapesQueryModify } from './permissions/titres-etapes.js'
 import { createJournalCreate, patchJournalCreate, upsertJournalCreate } from './journaux.js'
 import { User, UserNotNull } from 'camino-common/src/roles'
+import { TitreId } from 'camino-common/src/titres.js'
+import { EtapeId } from 'camino-common/src/etape.js'
 
 const titresEtapesQueryBuild = ({ fields }: { fields?: IFields }, user: User) => {
   const graph = fields ? graphBuild(fields, 'etapes', fieldsFormat) : options.titresEtapes.graph
@@ -22,7 +24,7 @@ const titresEtapesQueryBuild = ({ fields }: { fields?: IFields }, user: User) =>
 }
 
 // utilisé dans le daily et le resolver des documents uniquement
-const titreEtapeGet = async (titreEtapeId: string, { fields, fetchHeritage }: { fields?: IFields; fetchHeritage?: boolean }, user: User) => {
+const titreEtapeGet = async (titreEtapeId: EtapeId, { fields, fetchHeritage }: { fields?: IFields; fetchHeritage?: boolean }, user: User) => {
   const q = titresEtapesQueryBuild({ fields }, user)
 
   q.context({ fetchHeritage })
@@ -76,11 +78,11 @@ const titreEtapeCreate = async (titreEtape: Omit<ITitreEtape, 'id'>, user: UserN
   return newValue
 }
 
-const titreEtapeUpdate = async (id: string, titreEtape: Partial<DBTitresEtapes>, user: UserNotNull, titreId: string): Promise<TitresEtapes> => {
+const titreEtapeUpdate = async (id: EtapeId, titreEtape: Partial<DBTitresEtapes>, user: UserNotNull, titreId: TitreId): Promise<TitresEtapes> => {
   return patchJournalCreate<TitresEtapes>(id, titreEtape, TitresEtapes, user.id, titreId)
 }
 
-const titreEtapeUpsert = async (titreEtape: Partial<Pick<ITitreEtape, 'id'>> & Omit<ITitreEtape, 'id'>, user: UserNotNull, titreId: string) =>
+const titreEtapeUpsert = async (titreEtape: Partial<Pick<ITitreEtape, 'id'>> & Omit<ITitreEtape, 'id'>, user: UserNotNull, titreId: TitreId) =>
   upsertJournalCreate<TitresEtapes>(titreEtape.id, titreEtape, TitresEtapes, options.titresEtapes.update, options.titresEtapes.graph, user.id, titreId)
 
 const titresEtapesJustificatifsUpsert = async (titresEtapesJustificatifs: ITitreEtapeJustificatif[]) =>
diff --git a/packages/api/src/database/queries/titres-titres.ts b/packages/api/src/database/queries/titres-titres.ts
index 42c82752b..10cb98706 100644
--- a/packages/api/src/database/queries/titres-titres.ts
+++ b/packages/api/src/database/queries/titres-titres.ts
@@ -1,8 +1,9 @@
 import TitresTitres from '../models/titres--titres.js'
+import { TitreId } from 'camino-common/src/titres.js'
 
 interface LinkTitre {
-  linkTo: string
-  linkFrom: string[]
+  linkTo: TitreId
+  linkFrom: TitreId[]
 }
 export const linkTitres = async (link: LinkTitre): Promise<void> => {
   await TitresTitres.query().where('titreToId', link.linkTo).delete()
diff --git a/packages/api/src/database/queries/titres.ts b/packages/api/src/database/queries/titres.ts
index eb36e9105..eba7f7c5b 100644
--- a/packages/api/src/database/queries/titres.ts
+++ b/packages/api/src/database/queries/titres.ts
@@ -16,7 +16,7 @@ import { User } from 'camino-common/src/roles'
 import { DepartementId } from 'camino-common/src/static/departement.js'
 import { RegionId } from 'camino-common/src/static/region.js'
 import { FacadesMaritimes } from 'camino-common/src/static/facades.js'
-import { EditableTitre } from 'camino-common/src/titres.js'
+import { EditableTitre, TitreId } from 'camino-common/src/titres.js'
 
 /**
  * Construit la requête pour récupérer certains champs de titres filtrés
@@ -290,9 +290,9 @@ const titreCreate = async (titre: Omit<ITitre, 'id'>, { fields }: { fields?: IFi
   return Titres.query().withGraphFetched(graph).insertGraph(titre, options.titres.update)
 }
 
-const titreUpdate = async (id: string, titre: Partial<DBTitre>) => Titres.query().patchAndFetchById(id, { ...titre, id })
+const titreUpdate = async (id: TitreId, titre: Partial<DBTitre>) => Titres.query().patchAndFetchById(id, { ...titre, id })
 
-export const titreArchive = async (id: string) => {
+export const titreArchive = async (id: TitreId) => {
   // archive le titre
   await titreUpdate(id, { archive: true })
 
diff --git a/packages/api/src/knex/migrations/20230607092129_etape-ordre-not-null.ts b/packages/api/src/knex/migrations/20230607092129_etape-ordre-not-null.ts
new file mode 100644
index 000000000..f2adbb4aa
--- /dev/null
+++ b/packages/api/src/knex/migrations/20230607092129_etape-ordre-not-null.ts
@@ -0,0 +1,8 @@
+import { Knex } from 'knex'
+
+export const up = async (knex: Knex) => {
+  await knex.raw('ALTER TABLE titres_etapes ALTER COLUMN ordre SET NOT NULL')
+  await knex.raw('ALTER TABLE titres_etapes ALTER COLUMN ordre SET DEFAULT 0')
+}
+
+export const down = () => ({})
diff --git a/packages/api/src/tools/demarches/definitions-check.ts b/packages/api/src/tools/demarches/definitions-check.ts
index 6884b02dc..bb2351bf9 100644
--- a/packages/api/src/tools/demarches/definitions-check.ts
+++ b/packages/api/src/tools/demarches/definitions-check.ts
@@ -2,11 +2,9 @@ import { demarchesDefinitions } from '../../business/rules-demarches/definitions
 import { titresDemarchesGet } from '../../database/queries/titres-demarches.js'
 import { titreDemarcheUpdatedEtatValidate } from '../../business/validations/titre-demarche-etat-validate.js'
 import { userSuper } from '../../database/user-super.js'
-import { getCurrent } from 'camino-common/src/date.js'
 
 const demarchesValidate = async () => {
   const errors = [] as string[]
-  const currentDate = getCurrent()
   for (const demarcheDefinition of demarchesDefinitions) {
     for (const demarcheTypeId of demarcheDefinition.demarcheTypeIds) {
       const demarches = await titresDemarchesGet(
@@ -29,7 +27,7 @@ const demarchesValidate = async () => {
         .filter(demarche => demarche.etapes?.length)
         .forEach(demarche => {
           try {
-            const errs = titreDemarcheUpdatedEtatValidate(currentDate, demarche.type!, demarche.titre!, demarche.etapes![0], demarche.id, demarche.etapes!)
+            const errs = titreDemarcheUpdatedEtatValidate(demarche.type!, demarche.titre!, demarche.etapes![0], demarche.id, demarche.etapes!)
 
             if (errs.length) {
               errors.push(`https://camino.beta.gouv.fr/titres/${demarche.titreId} => démarche "${demarche.typeId}" : ${errs}`)
diff --git a/packages/api/src/tools/demarches/tde-check.ts b/packages/api/src/tools/demarches/tde-check.ts
index cbe50e424..a4ead88b9 100644
--- a/packages/api/src/tools/demarches/tde-check.ts
+++ b/packages/api/src/tools/demarches/tde-check.ts
@@ -1,6 +1,6 @@
 import { EtapesTypes } from 'camino-common/src/static/etapesTypes.js'
 import { isTDEExist } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index.js'
-import { demarcheDefinitionFind, isDemarcheDefinitionMachine } from '../../business/rules-demarches/definitions.js'
+import { demarcheDefinitionFind } from '../../business/rules-demarches/definitions.js'
 import { titresDemarchesGet } from '../../database/queries/titres-demarches.js'
 import { userSuper } from '../../database/user-super.js'
 
@@ -26,7 +26,7 @@ export const titreTypeDemarcheTypeEtapeTypeCheck = async () => {
   demarches.forEach(d => {
     const demarcheDefinition = demarcheDefinitionFind(d.titre!.typeId, d.typeId, d.etapes, d.id)
 
-    if (!isDemarcheDefinitionMachine(demarcheDefinition)) {
+    if (!demarcheDefinition) {
       d.etapes?.forEach(({ typeId }) => {
         if (!isTDEExist(d.titre!.typeId, d.typeId, typeId)) {
           console.info(`erreur sur le titre https://camino.beta.gouv.fr/titres/${d.titre!.id}, TDE inconnu ${d.titre!.typeId} ${d.typeId} ${typeId} (${EtapesTypes[typeId].nom})`)
diff --git a/packages/api/src/tools/demarches/tests-creation.ts b/packages/api/src/tools/demarches/tests-creation.ts
index ce87bf955..7db76b5b7 100644
--- a/packages/api/src/tools/demarches/tests-creation.ts
+++ b/packages/api/src/tools/demarches/tests-creation.ts
@@ -4,15 +4,14 @@ import { titresDemarchesGet } from '../../database/queries/titres-demarches.js'
 import { userSuper } from '../../database/user-super.js'
 import { titreDemarcheDepotDemandeDateFind } from '../../business/rules/titre-demarche-depot-demande-date-find.js'
 import { writeFileSync } from 'fs'
-import { Etape, toMachineEtapes } from '../../business/rules-demarches/machine-common.js'
-import { demarchesDefinitions, isDemarcheDefinitionMachine } from '../../business/rules-demarches/definitions.js'
+import { Etape, titreEtapeForMachineValidator, toMachineEtapes } from '../../business/rules-demarches/machine-common.js'
+import { demarchesDefinitions } from '../../business/rules-demarches/definitions.js'
 import { dateAddDays, daysBetween, setDayInMonth } from 'camino-common/src/date.js'
 import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes.js'
+import { toCommuneId } from 'camino-common/src/static/communes.js'
 
 const writeEtapesForTest = async () => {
-  const demarcheDefinitionMachines = demarchesDefinitions.filter(isDemarcheDefinitionMachine)
-
-  for (const demarcheDefinition of demarcheDefinitionMachines) {
+  for (const demarcheDefinition of demarchesDefinitions) {
     const demarches = await titresDemarchesGet(
       {
         titresTypesIds: [demarcheDefinition.titreTypeId.slice(0, 2)],
@@ -22,7 +21,7 @@ const writeEtapesForTest = async () => {
       {
         fields: {
           titre: { id: {}, demarches: { etapes: { id: {} } } },
-          etapes: { id: {} },
+          etapes: { communes: { id: {} } },
           type: { etapesTypes: { id: {} } },
         },
       },
@@ -36,39 +35,25 @@ const writeEtapesForTest = async () => {
 
         return (date ?? '') > demarcheDefinition.dateDebut && !demarcheDefinition.demarcheIdExceptions?.includes(demarche.id)
       })
-      .filter(({ titreId }) => {
-        if (
-          [
-            // décision du propriétaire du sol avant le dépôt de la demande
-            'EI4lAxLbhdFOoHb6LWL0y9pO',
-            'e8ZYqaA9HB3bXuOeRlXz5g76',
-            // visibilité publique
-            'z0DZo6TKEvP28D6oQyAuTvwA',
-            'RGOrc6hTOErMD8SBkUChbTyg',
-            '8KsDiNBHR9lAHv229GIqA7fw',
-            '8pY4eoUKtuR3is8l3Vy0vmJC',
-          ].includes(titreId)
-        ) {
-          console.info('On ignore le titre ' + titreId)
-
-          return false
-        }
-
-        return true
-      })
       .map((demarche, index) => {
         const etapes: Etape[] = toMachineEtapes(
-          demarche?.etapes
-            ?.sort((a, b) => (a.ordre ?? 0) - (b.ordre ?? 0))
-            ?.map(etape => {
-              if (etape?.contenu?.arm) {
-                etape.contenu = { arm: etape.contenu?.arm }
-              } else {
-                delete etape.contenu
-              }
+          (
+            demarche?.etapes
+              ?.sort((a, b) => (a.ordre ?? 0) - (b.ordre ?? 0))
+              ?.map(etape => {
+                if (etape?.contenu?.arm) {
+                  etape.contenu = { arm: etape.contenu?.arm }
+                } else {
+                  delete etape.contenu
+                }
+
+                if (etape.communes?.length) {
+                  etape.communes = etape.communes.map(({ id }) => ({ nom: '', id: toCommuneId(`${id.startsWith('97') ? `${id.substring(0, 3)}00` : `${id.substring(0, 2)}000`}}`) }))
+                }
 
-              return etape
-            }) ?? []
+                return etape
+              }) ?? []
+          ).map(etape => titreEtapeForMachineValidator.parse(etape))
         )
         // Pour anonymiser la date en gardant les délai en mois entre la saisine et l'apd,
         // on trouve la date de saisine et on calcule un delta random pour tomber dans le même mois
diff --git a/packages/api/src/tools/documents/files-document-check.ts b/packages/api/src/tools/documents/files-document-check.ts
index 085834ba4..b773eb6ab 100644
--- a/packages/api/src/tools/documents/files-document-check.ts
+++ b/packages/api/src/tools/documents/files-document-check.ts
@@ -5,6 +5,7 @@ import { titreEtapeGet } from '../../database/queries/titres-etapes.js'
 import { userSuper } from '../../database/user-super.js'
 import { contenuFilesGet } from '../../business/utils/contenu-element-file-process.js'
 import { getSections } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.js'
+import { newEtapeId } from '../../database/models/_format/id-create.js'
 
 const etapeGet = (str: string) => str.split('-').slice(0, -1).join('-')
 
@@ -14,7 +15,7 @@ const contenuFilesCheck = async (filePath: string) => {
   const split = filePath.split('/')
 
   const repertoire = split[0]
-  const etapeId = split[1]
+  const etapeId = newEtapeId(split[1])
   const fileName = split[2]
 
   if (repertoire !== 'demarches') {
diff --git a/packages/api/src/tools/geojson.ts b/packages/api/src/tools/geojson.ts
index 8e58d904d..31e35ceee 100644
--- a/packages/api/src/tools/geojson.ts
+++ b/packages/api/src/tools/geojson.ts
@@ -7,6 +7,7 @@ import { knex } from '../knex.js'
 import { SDOMZoneId } from 'camino-common/src/static/sdom.js'
 import { SecteursMaritimesIds } from 'camino-common/src/static/facades.js'
 import { Feature } from 'geojson'
+import { CommuneId } from 'camino-common/src/static/communes.js'
 
 // convertit des points
 // en un geojson de type 'MultiPolygon'
@@ -155,8 +156,8 @@ export const geojsonIntersectsSecteursMaritime = async (geojson: Feature<any>):
   return { fallback, data: result.rows.map(({ id }) => id) }
 }
 
-export const geojsonIntersectsCommunes = async (geojson: Feature<any>): Promise<GeoJsonResult<{ id: string; surface: number }[]>> => {
-  let result: { rows: { id: string; surface: string }[] }
+export const geojsonIntersectsCommunes = async (geojson: Feature<any>): Promise<GeoJsonResult<{ id: CommuneId; surface: number }[]>> => {
+  let result: { rows: { id: CommuneId; surface: string }[] }
   let fallback = false
   try {
     result = await knex.raw(
diff --git a/packages/api/src/tools/phases/tests-creation.ts b/packages/api/src/tools/phases/tests-creation.ts
index 900fdd230..77ccb9319 100644
--- a/packages/api/src/tools/phases/tests-creation.ts
+++ b/packages/api/src/tools/phases/tests-creation.ts
@@ -11,7 +11,7 @@ import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts.js'
 import { EtapeTypeId } from 'camino-common/src/static/etapesTypes.js'
 import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { DemarcheId } from 'camino-common/src/demarche.js'
-import { idGenerate, newDemarcheId } from '../../database/models/_format/id-create.js'
+import { newDemarcheId, newTitreId } from '../../database/models/_format/id-create.js'
 import { TitreDemarchePhaseFind, TitreEtapePhaseFind } from '../../business/rules/titre-phases-find.js'
 
 const writePhasesForTest = async () => {
@@ -62,7 +62,7 @@ const writePhasesForTest = async () => {
     }
 
     const fakeDemarcheId = newDemarcheId()
-    const fakeTitreId = idGenerate()
+    const fakeTitreId = newTitreId()
 
     const etapes: TitreEtapePhaseFind[] = etapesDb.rows
       .filter(({ titre_demarche_id }) => titre_demarche_id === row.id)
diff --git a/packages/api/src/types.ts b/packages/api/src/types.ts
index 03047efcc..16baa5d57 100644
--- a/packages/api/src/types.ts
+++ b/packages/api/src/types.ts
@@ -30,6 +30,8 @@ import { Section, SectionsElement } from 'camino-common/src/static/titresTypes_d
 import { ActivitesTypesId } from 'camino-common/src/static/activitesTypes.js'
 import { CommuneId } from 'camino-common/src/static/communes.js'
 import { ForetId } from 'camino-common/src/static/forets.js'
+import { TitreId } from 'camino-common/src/titres.js'
+import { EtapeId } from 'camino-common/src/etape'
 
 enum TitreEtapesTravauxTypes {
   DemandeAutorisationOuverture = 'wfa',
@@ -347,12 +349,12 @@ interface IAdministrationActiviteTypeEmail {
 }
 
 export interface ITitreTitre {
-  titreFromId: string
-  titreToId: string
+  titreFromId: TitreId
+  titreToId: TitreId
 }
 
 interface ITitre {
-  id: string
+  id: TitreId
   slug?: string
   nom: string
   typeId: TitreTypeId
@@ -394,7 +396,7 @@ interface ITitre {
 interface ITitreActivite {
   id: string
   slug?: string
-  titreId: string
+  titreId: TitreId
   titre?: ITitre | null
   date: CaminoDate
   typeId: string
@@ -422,7 +424,7 @@ interface ITitreDemarche {
   id: DemarcheId
   description?: string
   slug?: string
-  titreId: string
+  titreId: TitreId
   titre?: ITitre | null
   typeId: DemarcheTypeId
   statutId?: DemarcheStatutId | null
@@ -457,7 +459,7 @@ interface IDocument {
   nor?: string | null
   publicLecture?: boolean | null
   entreprisesLecture?: boolean | null
-  titreEtapeId?: string | null
+  titreEtapeId?: EtapeId | null
   etape?: ITitreEtape | null
   titreActiviteId?: string | null
   activite?: ITitreActivite | null
@@ -466,7 +468,7 @@ interface IDocument {
   suppression?: boolean | null
 }
 interface ITitreEtape {
-  id: string
+  id: EtapeId
   slug?: string
   typeId: EtapeTypeId
   type?: IEtapeType | null
diff --git a/packages/api/tests/_utils/administrations-permissions.ts b/packages/api/tests/_utils/administrations-permissions.ts
index 869fd0bb3..61d754c83 100644
--- a/packages/api/tests/_utils/administrations-permissions.ts
+++ b/packages/api/tests/_utils/administrations-permissions.ts
@@ -7,7 +7,7 @@ import DemarchesTypes from '../../src/database/models/demarches-types.js'
 import options from '../../src/database/queries/_options.js'
 import { etapeTypeGet } from '../../src/database/queries/metas.js'
 import { titreEtapePropsIds } from '../../src/business/utils/titre-etape-heritage-props-find.js'
-import { newDemarcheId, newDocumentId } from '../../src/database/models/_format/id-create.js'
+import { newDemarcheId, newDocumentId, newTitreId, newEtapeId } from '../../src/database/models/_format/id-create.js'
 import { TitreTypeId } from 'camino-common/src/static/titresTypes.js'
 import { getDocuments } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.js'
 import { documentCreate } from '../../src/database/queries/documents.js'
@@ -19,6 +19,7 @@ import { AdministrationId, sortedAdministrations } from 'camino-common/src/stati
 import { TestUser } from 'camino-common/src/tests-utils.js'
 import type { Pool } from 'pg'
 import { getSections } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.js'
+import { TitreId } from 'camino-common/src/titres.js'
 export const visibleCheck = async (
   pool: Pool,
   administrationId: AdministrationId,
@@ -36,7 +37,7 @@ export const visibleCheck = async (
 
   const titre = titreBuild(
     {
-      titreId: `${titreTypeId}${locale ? '-local' : ''}-${cible}-admin-${administrationId}`,
+      titreId: newTitreId(`${titreTypeId}${locale ? '-local' : ''}-${cible}-admin-${administrationId}`),
       titreTypeId,
     },
     gestionnaire ? administrationId : undefined,
@@ -272,7 +273,7 @@ export const modificationCheck = async (
 
   const titre = titreBuild(
     {
-      titreId: `${titreTypeId}${locale ? '-local' : ''}${etapeTypeId}-${cible}-modification-admin-${administrationId}`,
+      titreId: newTitreId(`${titreTypeId}${locale ? '-local' : ''}${etapeTypeId}-${cible}-modification-admin-${administrationId}`),
       titreTypeId,
     },
     gestionnaire ? administrationId : undefined,
@@ -348,7 +349,7 @@ const titreBuild = (
     titreId,
     titreTypeId,
   }: {
-    titreId: string
+    titreId: TitreId
     titreTypeId: TitreTypeId
   },
   administrationIdGestionnaire?: AdministrationId,
@@ -368,7 +369,7 @@ const titreBuild = (
         typeId: 'oct',
         etapes: [
           {
-            id: `${titreId}-demarche-id-etape-id`,
+            id: newEtapeId(`${titreId}-demarche-id-etape-id`),
             typeId: etapeTypeId || 'mcr',
             ordre: 0,
             titreDemarcheId: newDemarcheId(`${titreId}-demarche-id`),
diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json
index 6e25e5c97..2e93e11d8 100644
--- a/packages/api/tsconfig.json
+++ b/packages/api/tsconfig.json
@@ -1,6 +1,6 @@
 {
   "compilerOptions": {
-    "allowJs": true,
+    "allowJs": false,
     "allowSyntheticDefaultImports": true,
     "alwaysStrict": true,
     "esModuleInterop": true,
diff --git a/packages/common/src/demarche.ts b/packages/common/src/demarche.ts
index 4c919083f..554e7d55e 100644
--- a/packages/common/src/demarche.ts
+++ b/packages/common/src/demarche.ts
@@ -1,12 +1,13 @@
 import { z } from 'zod'
 import { demarcheTypeIdValidator } from './static/demarchesTypes.js'
+import { titreIdValidator } from './titres.js'
 
 export const demarcheIdValidator = z.string().brand<'DemarcheId'>()
 export type DemarcheId = z.infer<typeof demarcheIdValidator>
 
 export const commonDemarcheValidator = z.object({
   id: z.string(),
-  titre_id: z.string(),
+  titre_id: titreIdValidator,
   type_id: demarcheTypeIdValidator,
 })
 export type CommonDemarche = z.infer<typeof commonDemarcheValidator>
diff --git a/packages/common/src/etape.ts b/packages/common/src/etape.ts
index 81b9a1cfa..7c7e81cd6 100644
--- a/packages/common/src/etape.ts
+++ b/packages/common/src/etape.ts
@@ -9,6 +9,9 @@ import { EtapeTypeId, etapeTypeIdValidator } from './static/etapesTypes.js'
 import { SubstanceLegaleId } from './static/substancesLegales.js'
 import { z } from 'zod'
 
+export const etapeIdValidator = z.string().brand<'EtapeId'>()
+export type EtapeId = z.infer<typeof etapeIdValidator>
+
 export type HeritageProp<T> =
   | {
       actif: true
@@ -26,7 +29,7 @@ export interface CaminoDocument {
 }
 
 type EtapeBase = {
-  id: string
+  id: EtapeId
   contenu: { [key: string]: unknown }
   date: CaminoDate
   type: { id: EtapeTypeId; nom: string }
diff --git a/packages/common/src/rest.ts b/packages/common/src/rest.ts
index 6933bfc0e..6e7762537 100644
--- a/packages/common/src/rest.ts
+++ b/packages/common/src/rest.ts
@@ -16,6 +16,7 @@ import {
   sectionValidator,
   titreDrealValidator,
   titreGetValidator,
+  titreIdValidator,
   titreLinksValidator,
   titreOnfValidator,
   titrePtmgValidator,
@@ -23,7 +24,7 @@ import {
 } from './titres.js'
 import { userValidator } from './roles.js'
 import { caminoAnneeValidator, caminoDateValidator } from './date.js'
-import { etapeTypeEtapeStatutWithMainStepValidator } from './etape.js'
+import { etapeIdValidator, etapeTypeEtapeStatutWithMainStepValidator } from './etape.js'
 import { statistiquesDGTMValidator, statistiquesGranulatsMarinsValidator, statistiquesGuyaneDataValidator, statistiquesMinerauxMetauxMetropoleValidator } from './statistiques.js'
 import { fiscaliteValidator } from './fiscalite.js'
 import { caminoConfigValidator } from './static/config.js'
@@ -94,16 +95,16 @@ export const CaminoRestRoutes = {
   '/rest/statistiques/minerauxMetauxMetropole': { get: { output: statistiquesMinerauxMetauxMetropoleValidator } },
   '/rest/statistiques/guyane': { get: { output: statistiquesGuyaneDataValidator } },
   '/rest/statistiques/granulatsMarins': { get: { output: statistiquesGranulatsMarinsValidator } },
-  '/rest/titreSections/:titreId': { params: { titreId: z.string() }, get: { output: z.array(sectionValidator) } },
+  '/rest/titreSections/:titreId': { params: { titreId: titreIdValidator }, get: { output: z.array(sectionValidator) } },
   '/rest/demarches/:demarcheId': { params: { demarcheId: demarcheIdValidator }, get: { output: demarcheGetValidator } },
-  '/rest/titres/:titreId': { params: { titreId: z.string() }, get: { output: titreGetValidator }, delete: true, post: { output: z.void(), input: editableTitreValidator } },
-  '/rest/titres/:titreId/abonne': { params: { titreId: z.string() }, post: { input: utilisateurTitreAbonneValidator, output: z.void() } },
-  '/rest/titres/:titreId/date': { params: { titreId: z.string() }, get: { output: caminoDateValidator.nullable() } },
+  '/rest/titres/:titreId': { params: { titreId: titreIdValidator }, get: { output: titreGetValidator }, delete: true, post: { output: z.void(), input: editableTitreValidator } },
+  '/rest/titres/:titreId/abonne': { params: { titreId: titreIdValidator }, post: { input: utilisateurTitreAbonneValidator, output: z.void() } },
+  '/rest/titres/:titreId/date': { params: { titreId: titreIdValidator }, get: { output: caminoDateValidator.nullable() } },
   '/rest/titresONF': { get: { output: z.array(titreOnfValidator) } },
   '/rest/titresPTMG': { get: { output: z.array(titrePtmgValidator) } },
   '/rest/titresDREAL': { get: { output: z.array(titreDrealValidator) } },
-  '/rest/titres/:id/titreLiaisons': { params: { id: z.string() }, get: { output: titreLinksValidator }, post: { input: z.array(z.string()), output: titreLinksValidator } },
-  '/rest/titres/:id/communes': { params: { id: z.string() }, get: { output: z.array(communeValidator) } },
+  '/rest/titres/:id/titreLiaisons': { params: { id: titreIdValidator }, get: { output: titreLinksValidator }, post: { input: z.array(z.string()), output: titreLinksValidator } },
+  '/rest/titres/:id/communes': { params: { id: titreIdValidator }, get: { output: z.array(communeValidator) } },
   '/rest/statistiques/dgtm': { get: { output: statistiquesDGTMValidator } },
 
   '/rest/entreprises/:entrepriseId/fiscalite/:annee': { params: { entrepriseId: entrepriseIdValidator, annee: caminoAnneeValidator }, get: { output: fiscaliteValidator } },
@@ -126,14 +127,14 @@ export const CaminoRestRoutes = {
   '/changerMotDePasse': { get: { output: z.string() } },
   '/download/fichiers/:documentId': { params: { documentId: documentIdValidator }, download: true },
   '/fichiers/:documentId': { params: { documentId: documentIdValidator }, download: true },
-  '/titres/:id': { params: { id: z.string() }, download: true },
+  '/titres/:id': { params: { id: titreIdValidator }, download: true },
   '/titres': { download: true },
   '/titres_qgis': { download: true },
   '/demarches': { download: true },
   '/activites': { download: true },
   '/utilisateurs': { download: true },
-  '/etape/zip/:etapeId': { params: { etapeId: z.string() }, download: true },
-  '/etape/:etapeId/:fichierNom': { params: { etapeId: z.string(), fichierNom: z.string() }, download: true },
+  '/etape/zip/:etapeId': { params: { etapeId: etapeIdValidator }, download: true },
+  '/etape/:etapeId/:fichierNom': { params: { etapeId: etapeIdValidator, fichierNom: z.string() }, download: true },
   '/entreprises': { download: true },
 } as const satisfies { [k in CaminoRestRoute]: CaminoRoute<k> }
 
diff --git a/packages/common/src/static/demarchesStatuts.ts b/packages/common/src/static/demarchesStatuts.ts
index 44dda458c..6cca05f41 100644
--- a/packages/common/src/static/demarchesStatuts.ts
+++ b/packages/common/src/static/demarchesStatuts.ts
@@ -1,6 +1,8 @@
 import { Definition } from '../definition.js'
 import { Couleur } from './couleurs.js'
+import { z } from 'zod'
 
+const IDS = ['acc', 'cls', 'dep', 'des', 'eco', 'fpm', 'ind', 'ini', 'ins', 'rej', 'ter'] as const
 export const DemarchesStatutsIds = {
   Accepte: 'acc',
   ClasseSansSuite: 'cls',
@@ -13,9 +15,10 @@ export const DemarchesStatutsIds = {
   EnInstruction: 'ins',
   Rejete: 'rej',
   Termine: 'ter',
-} as const
+} as const satisfies Record<string, (typeof IDS)[number]>
 
-export type DemarcheStatutId = (typeof DemarchesStatutsIds)[keyof typeof DemarchesStatutsIds]
+export const demarcheStatutIdValidator = z.enum(IDS)
+export type DemarcheStatutId = z.infer<typeof demarcheStatutIdValidator>
 
 export type DemarcheStatut<T = DemarcheStatutId> = Definition<T> & { couleur: Couleur }
 
diff --git a/packages/common/src/static/pays.test.ts b/packages/common/src/static/pays.test.ts
index 6192e44e0..57383aea6 100644
--- a/packages/common/src/static/pays.test.ts
+++ b/packages/common/src/static/pays.test.ts
@@ -1,4 +1,4 @@
-import { isPaysId, PAYS_IDS } from './pays.js'
+import { isGuyane, isMetropole, isOutreMer, isPaysId, PAYS_IDS } from './pays.js'
 import { test, expect } from 'vitest'
 
 test('isPaysId', () => {
@@ -11,3 +11,24 @@ test('isPaysId', () => {
     expect(isPaysId(paysId.toLowerCase())).toBe(false)
   })
 })
+
+test('isOutreMer', () => {
+  expect(isOutreMer('FR')).toBe(false)
+  expect(isOutreMer(null)).toBe(false)
+  expect(isOutreMer('GF')).toBe(true)
+  expect(isOutreMer('XX')).toBe(true)
+})
+
+test('isGuyane', () => {
+  expect(isGuyane('FR')).toBe(false)
+  expect(isGuyane(null)).toBe(false)
+  expect(isGuyane('GF')).toBe(true)
+  expect(isGuyane('XX')).toBe(false)
+})
+
+test('isMetropole', () => {
+  expect(isMetropole('FR')).toBe(true)
+  expect(isMetropole(null)).toBe(false)
+  expect(isMetropole('GF')).toBe(false)
+  expect(isMetropole('XX')).toBe(false)
+})
diff --git a/packages/common/src/static/pays.ts b/packages/common/src/static/pays.ts
index 9e15c200d..6a8985113 100644
--- a/packages/common/src/static/pays.ts
+++ b/packages/common/src/static/pays.ts
@@ -46,3 +46,7 @@ export const PaysList: { [key in PaysId]: Pays<key> } = {
 }
 
 export const isPaysId = (value: string): value is PaysId => paysIdValidator.safeParse(value).success
+
+export const isGuyane = (pays: PaysId | null): boolean => pays === 'GF'
+export const isMetropole = (pays: PaysId | null): boolean => pays === 'FR'
+export const isOutreMer = (pays: PaysId | null): boolean => pays !== null && !isMetropole(pays)
diff --git a/packages/common/src/titres.ts b/packages/common/src/titres.ts
index 44e4d63cd..5c9149ed5 100644
--- a/packages/common/src/titres.ts
+++ b/packages/common/src/titres.ts
@@ -19,8 +19,11 @@ import { deviseIdValidator } from './static/devise.js'
 import { z } from 'zod'
 import { administrationIdValidator } from './static/administrations.js'
 
+export const titreIdValidator = z.string().brand<'TitreId'>()
+export type TitreId = z.infer<typeof titreIdValidator>
+
 export const commonTitreValidator = z.object({
-  id: z.string(),
+  id: titreIdValidator,
   nom: z.string(),
   slug: z.string(),
   type_id: titreTypeIdValidator,
@@ -36,7 +39,7 @@ export const commonTitreValidator = z.object({
 
 /** @deprecated use CommonRestTitre */
 export interface CommonTitre {
-  id: string
+  id: TitreId
   nom: string
   slug: string
   typeId: TitreTypeId
diff --git a/packages/ui/src/components/_common/perimetre.stories.tsx b/packages/ui/src/components/_common/perimetre.stories.tsx
index c4ec5c227..98d50fc75 100644
--- a/packages/ui/src/components/_common/perimetre.stories.tsx
+++ b/packages/ui/src/components/_common/perimetre.stories.tsx
@@ -4,6 +4,7 @@ import { MapPattern } from '../_map/pattern'
 import { Perimetre } from './perimetre'
 import { MultiPolygon, Feature } from 'geojson'
 import { Point } from '@/utils/titre-etape-edit'
+import { titreIdValidator } from 'camino-common/src/titres'
 
 const meta: Meta = {
   title: 'Components/Common/Perimetre',
@@ -112,13 +113,13 @@ const tabUpdate = action('tabUpdate')
 export const DefaultNoSnapshot: StoryFn = () => (
   <>
     <MapPattern />
-    <Perimetre titreTypeId="axm" points={points} geojsonMultiPolygon={geojsonMultiPolygon} titreId="id" tabUpdate={tabUpdate} />
+    <Perimetre titreTypeId="axm" points={points} geojsonMultiPolygon={geojsonMultiPolygon} titreId={titreIdValidator.parse('id')} tabUpdate={tabUpdate} />
   </>
 )
 
 export const NoMap: StoryFn = () => (
   <>
     <MapPattern />
-    <Perimetre titreTypeId="axm" geojsonMultiPolygon={geojsonMultiPolygon} titreId="id" tabUpdate={tabUpdate} />
+    <Perimetre titreTypeId="axm" geojsonMultiPolygon={geojsonMultiPolygon} titreId={titreIdValidator.parse('id')} tabUpdate={tabUpdate} />
   </>
 )
diff --git a/packages/ui/src/components/_common/perimetre.tsx b/packages/ui/src/components/_common/perimetre.tsx
index 4874f3ff6..fea7ac083 100644
--- a/packages/ui/src/components/_common/perimetre.tsx
+++ b/packages/ui/src/components/_common/perimetre.tsx
@@ -6,13 +6,14 @@ import { Icon as IconSprite } from '../_ui/iconSpriteType'
 import { Download } from './download'
 import { CamionCommonMap, Props as CaminoCommonMapProps } from './map'
 import { Points } from './points'
+import { TitreId } from 'camino-common/src/titres'
 
 export type TabId = 'carte' | 'points'
 export interface Props {
   points?: Point[]
   geojsonMultiPolygon: CaminoCommonMapProps['geojson']
   titreTypeId: TitreTypeId
-  titreId?: string
+  titreId?: TitreId
   isMain?: boolean
   tabId?: TabId
   tabUpdate: (tabId: TabId) => void
diff --git a/packages/ui/src/components/dashboard/pure-onf-dashboard.stories.tsx b/packages/ui/src/components/dashboard/pure-onf-dashboard.stories.tsx
index ddaa29459..305949394 100644
--- a/packages/ui/src/components/dashboard/pure-onf-dashboard.stories.tsx
+++ b/packages/ui/src/components/dashboard/pure-onf-dashboard.stories.tsx
@@ -1,6 +1,6 @@
 import { PureONFDashboard } from './pure-onf-dashboard'
 import { Meta, StoryFn } from '@storybook/vue3'
-import { CommonTitreONF } from 'camino-common/src/titres'
+import { CommonTitreONF, titreIdValidator } from 'camino-common/src/titres'
 
 const meta: Meta = {
   title: 'Components/Dashboard/ONF',
@@ -13,7 +13,7 @@ export default meta
 
 const onfs: CommonTitreONF[] = [
   {
-    id: 'firstId',
+    id: titreIdValidator.parse('firstId'),
     slug: 'first-id-slug',
     nom: 'first-name',
     titre_statut_id: 'dmi',
@@ -30,7 +30,7 @@ const onfs: CommonTitreONF[] = [
     enAttenteDeONF: true,
   },
   {
-    id: 'secondId',
+    id: titreIdValidator.parse('secondId'),
     slug: 'second-slug',
     nom: 'Second Nom de titre',
     titre_statut_id: 'dmi',
@@ -53,7 +53,7 @@ const onfs: CommonTitreONF[] = [
     enAttenteDeONF: true,
   },
   {
-    id: 'thirdId',
+    id: titreIdValidator.parse('thirdId'),
     slug: 'third-id-slug',
     nom: 'third-name',
     titre_statut_id: 'dmi',
@@ -70,7 +70,7 @@ const onfs: CommonTitreONF[] = [
     enAttenteDeONF: false,
   },
   {
-    id: 'fourthId',
+    id: titreIdValidator.parse('fourthId'),
     slug: 'fourth-slug',
     nom: 'Quatrième Nom de titre',
     titre_statut_id: 'dmi',
diff --git a/packages/ui/src/components/dashboard/pure-ptmg-dashboard.stories.tsx b/packages/ui/src/components/dashboard/pure-ptmg-dashboard.stories.tsx
index f522e1d36..114411362 100644
--- a/packages/ui/src/components/dashboard/pure-ptmg-dashboard.stories.tsx
+++ b/packages/ui/src/components/dashboard/pure-ptmg-dashboard.stories.tsx
@@ -1,6 +1,6 @@
 import { PurePTMGDashboard } from './pure-ptmg-dashboard'
 import { Meta, StoryFn } from '@storybook/vue3'
-import { CommonTitrePTMG } from 'camino-common/src/titres'
+import { CommonTitrePTMG, titreIdValidator } from 'camino-common/src/titres'
 
 const meta: Meta = {
   title: 'Components/Dashboard/PTMG',
@@ -10,7 +10,7 @@ export default meta
 
 const titres: CommonTitrePTMG[] = [
   {
-    id: 'firstId',
+    id: titreIdValidator.parse('firstId'),
     slug: 'first-id-slug',
     nom: 'first-name',
     titre_statut_id: 'dmi',
@@ -24,7 +24,7 @@ const titres: CommonTitrePTMG[] = [
     enAttenteDePTMG: true,
   },
   {
-    id: 'secondId',
+    id: titreIdValidator.parse('secondId'),
     slug: 'second-slug',
     nom: 'Second Nom de titre',
     titre_statut_id: 'dmi',
@@ -44,7 +44,7 @@ const titres: CommonTitrePTMG[] = [
     enAttenteDePTMG: true,
   },
   {
-    id: 'thirdId',
+    id: titreIdValidator.parse('thirdId'),
     slug: 'third-id-slug',
     nom: 'third-name',
     titre_statut_id: 'dmi',
@@ -58,7 +58,7 @@ const titres: CommonTitrePTMG[] = [
     enAttenteDePTMG: false,
   },
   {
-    id: 'fourthId',
+    id: titreIdValidator.parse('fourthId'),
     slug: 'fourth-slug',
     nom: 'Quatrième Nom de titre',
     titre_statut_id: 'dmi',
diff --git a/packages/ui/src/components/dashboard/testData.ts b/packages/ui/src/components/dashboard/testData.ts
index 2da21bb1e..79bc6675a 100644
--- a/packages/ui/src/components/dashboard/testData.ts
+++ b/packages/ui/src/components/dashboard/testData.ts
@@ -1,11 +1,11 @@
 import { toCaminoDate, toCaminoAnnee } from 'camino-common/src/date'
 import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes'
 import { StatistiquesDGTM } from 'camino-common/src/statistiques'
-import { CommonTitreDREAL } from 'camino-common/src/titres'
+import { CommonTitreDREAL, titreIdValidator } from 'camino-common/src/titres'
 
 export const titresDreal: CommonTitreDREAL[] = [
   {
-    id: 'firstId',
+    id: titreIdValidator.parse('firstId'),
     slug: 'first-id-slug',
     nom: 'first-name',
     type_id: 'prm',
@@ -23,7 +23,7 @@ export const titresDreal: CommonTitreDREAL[] = [
     derniereEtape: { date: toCaminoDate('2022-01-01'), etapeTypeId: 'mcr' },
   },
   {
-    id: 'secondId',
+    id: titreIdValidator.parse('secondId'),
     slug: 'second-slug',
     nom: 'Second Nom de titre',
     type_id: 'prm',
@@ -47,7 +47,7 @@ export const titresDreal: CommonTitreDREAL[] = [
     derniereEtape: { date: toCaminoDate('2022-01-01'), etapeTypeId: 'mcr' },
   },
   {
-    id: 'thirdId',
+    id: titreIdValidator.parse('thirdId'),
     slug: 'third-id-slug',
     nom: 'third-name',
     type_id: 'prm',
@@ -65,7 +65,7 @@ export const titresDreal: CommonTitreDREAL[] = [
     derniereEtape: { date: toCaminoDate('2022-01-01'), etapeTypeId: 'mcr' },
   },
   {
-    id: 'fourthId',
+    id: titreIdValidator.parse('fourthId'),
     slug: 'fourth-slug',
     nom: 'Quatrième Nom de titre',
     type_id: 'arc',
diff --git a/packages/ui/src/components/etape/fondamentales-edit.stories.ts b/packages/ui/src/components/etape/fondamentales-edit.stories.ts
index 622c8a66f..d51aa86e8 100644
--- a/packages/ui/src/components/etape/fondamentales-edit.stories.ts
+++ b/packages/ui/src/components/etape/fondamentales-edit.stories.ts
@@ -1,6 +1,6 @@
 import { FondamentalesEdit, Props } from './fondamentales-edit'
 import { Meta, StoryFn } from '@storybook/vue3'
-import { EtapeFondamentale } from 'camino-common/src/etape'
+import { EtapeFondamentale, etapeIdValidator } from 'camino-common/src/etape'
 import { newEntrepriseId } from 'camino-common/src/entreprise'
 import { toCaminoDate } from 'camino-common/src/date'
 import { testBlankUser } from 'camino-common/src/tests-utils'
@@ -13,7 +13,7 @@ const meta: Meta = {
 export default meta
 
 const etape: EtapeFondamentale = {
-  id: 'id',
+  id: etapeIdValidator.parse('id'),
   type: {
     id: 'mfr',
     nom: 'demande',
diff --git a/packages/ui/src/components/titre/edit-popup.stories.tsx b/packages/ui/src/components/titre/edit-popup.stories.tsx
index e4ecaa01b..ce42f643a 100644
--- a/packages/ui/src/components/titre/edit-popup.stories.tsx
+++ b/packages/ui/src/components/titre/edit-popup.stories.tsx
@@ -1,6 +1,7 @@
 import { EditPopup } from './edit-popup'
 import { Meta, StoryFn } from '@storybook/vue3'
 import { action } from '@storybook/addon-actions'
+import { titreIdValidator } from 'camino-common/src/titres'
 
 const meta: Meta = {
   title: 'Components/Titre/EditPopup',
@@ -15,7 +16,7 @@ const close = action('close')
 export const DefaultNoReference: StoryFn = () => (
   <EditPopup
     titre={{
-      id: 'id',
+      id: titreIdValidator.parse('id'),
       nom: 'Nom du titre',
       references: [],
     }}
@@ -30,7 +31,7 @@ export const DefaultNoReference: StoryFn = () => (
 export const OneReference: StoryFn = () => (
   <EditPopup
     titre={{
-      id: 'id',
+      id: titreIdValidator.parse('id'),
       nom: 'Nom du titre',
       references: [{ nom: 'RefValue', referenceTypeId: 'brg' }],
     }}
diff --git a/packages/ui/src/components/titre/header.stories.tsx b/packages/ui/src/components/titre/header.stories.tsx
index bbfeed6e1..4abe98f37 100644
--- a/packages/ui/src/components/titre/header.stories.tsx
+++ b/packages/ui/src/components/titre/header.stories.tsx
@@ -4,6 +4,7 @@ import { action } from '@storybook/addon-actions'
 import { testBlankUser } from 'camino-common/src/tests-utils'
 import { TitreApiClient } from './titre-api-client'
 import { toCaminoDate } from 'camino-common/src/date'
+import { titreIdValidator } from 'camino-common/src/titres'
 
 const meta: Meta = {
   title: 'Components/Titre/Header',
@@ -39,7 +40,7 @@ const apiClientMock: Pick<TitreApiClient, 'titreUtilisateurAbonne' | 'editTitre'
 export const Default: StoryFn = () => (
   <PureHeader
     titre={{
-      id: 'id',
+      id: titreIdValidator.parse('id'),
       references: [],
       abonnement: false,
       modification: false,
@@ -55,7 +56,7 @@ export const Default: StoryFn = () => (
 export const AbonneAuTitre: StoryFn = () => (
   <PureHeader
     titre={{
-      id: 'id',
+      id: titreIdValidator.parse('id'),
       references: [],
       abonnement: true,
       modification: false,
@@ -71,7 +72,7 @@ export const AbonneAuTitre: StoryFn = () => (
 export const CanDeleteTitre: StoryFn = () => (
   <PureHeader
     titre={{
-      id: 'id',
+      id: titreIdValidator.parse('id'),
       references: [],
       abonnement: false,
       modification: false,
@@ -87,7 +88,7 @@ export const CanDeleteTitre: StoryFn = () => (
 export const CanEditTitre: StoryFn = () => (
   <PureHeader
     titre={{
-      id: 'id',
+      id: titreIdValidator.parse('id'),
       references: [{ nom: 'cette-ref', referenceTypeId: 'brg' }],
       abonnement: false,
       modification: true,
@@ -103,7 +104,7 @@ export const CanEditTitre: StoryFn = () => (
 export const Loading: StoryFn = () => (
   <PureHeader
     titre={{
-      id: 'id',
+      id: titreIdValidator.parse('id'),
       references: [{ nom: 'cette-ref', referenceTypeId: 'brg' }],
       abonnement: false,
       modification: true,
@@ -124,7 +125,7 @@ export const Loading: StoryFn = () => (
 export const WithError: StoryFn = () => (
   <PureHeader
     titre={{
-      id: 'id',
+      id: titreIdValidator.parse('id'),
       references: [{ nom: 'cette-ref', referenceTypeId: 'brg' }],
       abonnement: false,
       modification: true,
diff --git a/packages/ui/src/components/titre/header.tsx b/packages/ui/src/components/titre/header.tsx
index 2b22b16f0..ad916135b 100644
--- a/packages/ui/src/components/titre/header.tsx
+++ b/packages/ui/src/components/titre/header.tsx
@@ -3,7 +3,7 @@ import { canDeleteTitre } from 'camino-common/src/permissions/titres'
 import { User } from 'camino-common/src/roles'
 import { ReferenceTypeId } from 'camino-common/src/static/referencesTypes'
 import { TitreTypeId } from 'camino-common/src/static/titresTypes'
-import { EditableTitre } from 'camino-common/src/titres'
+import { EditableTitre, TitreId } from 'camino-common/src/titres'
 import { computed, ref, watch } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { useStore } from 'vuex'
@@ -17,7 +17,7 @@ import { LoadingElement } from '../_ui/functional-loader'
 
 interface Props {
   titre: {
-    id: string
+    id: TitreId
     nom: string
     typeId: TitreTypeId
     abonnement: boolean
@@ -73,7 +73,7 @@ export const Header = caminoDefineComponent<Props>(['titre', 'titreEventTrack'],
     store.dispatch('messageAdd', { value: 'le titre a été mis à jour', type: 'success' }, { root: true })
   }
 
-  const abonne = async (titreId: string, abonner: boolean) => {
+  const abonne = async (titreId: TitreId, abonner: boolean) => {
     await titreApiClient.titreUtilisateurAbonne(titreId, abonner)
     store.commit('titre/set', { ...props.titre, abonnement: abonner })
 
diff --git a/packages/ui/src/components/titre/infos.stories.tsx b/packages/ui/src/components/titre/infos.stories.tsx
index 8f36107cf..601e5af2d 100644
--- a/packages/ui/src/components/titre/infos.stories.tsx
+++ b/packages/ui/src/components/titre/infos.stories.tsx
@@ -1,8 +1,10 @@
 import { Meta, StoryFn } from '@storybook/vue3'
 import { Infos, Props } from './infos'
-import { Section, TitreLink, TitreLinks } from 'camino-common/src/titres'
+import { Section, TitreId, TitreLink, TitreLinks, titreIdValidator } from 'camino-common/src/titres'
 import { testBlankUser } from 'camino-common/src/tests-utils'
 import { toCaminoDate } from 'camino-common/src/date'
+import { demarcheIdValidator } from 'camino-common/src/demarche'
+import { entrepriseIdValidator } from 'camino-common/src/entreprise'
 
 const meta: Meta = {
   title: 'Components/Titre/Infos',
@@ -10,14 +12,14 @@ const meta: Meta = {
 }
 export default meta
 
-const titresTo: TitreLink[] = [{ id: 'id10', nom: 'Titre fils' }]
-const titresFrom: TitreLink[] = [{ id: 'id11', nom: 'Titre père' }]
+const titresTo: TitreLink[] = [{ id: titreIdValidator.parse('id10'), nom: 'Titre fils' }]
+const titresFrom: TitreLink[] = [{ id: titreIdValidator.parse('id11'), nom: 'Titre père' }]
 
 const apiClient: Props['apiClient'] = {
   loadLinkableTitres: () => () => Promise.resolve([]),
   loadTitreLinks: () => Promise.resolve({ aval: titresTo, amont: titresFrom }),
   linkTitres: () => new Promise<TitreLinks>(resolve => resolve({ aval: titresTo, amont: titresFrom })),
-  loadTitreSections: (_titreId: string) =>
+  loadTitreSections: (_titreId: TitreId) =>
     new Promise<Section[]>(resolve =>
       resolve([
         {
@@ -42,19 +44,19 @@ export const Default: StoryFn = () => (
   <Infos
     currentDay={toCaminoDate('2023-04-06')}
     titre={{
-      id: 'fakeId',
+      id: titreIdValidator.parse('fakeId'),
       typeId: 'arm',
       contenu: { arm: { mecanisation: true } },
       titreStatutId: 'val',
       demarches: [
         {
-          id: 'oct',
+          id: demarcheIdValidator.parse('oct'),
           demarcheDateDebut: toCaminoDate('2020-01-01'),
           demarcheDateFin: toCaminoDate('2022-01-01'),
           typeId: 'oct',
         },
         {
-          id: 'pro',
+          id: demarcheIdValidator.parse('pro'),
           demarcheDateDebut: toCaminoDate('2022-01-01'),
           demarcheDateFin: toCaminoDate('2025-01-01'),
           typeId: 'pro',
@@ -63,13 +65,13 @@ export const Default: StoryFn = () => (
       administrations: ['ope-onf-973-01'],
       titulaires: [
         {
-          id: 'entreprise1',
+          id: entrepriseIdValidator.parse('entreprise1'),
           nom: 'Entreprise 1',
           legalSiren: 'Entreprise 1 Siren',
           operateur: true,
         },
         {
-          id: 'entreprise2',
+          id: entrepriseIdValidator.parse('entreprise2'),
           nom: 'Entreprise 2',
           legalSiren: 'Entreprise 2 Siren',
           operateur: false,
@@ -77,7 +79,7 @@ export const Default: StoryFn = () => (
       ],
       amodiataires: [
         {
-          id: 'entreprise3',
+          id: entrepriseIdValidator.parse('entreprise3'),
           nom: 'Entreprise 3',
           legalSiren: 'Entreprise 3 Siren',
           operateur: false,
@@ -95,7 +97,7 @@ export const Empty: StoryFn = () => (
   <Infos
     currentDay={toCaminoDate('2023-04-06')}
     titre={{
-      id: 'fakeId',
+      id: titreIdValidator.parse('fakeId'),
       typeId: 'arm',
       contenu: {},
       titreStatutId: 'dmi',
diff --git a/packages/ui/src/components/titre/infos.tsx b/packages/ui/src/components/titre/infos.tsx
index c2df47383..c6cbb9a55 100644
--- a/packages/ui/src/components/titre/infos.tsx
+++ b/packages/ui/src/components/titre/infos.tsx
@@ -20,20 +20,22 @@ import { LoadingElement } from '@/components/_ui/functional-loader'
 import { Sections } from '../_common/new-section'
 import { FunctionalComponent, onMounted, ref } from 'vue'
 import { AsyncData } from '../../api/client-rest'
-import { Section } from 'camino-common/src/titres'
+import { Section, TitreId } from 'camino-common/src/titres'
 import { caminoDefineComponent } from '@/utils/vue-tsx-utils'
 import { CaminoDate, getCurrent } from 'camino-common/src/date'
 import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools'
+import { DemarcheId } from 'camino-common/src/demarche'
+import { EntrepriseId } from 'camino-common/src/entreprise'
 
 export interface Entreprise {
-  id: string
+  id: EntrepriseId
   nom: string
   legalSiren?: string
   operateur: boolean
 }
 
 interface Demarche {
-  id: string
+  id: DemarcheId
   typeId: DemarcheTypeId
   demarcheDateDebut: CaminoDate | null
   demarcheDateFin: CaminoDate | null
@@ -42,7 +44,7 @@ interface Demarche {
 export interface Props {
   currentDay?: CaminoDate
   titre: {
-    id: string
+    id: TitreId
     typeId: TitreTypeId
     titreStatutId: TitreStatutId
     demarches: Demarche[]
diff --git a/packages/ui/src/components/titre/territoires.stories.tsx b/packages/ui/src/components/titre/territoires.stories.tsx
index 608d01d9b..ab5714324 100644
--- a/packages/ui/src/components/titre/territoires.stories.tsx
+++ b/packages/ui/src/components/titre/territoires.stories.tsx
@@ -3,6 +3,7 @@ import { Territoires } from './territoires'
 import { Meta, StoryFn } from '@storybook/vue3'
 import { toCommuneId } from 'camino-common/src/static/communes'
 import { TitreApiClient } from './titre-api-client'
+import { titreIdValidator } from 'camino-common/src/titres'
 
 const meta: Meta = {
   title: 'Components/Titre/Territoires',
@@ -27,19 +28,35 @@ const apiClient: Pick<TitreApiClient, 'getTitreCommunes'> = {
   },
 }
 
-export const OnlyCommunes: StoryFn = () => <Territoires surface={0} forets={[]} titreId="titreId" secteursMaritimes={[]} apiClient={apiClient} />
-export const OnlySurface: StoryFn = () => <Territoires surface={4} forets={[]} titreId="pasDeCommunes" secteursMaritimes={[]} apiClient={apiClient} />
-export const OnlyForets: StoryFn = () => <Territoires surface={0} forets={['3PI', 'BEL']} titreId="pasDeCommunes" secteursMaritimes={[]} apiClient={apiClient} />
-export const OnlySdomZones: StoryFn = () => <Territoires surface={0} forets={[]} titreId="pasDeCommunes" secteursMaritimes={[]} sdomZones={['1', '2']} apiClient={apiClient} />
+export const OnlyCommunes: StoryFn = () => <Territoires surface={0} forets={[]} titreId={titreIdValidator.parse('titreId')} secteursMaritimes={[]} apiClient={apiClient} />
+export const OnlySurface: StoryFn = () => <Territoires surface={4} forets={[]} titreId={titreIdValidator.parse('pasDeCommunes')} secteursMaritimes={[]} apiClient={apiClient} />
+export const OnlyForets: StoryFn = () => <Territoires surface={0} forets={['3PI', 'BEL']} titreId={titreIdValidator.parse('pasDeCommunes')} secteursMaritimes={[]} apiClient={apiClient} />
+export const OnlySdomZones: StoryFn = () => (
+  <Territoires surface={0} forets={[]} titreId={titreIdValidator.parse('pasDeCommunes')} secteursMaritimes={[]} sdomZones={['1', '2']} apiClient={apiClient} />
+)
 export const OnlySecteursMaritimes: StoryFn = () => (
-  <Territoires surface={0} forets={[]} titreId="pasDeCommunes" secteursMaritimes={['Balagne', 'Bretagne nord', 'Bretagne sud']} sdomZones={[]} apiClient={apiClient} />
+  <Territoires surface={0} forets={[]} titreId={titreIdValidator.parse('pasDeCommunes')} secteursMaritimes={['Balagne', 'Bretagne nord', 'Bretagne sud']} sdomZones={[]} apiClient={apiClient} />
 )
 export const All: StoryFn = () => (
-  <Territoires surface={4} forets={['BEL', 'AMO']} secteursMaritimes={['Balagne', 'Bretagne nord', 'Bretagne sud']} sdomZones={['1', '0']} titreId="titreId" apiClient={apiClient} />
+  <Territoires
+    surface={4}
+    forets={['BEL', 'AMO']}
+    secteursMaritimes={['Balagne', 'Bretagne nord', 'Bretagne sud']}
+    sdomZones={['1', '0']}
+    titreId={titreIdValidator.parse('titreId')}
+    apiClient={apiClient}
+  />
 )
 
-export const Empty: StoryFn = () => <Territoires apiClient={apiClient} forets={[]} titreId="pasDeCommunes" secteursMaritimes={[]} />
-export const Loading: StoryFn = () => <Territoires apiClient={{ getTitreCommunes: () => new Promise(() => ({})) }} forets={['BEL', 'AMO']} titreId="titreId" secteursMaritimes={[]} />
+export const Empty: StoryFn = () => <Territoires apiClient={apiClient} forets={[]} titreId={titreIdValidator.parse('pasDeCommunes')} secteursMaritimes={[]} />
+export const Loading: StoryFn = () => (
+  <Territoires apiClient={{ getTitreCommunes: () => new Promise(() => ({})) }} forets={['BEL', 'AMO']} titreId={titreIdValidator.parse('titreId')} secteursMaritimes={[]} />
+)
 export const WithError: StoryFn = () => (
-  <Territoires apiClient={{ getTitreCommunes: () => Promise.reject(new Error('Chargement impossible des communes')) }} forets={['BEL', 'AMO']} titreId="titreId" secteursMaritimes={[]} />
+  <Territoires
+    apiClient={{ getTitreCommunes: () => Promise.reject(new Error('Chargement impossible des communes')) }}
+    forets={['BEL', 'AMO']}
+    titreId={titreIdValidator.parse('titreId')}
+    secteursMaritimes={[]}
+  />
 )
diff --git a/packages/ui/src/components/titre/territoires.tsx b/packages/ui/src/components/titre/territoires.tsx
index ef94f5284..6d6c292b6 100644
--- a/packages/ui/src/components/titre/territoires.tsx
+++ b/packages/ui/src/components/titre/territoires.tsx
@@ -1,4 +1,4 @@
-import { DepartementId, Departements, toDepartementId } from 'camino-common/src/static/departement'
+import { DepartementId, DepartementLabel, Departements, toDepartementId } from 'camino-common/src/static/departement'
 import { getFacadesComputed, SecteursMaritimes, FacadeComputed } from 'camino-common/src/static/facades'
 import { PaysId, PAYS_IDS } from 'camino-common/src/static/pays'
 import { Regions } from 'camino-common/src/static/region'
@@ -12,6 +12,7 @@ import { LoadingElement } from '../_ui/functional-loader'
 import { caminoDefineComponent } from '../../utils/vue-tsx-utils'
 import { AsyncData } from '../../api/client-rest'
 import { TitreApiClient } from './titre-api-client'
+import { TitreId } from 'camino-common/src/titres'
 
 export interface TerritoiresCommune {
   id: CommuneId
@@ -22,7 +23,7 @@ export interface TerritoiresProps {
   surface?: number
   forets: ForetId[]
   sdomZones?: SDOMZoneId[]
-  titreId: string
+  titreId: TitreId
   secteursMaritimes: SecteursMaritimes[]
 }
 
@@ -30,7 +31,7 @@ type RegionsComputed = {
   id: string
   nom: string
   paysId: PaysId
-  departements: { id: DepartementId; nom: string; communes: string[] }[]
+  departements: { id: DepartementId; nom: DepartementLabel; communes: string[] }[]
 }[]
 
 function CommunesEtRegions({ communes }: { communes: Commune[] }) {
diff --git a/packages/ui/src/components/titre/titre-api-client.ts b/packages/ui/src/components/titre/titre-api-client.ts
index 66f1dd565..e28a40fd3 100644
--- a/packages/ui/src/components/titre/titre-api-client.ts
+++ b/packages/ui/src/components/titre/titre-api-client.ts
@@ -1,38 +1,38 @@
-import { EditableTitre, Section, TitreGet } from 'camino-common/src/titres'
+import { EditableTitre, Section, TitreGet, TitreId } from 'camino-common/src/titres'
 import { deleteWithJson, getWithJson, postWithJson } from '../../api/client-rest'
 import { CaminoDate } from 'camino-common/src/date'
 import { Commune } from 'camino-common/src/static/communes'
 
 export interface TitreApiClient {
-  loadTitreSections: (titreId: string) => Promise<Section[]>
-  removeTitre: (titreId: string) => Promise<void>
-  titreUtilisateurAbonne: (titreId: string, abonne: boolean) => Promise<void>
+  loadTitreSections: (titreId: TitreId) => Promise<Section[]>
+  removeTitre: (titreId: TitreId) => Promise<void>
+  titreUtilisateurAbonne: (titreId: TitreId, abonne: boolean) => Promise<void>
   editTitre: (titre: EditableTitre) => Promise<void>
-  getTitreById: (titreId: string) => Promise<TitreGet>
-  getLastModifiedDate: (titreId: string) => Promise<CaminoDate | null>
-  getTitreCommunes: (titreId: string) => Promise<Commune[]>
+  getTitreById: (titreId: TitreId) => Promise<TitreGet>
+  getLastModifiedDate: (titreId: TitreId) => Promise<CaminoDate | null>
+  getTitreCommunes: (titreId: TitreId) => Promise<Commune[]>
 }
 
 export const titreApiClient: TitreApiClient = {
-  loadTitreSections: async (titreId: string): Promise<Section[]> => {
+  loadTitreSections: async (titreId: TitreId): Promise<Section[]> => {
     return getWithJson('/rest/titreSections/:titreId', { titreId })
   },
-  removeTitre: async (titreId: string): Promise<void> => {
+  removeTitre: async (titreId: TitreId): Promise<void> => {
     return deleteWithJson('/rest/titres/:titreId', { titreId })
   },
-  titreUtilisateurAbonne: async (titreId: string, abonne: boolean): Promise<void> => {
+  titreUtilisateurAbonne: async (titreId: TitreId, abonne: boolean): Promise<void> => {
     return postWithJson('/rest/titres/:titreId/abonne', { titreId }, { abonne })
   },
   editTitre: (titre: EditableTitre): Promise<void> => {
     return postWithJson('/rest/titres/:titreId', { titreId: titre.id }, titre)
   },
-  getTitreById: (titreId: string): Promise<TitreGet> => {
+  getTitreById: (titreId: TitreId): Promise<TitreGet> => {
     return getWithJson('/rest/titres/:titreId', { titreId })
   },
-  getLastModifiedDate: (titreId: string): Promise<CaminoDate | null> => {
+  getLastModifiedDate: (titreId: TitreId): Promise<CaminoDate | null> => {
     return getWithJson('/rest/titres/:titreId/date', { titreId })
   },
-  getTitreCommunes: (id: string): Promise<Commune[]> => {
+  getTitreCommunes: (id: TitreId): Promise<Commune[]> => {
     return getWithJson('/rest/titres/:id/communes', { id })
   },
 }
diff --git a/packages/ui/src/components/titre/titres-link-form-api-client.ts b/packages/ui/src/components/titre/titres-link-form-api-client.ts
index 975b06977..0326042d8 100644
--- a/packages/ui/src/components/titre/titres-link-form-api-client.ts
+++ b/packages/ui/src/components/titre/titres-link-form-api-client.ts
@@ -4,7 +4,7 @@ import { getLinkConfig } from 'camino-common/src/permissions/titres'
 import { apiGraphQLFetch } from '@/api/_client'
 import gql from 'graphql-tag'
 
-import { TitreLink, TitreLinks } from 'camino-common/src/titres'
+import { TitreId, TitreLink, TitreLinks } from 'camino-common/src/titres'
 import { TitreStatutId } from 'camino-common/src/static/titresStatuts'
 import { getWithJson, postWithJson } from '@/api/client-rest'
 import { CaminoDate } from 'camino-common/src/date'
@@ -12,11 +12,11 @@ import { CaminoDate } from 'camino-common/src/date'
 export type TitresLinkConfig =
   | {
       type: 'single'
-      selectedTitreId: string | null
+      selectedTitreId: TitreId | null
     }
   | {
       type: 'multiple'
-      selectedTitreIds: string[]
+      selectedTitreIds: TitreId[]
     }
 
 type TitreLinkDemarche = { demarcheDateDebut: CaminoDate | null; demarcheDateFin: CaminoDate | null }
@@ -26,17 +26,17 @@ export type LinkableTitre = TitreLink & {
 }
 
 export interface TitresLinkFormApiClient {
-  linkTitres: (titreId: string, titreFromIds: string[]) => Promise<TitreLinks>
-  loadTitreLinks: (titreId: string) => Promise<TitreLinks>
+  linkTitres: (titreId: TitreId, titreFromIds: TitreId[]) => Promise<TitreLinks>
+  loadTitreLinks: (titreId: TitreId) => Promise<TitreLinks>
   loadLinkableTitres: (titreTypeId: TitreTypeId, demarches: { typeId: DemarcheTypeId }[]) => () => Promise<LinkableTitre[]>
 }
 
 export const titresLinkFormApiClient: TitresLinkFormApiClient = {
-  linkTitres: async (titreId: string, titreFromIds: string[]): Promise<TitreLinks> => {
+  linkTitres: async (titreId: TitreId, titreFromIds: TitreId[]): Promise<TitreLinks> => {
     return await postWithJson('/rest/titres/:id/titreLiaisons', { id: titreId }, titreFromIds)
   },
 
-  loadTitreLinks: async (titreId: string) => {
+  loadTitreLinks: async (titreId: TitreId) => {
     return await getWithJson('/rest/titres/:id/titreLiaisons', { id: titreId })
   },
 
diff --git a/packages/ui/src/components/titre/titres-link-form.stories.tsx b/packages/ui/src/components/titre/titres-link-form.stories.tsx
index 31f7a74f7..273f403a4 100644
--- a/packages/ui/src/components/titre/titres-link-form.stories.tsx
+++ b/packages/ui/src/components/titre/titres-link-form.stories.tsx
@@ -1,6 +1,6 @@
 import { TitresLinkForm, Props } from './titres-link-form'
 import { Meta, StoryFn } from '@storybook/vue3'
-import { TitreLink, TitreLinks } from 'camino-common/src/titres'
+import { TitreLink, TitreLinks, titreIdValidator } from 'camino-common/src/titres'
 import { LinkableTitre } from '@/components/titre/titres-link-form-api-client'
 import { testBlankUser } from 'camino-common/src/tests-utils'
 import { toCaminoDate } from 'camino-common/src/date'
@@ -14,7 +14,7 @@ export default meta
 
 const linkableTitres: LinkableTitre[] = [
   {
-    id: 'id1',
+    id: titreIdValidator.parse('id1'),
     nom: 'Abttis Coucou',
     titreStatutId: 'ech',
     demarches: [
@@ -25,7 +25,7 @@ const linkableTitres: LinkableTitre[] = [
     ],
   },
   {
-    id: 'id2',
+    id: titreIdValidator.parse('id2'),
     nom: 'Affluent Crique Saint Bernard',
     titreStatutId: 'ech',
     demarches: [
@@ -36,7 +36,7 @@ const linkableTitres: LinkableTitre[] = [
     ],
   },
   {
-    id: 'id3',
+    id: titreIdValidator.parse('id3'),
     nom: 'Nouveau titre',
     titreStatutId: 'ech',
     demarches: [
@@ -48,7 +48,7 @@ const linkableTitres: LinkableTitre[] = [
   },
 ]
 
-const titresTo: TitreLink[] = [{ id: 'id10', nom: 'Titre fils' }]
+const titresTo: TitreLink[] = [{ id: titreIdValidator.parse('id10'), nom: 'Titre fils' }]
 const titresFrom: TitreLink[] = [linkableTitres[0]]
 
 const apiClient: Props['apiClient'] = {
@@ -58,7 +58,7 @@ const apiClient: Props['apiClient'] = {
 }
 
 export const AxmWithAlreadySelectedTitre: StoryFn = () => (
-  <TitresLinkForm user={{ role: 'super', ...testBlankUser }} titre={{ typeId: 'axm', administrations: [], id: 'titreId', demarches: [] }} apiClient={apiClient} />
+  <TitresLinkForm user={{ role: 'super', ...testBlankUser }} titre={{ typeId: 'axm', administrations: [], id: titreIdValidator.parse('titreId'), demarches: [] }} apiClient={apiClient} />
 )
 
 export const FusionWithAlreadySelectedTitre: StoryFn = () => (
@@ -67,7 +67,7 @@ export const FusionWithAlreadySelectedTitre: StoryFn = () => (
     titre={{
       typeId: 'cxm',
       administrations: [],
-      id: 'titreId',
+      id: titreIdValidator.parse('titreId'),
       demarches: [{ typeId: 'fus' }],
     }}
     apiClient={apiClient}
@@ -77,7 +77,7 @@ export const FusionWithAlreadySelectedTitre: StoryFn = () => (
 export const TitreWithTitreLinksLoading: StoryFn = () => (
   <TitresLinkForm
     user={{ role: 'super', ...testBlankUser }}
-    titre={{ typeId: 'axm', administrations: [], id: 'titreId', demarches: [] }}
+    titre={{ typeId: 'axm', administrations: [], id: titreIdValidator.parse('titreId'), demarches: [] }}
     apiClient={{
       ...apiClient,
       loadTitreLinks: () => new Promise<TitreLinks>(() => ({})),
@@ -86,5 +86,5 @@ export const TitreWithTitreLinksLoading: StoryFn = () => (
 )
 
 export const DefautCantUpdateLinks: StoryFn = () => (
-  <TitresLinkForm user={{ role: 'defaut', ...testBlankUser }} titre={{ typeId: 'axm', administrations: [], id: 'titreId', demarches: [] }} apiClient={apiClient} />
+  <TitresLinkForm user={{ role: 'defaut', ...testBlankUser }} titre={{ typeId: 'axm', administrations: [], id: titreIdValidator.parse('titreId'), demarches: [] }} apiClient={apiClient} />
 )
diff --git a/packages/ui/src/components/titre/titres-link-form.tsx b/packages/ui/src/components/titre/titres-link-form.tsx
index bafe16b0c..0c70080ce 100644
--- a/packages/ui/src/components/titre/titres-link-form.tsx
+++ b/packages/ui/src/components/titre/titres-link-form.tsx
@@ -9,14 +9,14 @@ import { AsyncData } from '@/api/client-rest'
 import { LoadingElement } from '@/components/_ui/functional-loader'
 import { Icon } from '@/components/_ui/icon'
 import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes'
-import { TitreLink, TitreLinks } from 'camino-common/src/titres'
+import { TitreId, TitreLink, TitreLinks } from 'camino-common/src/titres'
 import { ApiClient } from '@/api/api-client'
 import { TitresLinkConfig } from '@/components/titre/titres-link-form-api-client'
 
 export interface Props {
   user: User
   titre: {
-    id: string
+    id: TitreId
     typeId: TitreTypeId
     administrations: AdministrationId[]
     demarches: { typeId: DemarcheTypeId }[]
diff --git a/packages/ui/src/components/titre/titres-link.stories.tsx b/packages/ui/src/components/titre/titres-link.stories.tsx
index 2b05573f3..b3c623f13 100644
--- a/packages/ui/src/components/titre/titres-link.stories.tsx
+++ b/packages/ui/src/components/titre/titres-link.stories.tsx
@@ -3,6 +3,7 @@ import { Meta, StoryFn } from '@storybook/vue3'
 import { LinkableTitre } from '@/components/titre/titres-link-form-api-client'
 import { action } from '@storybook/addon-actions'
 import { toCaminoDate } from 'camino-common/src/date'
+import { titreIdValidator } from 'camino-common/src/titres'
 
 const meta: Meta = {
   title: 'Components/Titre/TitresLink',
@@ -13,7 +14,7 @@ export default meta
 
 const titres: LinkableTitre[] = [
   {
-    id: 'id1',
+    id: titreIdValidator.parse('id1'),
     nom: 'Abttis Coucou',
     titreStatutId: 'ech',
     demarches: [
@@ -24,7 +25,7 @@ const titres: LinkableTitre[] = [
     ],
   },
   {
-    id: 'id2',
+    id: titreIdValidator.parse('id2'),
     nom: 'Affluent Crique Saint Bernard',
     titreStatutId: 'ech',
     demarches: [
@@ -35,7 +36,7 @@ const titres: LinkableTitre[] = [
     ],
   },
   {
-    id: 'id3',
+    id: titreIdValidator.parse('id3'),
     nom: 'Nouveau titre',
     titreStatutId: 'ech',
     demarches: [
@@ -53,7 +54,12 @@ export const AXM: StoryFn = () => (
 )
 
 export const AXMWithAlreadySelectedTitre: StoryFn = () => (
-  <TitresLink config={{ type: 'single', selectedTitreId: 'id1' }} loadLinkableTitres={() => Promise.resolve(titres)} onSelectTitre={onSelectTitre} onSelectTitres={onSelectTitres} />
+  <TitresLink
+    config={{ type: 'single', selectedTitreId: titreIdValidator.parse('id1') }}
+    loadLinkableTitres={() => Promise.resolve(titres)}
+    onSelectTitre={onSelectTitre}
+    onSelectTitres={onSelectTitres}
+  />
 )
 
 export const DemarcheFusion: StoryFn = () => (
@@ -61,14 +67,19 @@ export const DemarcheFusion: StoryFn = () => (
 )
 
 export const DemarcheFusionWithAlreadySelectedTitre: StoryFn = () => (
-  <TitresLink config={{ type: 'multiple', selectedTitreIds: ['id1', 'id2'] }} loadLinkableTitres={() => Promise.resolve(titres)} onSelectTitre={onSelectTitre} onSelectTitres={onSelectTitres} />
+  <TitresLink
+    config={{ type: 'multiple', selectedTitreIds: [titreIdValidator.parse('id1'), titreIdValidator.parse('id2')] }}
+    loadLinkableTitres={() => Promise.resolve(titres)}
+    onSelectTitre={onSelectTitre}
+    onSelectTitres={onSelectTitres}
+  />
 )
 
 export const Loading: StoryFn = () => (
   <TitresLink
     config={{
       type: 'multiple',
-      selectedTitreIds: ['id1'],
+      selectedTitreIds: [titreIdValidator.parse('id1')],
     }}
     loadLinkableTitres={() => new Promise<LinkableTitre[]>(resolve => {})}
     onSelectTitre={onSelectTitre}
@@ -80,7 +91,7 @@ export const WithError: StoryFn = () => (
   <TitresLink
     config={{
       type: 'multiple',
-      selectedTitreIds: ['id1'],
+      selectedTitreIds: [titreIdValidator.parse('id1')],
     }}
     loadLinkableTitres={() => Promise.reject(new Error('because reasons'))}
     onSelectTitre={onSelectTitre}
diff --git a/packages/ui/src/utils/titre-etape-edit.test.ts b/packages/ui/src/utils/titre-etape-edit.test.ts
index 5a9147958..c023150d0 100644
--- a/packages/ui/src/utils/titre-etape-edit.test.ts
+++ b/packages/ui/src/utils/titre-etape-edit.test.ts
@@ -2,6 +2,7 @@ import { etapeEditFormat } from './titre-etape-edit'
 import { GEO_SYSTEME_IDS } from 'camino-common/src/static/geoSystemes'
 import { describe, expect, test } from 'vitest'
 import { newEntrepriseId } from 'camino-common/src/entreprise'
+import { etapeIdValidator } from 'camino-common/src/etape'
 
 // dateFormat
 describe('etapeEditFormat', () => {
@@ -9,7 +10,7 @@ describe('etapeEditFormat', () => {
     expect(
       // @ts-ignore
       etapeEditFormat({
-        id: 'etape-id',
+        id: etapeIdValidator.parse('etape-id'),
       })
     ).toEqual({
       id: 'etape-id',
@@ -38,7 +39,7 @@ describe('etapeEditFormat', () => {
     expect(
       // @ts-ignore
       etapeEditFormat({
-        id: 'etape-id',
+        id: etapeIdValidator.parse('etape-id'),
         points: [
           {
             id: 'point-id-111',
@@ -98,7 +99,7 @@ describe('etapeEditFormat', () => {
 
     expect(
       etapeEditFormat({
-        id: 'etape-id',
+        id: etapeIdValidator.parse('etape-id'),
         type: { id: 'aac', nom: 'plop' },
         // @ts-ignore
         statutId: 'etape-statut-id',
-- 
GitLab