diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000000000000000000000000000000000000..b450dbcf34d580a2d7ce598133e33273ce6eca55
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+**/vitest.config.ts
diff --git a/package.json b/package.json
index 7eac8e71eec99b87f6bcfef8b4daff2d8b1a6352..6856bcb52d6f87afb1c62a92de44548cb8b8a8e3 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
       "prettier --write"
     ],
     "packages/api/**/*.{graphql,md}": "prettier --write",
-    "packages/common/**/*.ts": [
+    "packages/common/src/**/*.ts": [
       "eslint --cache --fix --max-warnings=0",
       "prettier --write"
     ],
diff --git a/packages/api/src/api/rest/etapes.test.integration.ts b/packages/api/src/api/rest/etapes.test.integration.ts
index 1e7f8b976e88fe305211c959a76026471d39e4ea..826ab75acd9d1fbf087553e6abfa1d19a20e17f1 100644
--- a/packages/api/src/api/rest/etapes.test.integration.ts
+++ b/packages/api/src/api/rest/etapes.test.integration.ts
@@ -3,7 +3,7 @@ import { titreCreate } from '../../database/queries/titres'
 import { titreDemarcheCreate } from '../../database/queries/titres-demarches'
 import { userSuper } from '../../database/user-super'
 import { restCall, restDeleteCall } from '../../../tests/_utils/index'
-import { caminoDateValidator, getCurrent, toCaminoDate } from 'camino-common/src/date'
+import { caminoDateValidator, toCaminoDate } from 'camino-common/src/date'
 import { afterAll, beforeAll, test, expect, describe, vi } from 'vitest'
 import type { Pool } from 'pg'
 import { HTTP_STATUS } from 'camino-common/src/http'
@@ -51,7 +51,7 @@ describe('getEtapesTypesEtapesStatusWithMainStep', () => {
       typeId: 'oct',
     })
 
-    const tested = await restCall(dbPool, '/rest/etapesTypes/:demarcheId/:date', { demarcheId: titreDemarche.id, date: getCurrent() }, userSuper)
+    const tested = await restCall(dbPool, '/rest/etapesTypes/:demarcheId/:date', { demarcheId: titreDemarche.id, date: toCaminoDate('2024-09-01') }, userSuper)
 
     expect(tested.statusCode).toBe(HTTP_STATUS.OK)
     // TODO 2024-06-19 changer ce format ?
@@ -141,7 +141,7 @@ describe('getEtapesTypesEtapesStatusWithMainStep', () => {
       titre.id
     )
 
-    const tested = await restCall(dbPool, '/rest/etapesTypes/:demarcheId/:date', { demarcheId: titreDemarche.id, date: getCurrent() }, userSuper)
+    const tested = await restCall(dbPool, '/rest/etapesTypes/:demarcheId/:date', { demarcheId: titreDemarche.id, date: toCaminoDate('2024-09-01') }, userSuper)
 
     expect(tested.statusCode).toBe(HTTP_STATUS.OK)
     expect(tested.body).toMatchInlineSnapshot(`
diff --git a/packages/api/src/api/rest/etapes.ts b/packages/api/src/api/rest/etapes.ts
index 110a49d5766048d7e14603421e2283a1803f8138..ddfb7c830ee760cb09e5081d3e5a7ec02596bab8 100644
--- a/packages/api/src/api/rest/etapes.ts
+++ b/packages/api/src/api/rest/etapes.ts
@@ -28,7 +28,7 @@ import { CaminoDate, caminoDateValidator, getCurrent } from 'camino-common/src/d
 import { titreDemarcheGet } from '../../database/queries/titres-demarches'
 import { userSuper } from '../../database/user-super'
 import { titreEtapeGet, titreEtapeUpdate, titreEtapeUpsert } from '../../database/queries/titres-etapes'
-import { demarcheDefinitionFind } from '../../business/rules-demarches/definitions'
+import { machineFind } from '../../business/rules-demarches/definitions'
 import { User, isBureauDEtudes, isEntreprise } from 'camino-common/src/roles'
 import { canCreateEtape, canDeposeEtape, canDeleteEtape, canEditEtape, canEditDates, canEditDuree } from 'camino-common/src/permissions/titres-etapes'
 import { TitresStatutIds } from 'camino-common/src/static/titresStatuts'
@@ -1057,7 +1057,7 @@ const demarcheEtapesTypesGet = async (titreDemarcheId: DemarcheId, date: CaminoD
 
   if (titreEtapeId && !titreEtape) throw new Error("l'étape n'existe pas")
 
-  const demarcheDefinition = demarcheDefinitionFind(titre.typeId, titreDemarche.typeId, titreDemarche.etapes, titreDemarche.id)
+  const demarcheDefinition = machineFind(titre.typeId, titreDemarche.typeId, titreDemarche.etapes, titreDemarche.id, date)
 
   const etapesTypes: EtapeTypeEtapeStatutWithMainStep[] = getPossiblesEtapesTypes(
     demarcheDefinition,
diff --git a/packages/api/src/api/rest/titres.ts b/packages/api/src/api/rest/titres.ts
index 2a60d166e7abe85401f15abe8a137879b1f16ad6..c9d99ba77ff946fbcb65d6dce0b94677de41a0ba 100644
--- a/packages/api/src/api/rest/titres.ts
+++ b/packages/api/src/api/rest/titres.ts
@@ -2,7 +2,7 @@ import { titreArchive, titresGet, titreGet, titreUpsert } from '../../database/q
 import { HTTP_STATUS } from 'camino-common/src/http'
 import { ITitre } from '../../types'
 import { CommonTitreAdministration, editableTitreValidator, TitreLink, TitreLinks, TitreGet, titreLinksValidator, utilisateurTitreAbonneValidator } from 'camino-common/src/titres'
-import { demarcheDefinitionFind } from '../../business/rules-demarches/definitions'
+import { machineFind } from '../../business/rules-demarches/definitions'
 import { CaminoRequest, CustomResponse } from './express-type'
 import { userSuper } from '../../database/user-super'
 import { NotNullableKeys, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined, onlyUnique } from 'camino-common/src/typescript-tools'
@@ -138,11 +138,11 @@ export const titresAdministrations =
                 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 (dd) {
+                const machine = machineFind(titre.typeId, demarcheLaPlusRecente.typeId, demarcheLaPlusRecente.etapes, demarcheLaPlusRecente.id)
+                if (machine) {
                   try {
-                    enAttenteDeAdministration = dd.machine.whoIsBlocking(etapesDerniereDemarche).includes(user.administrationId)
-                    const nextEtapes = dd.machine.possibleNextEtapes(etapesDerniereDemarche, getCurrent())
+                    enAttenteDeAdministration = machine.whoIsBlocking(etapesDerniereDemarche).includes(user.administrationId)
+                    const nextEtapes = machine.possibleNextEtapes(etapesDerniereDemarche, getCurrent())
                     prochainesEtapes.push(
                       ...nextEtapes
                         .map(etape => etape.etapeTypeId)
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 d75c84c8eb0c9dcb4b34bb199e4bcc1359027e84..b91fe885ea5c14a9c31103c331ecb41c495f770a 100644
--- a/packages/api/src/business/processes/titres-demarches-depot-create.ts
+++ b/packages/api/src/business/processes/titres-demarches-depot-create.ts
@@ -5,7 +5,7 @@ import { titreDemarcheGet } from '../../database/queries/titres-demarches'
 import { userSuper } from '../../database/user-super'
 import { titreEtapeUpdateTask } from '../titre-etape-update'
 import { titreEtapeAdministrationsEmailsSend } from '../../api/graphql/resolvers/_titre-etape-email'
-import { demarcheDefinitionFind } from '../rules-demarches/definitions'
+import { machineFind } from '../rules-demarches/definitions'
 import { titreUrlGet } from '../utils/urls-get'
 import { emailsWithTemplateSend } from '../../tools/api-mailjet/emails'
 import { EmailTemplateId, EmailAdministration } from '../../tools/api-mailjet/types'
@@ -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)
+  const demarcheDefinition = machineFind(titreDemarche.titre!.typeId, titreDemarche.typeId, titreDemarche.etapes, titreDemarche.id)
   // 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') {
diff --git a/packages/api/src/business/rules-demarches/arm/__snapshots__/oct.machine.test.ts.snap b/packages/api/src/business/rules-demarches/arm/__snapshots__/oct.machine.test.ts.snap
index 464d592b8d5bd6878ff8051f0a05d444e6ae401d..f7f3caa395535ad83ac9add96e8d5adfcc0be7c2 100644
--- a/packages/api/src/business/rules-demarches/arm/__snapshots__/oct.machine.test.ts.snap
+++ b/packages/api/src/business/rules-demarches/arm/__snapshots__/oct.machine.test.ts.snap
@@ -1,21 +1,21 @@
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer 2 "mfr" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mfr","etapeStatutId":"fai","date":"2020-01-03"}' after '["mfr_fai","mdp_fai"]'. The event {"type":"FAIRE_DEMANDE","mecanise":false,"franchissements":null} should be one of 'CLASSER_SANS_SUITE,DESISTER_PAR_LE_DEMANDEUR,MODIFIER_DEMANDE,PAYER_FRAIS_DE_DOSSIER']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer 2 "mfr" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mfr","etapeStatutId":"fai","date":"2020-01-03"}' after '["mfr_fai","mdp_fai"]'. The event {"type":"FAIRE_DEMANDE","mecanise":false,"franchissements":null,"date":"2020-01-03","status":"fai"} should be one of 'CLASSER_SANS_SUITE,DESISTER_PAR_LE_DEMANDEUR,MODIFIER_DEMANDE,PAYER_FRAIS_DE_DOSSIER']`;
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer deux "des" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"des","etapeStatutId":"fai","date":"2020-01-04"}' after '["mfr_fai","mdp_fai","des_fai"]'. The event {"type":"DESISTER_PAR_LE_DEMANDEUR"} should be one of 'VALIDER_FRAIS_DE_DOSSIER']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer deux "des" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"des","etapeStatutId":"fai","date":"2020-01-04"}' after '["mfr_fai","mdp_fai","des_fai"]'. The event {"type":"DESISTER_PAR_LE_DEMANDEUR","date":"2020-01-04","status":"fai"} should be one of 'VALIDER_FRAIS_DE_DOSSIER']`;
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une "css" après une "des" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"css","etapeStatutId":"fai","date":"2020-01-05"}' after '["mfr_fai","mdp_fai","des_fai"]'. The event {"type":"CLASSER_SANS_SUITE"} should be one of 'VALIDER_FRAIS_DE_DOSSIER']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une "css" après une "des" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"css","etapeStatutId":"fai","date":"2020-01-05"}' after '["mfr_fai","mdp_fai","des_fai"]'. The event {"type":"CLASSER_SANS_SUITE","date":"2020-01-05","status":"fai"} should be one of 'VALIDER_FRAIS_DE_DOSSIER']`;
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une "mno" après la "aca" si le titre n’est pas mécanisé 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mnb","etapeStatutId":"fai","date":"2020-01-04"}' after '["mfr_fai","mdp_fai","pfd_fai","mcp_com","vfd_fai","mcr_fav","asc_fai","sca_fai","aca_fav"]'. The event {"type":"NOTIFIER_DEMANDEUR_AVIS_FAVORABLE_CARM"} should be one of 'CLASSER_SANS_SUITE,DESISTER_PAR_LE_DEMANDEUR,SIGNER_AUTORISATION_DE_RECHERCHE_MINIERE']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une "mno" après la "aca" si le titre n’est pas mécanisé 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mnb","etapeStatutId":"fai","date":"2020-01-04"}' after '["mfr_fai","mdp_fai","pfd_fai","mcp_com","vfd_fai","mcr_fav","asc_fai","sca_fai","aca_fav"]'. The event {"type":"NOTIFIER_DEMANDEUR_AVIS_FAVORABLE_CARM","date":"2020-01-04","status":"fai"} should be one of 'CLASSER_SANS_SUITE,DESISTER_PAR_LE_DEMANDEUR,SIGNER_AUTORISATION_DE_RECHERCHE_MINIERE']`;
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une étape "{ etapeTypeId: 'mcb', etapeStatutId: 'fai' }" si il n’existe pas d’autres étapes 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mcb","etapeStatutId":"fai","date":"2020-01-01"}' after '[]'. The event {"type":"DEMANDER_COMPLEMENTS_RDE"} should be one of 'ACCEPTER_RDE,DEMANDER_MODIFICATION_DE_LA_DEMANDE,EXEMPTER_DAE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER,REFUSER_RDE']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une étape "{ etapeTypeId: 'mcb', etapeStatutId: 'fai' }" si il n’existe pas d’autres étapes 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mcb","etapeStatutId":"fai","date":"2020-01-01"}' after '[]'. The event {"type":"DEMANDER_COMPLEMENTS_RDE","date":"2020-01-01","status":"fai"} should be one of 'ACCEPTER_RDE,DEMANDER_MODIFICATION_DE_LA_DEMANDE,EXEMPTER_DAE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER,REFUSER_RDE']`;
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une étape "{ etapeTypeId: 'mcd', etapeStatutId: 'fai' }" si il n’existe pas d’autres étapes 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mcd","etapeStatutId":"fai","date":"2020-01-01"}' after '[]'. The event {"type":"DEMANDER_COMPLEMENTS_DAE"} should be one of 'ACCEPTER_RDE,DEMANDER_MODIFICATION_DE_LA_DEMANDE,EXEMPTER_DAE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER,REFUSER_RDE']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une étape "{ etapeTypeId: 'mcd', etapeStatutId: 'fai' }" si il n’existe pas d’autres étapes 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mcd","etapeStatutId":"fai","date":"2020-01-01"}' after '[]'. The event {"type":"DEMANDER_COMPLEMENTS_DAE","date":"2020-01-01","status":"fai"} should be one of 'ACCEPTER_RDE,DEMANDER_MODIFICATION_DE_LA_DEMANDE,EXEMPTER_DAE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER,REFUSER_RDE']`;
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une étape "mcp" sans "mdp" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mcp","etapeStatutId":"com","date":"2022-04-16"}' after '["mfr_fai"]'. The event {"type":"ACCEPTER_COMPLETUDE"} should be one of 'DEPOSER_DEMANDE,PAYER_FRAIS_DE_DOSSIER']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas créer une étape "mcp" sans "mdp" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mcp","etapeStatutId":"com","date":"2022-04-16"}' after '["mfr_fai"]'. The event {"type":"ACCEPTER_COMPLETUDE","date":"2022-04-16","status":"com"} should be one of 'DEPOSER_DEMANDE,PAYER_FRAIS_DE_DOSSIER']`;
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas déplacer une étape "mdp" sans "mfr" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mdp","etapeStatutId":"fai","date":"2020-02-02"}' after '[]'. The event {"type":"DEPOSER_DEMANDE"} should be one of 'ACCEPTER_RDE,DEMANDER_MODIFICATION_DE_LA_DEMANDE,EXEMPTER_DAE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER,REFUSER_RDE']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas déplacer une étape "mdp" sans "mfr" 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mdp","etapeStatutId":"fai","date":"2020-02-02"}' after '[]'. The event {"type":"DEPOSER_DEMANDE","date":"2020-02-02","status":"fai"} should be one of 'ACCEPTER_RDE,DEMANDER_MODIFICATION_DE_LA_DEMANDE,EXEMPTER_DAE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER,REFUSER_RDE']`;
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas faire de mfr non mécanisée après une dae 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mfr","etapeStatutId":"fai","date":"2021-02-25","contenu":{"arm":{"mecanise":false}}}' after '["dae_exe"]'. The event {"type":"FAIRE_DEMANDE","mecanise":false,"franchissements":null} should be one of 'ACCEPTER_RDE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER,REFUSER_RDE']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas faire de mfr non mécanisée après une dae 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mfr","etapeStatutId":"fai","date":"2021-02-25","contenu":{"arm":{"mecanise":false}}}' after '["dae_exe"]'. The event {"type":"FAIRE_DEMANDE","mecanise":false,"franchissements":null,"date":"2021-02-25","status":"fai"} should be one of 'ACCEPTER_RDE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER,REFUSER_RDE']`;
 
-exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas faire de mfr non mécanisée après une rde 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mfr","etapeStatutId":"fai","date":"2021-02-25","contenu":{"arm":{"mecanise":false}}}' after '["rde_fav"]'. The event {"type":"FAIRE_DEMANDE","mecanise":false,"franchissements":null} should be one of 'DEMANDER_MODIFICATION_DE_LA_DEMANDE,EXEMPTER_DAE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER']`;
+exports[`vérifie l’arbre d’octroi d’ARM > ne peut pas faire de mfr non mécanisée après une rde 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mfr","etapeStatutId":"fai","date":"2021-02-25","contenu":{"arm":{"mecanise":false}}}' after '["rde_fav"]'. The event {"type":"FAIRE_DEMANDE","mecanise":false,"franchissements":null,"date":"2021-02-25","status":"fai"} should be one of 'DEMANDER_MODIFICATION_DE_LA_DEMANDE,EXEMPTER_DAE,FAIRE_DEMANDE,PAYER_FRAIS_DE_DOSSIER']`;
diff --git a/packages/api/src/business/rules-demarches/arm/oct.machine.test.ts b/packages/api/src/business/rules-demarches/arm/oct.machine.test.ts
index 45902dad16b40bf6d162a5092e5006fbba76ffb4..bb9fe1266236725430cab5afaab63c583acb85ef 100644
--- a/packages/api/src/business/rules-demarches/arm/oct.machine.test.ts
+++ b/packages/api/src/business/rules-demarches/arm/oct.machine.test.ts
@@ -95,7 +95,7 @@ describe('vérifie l’arbre d’octroi d’ARM', () => {
         ETES.saisineDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_.FAIT,
       ])
     ).toThrowErrorMatchingInlineSnapshot(
-      `[Error: Error: cannot execute step: '{"etapeTypeId":"sca","etapeStatutId":"fai","date":"2023-10-03"}' after '["pfd_fai","mfr_fai","mdp_fai","mcp_com","vfd_fai","mcr_fav"]'. The event {"type":"FAIRE_SAISINE_CARM"} should be one of 'CLASSER_SANS_SUITE,DESISTER_PAR_LE_DEMANDEUR,MODIFIER_DEMANDE,RECEVOIR_EXPERTISE_SERVICE_EAU,RECEVOIR_EXPERTISE_SERVICE_MINES,RENDRE_AVIS_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES']`
+      `[Error: Error: cannot execute step: '{"etapeTypeId":"sca","etapeStatutId":"fai","date":"2023-10-03"}' after '["pfd_fai","mfr_fai","mdp_fai","mcp_com","vfd_fai","mcr_fav"]'. The event {"type":"FAIRE_SAISINE_CARM","date":"2023-10-03","status":"fai"} should be one of 'CLASSER_SANS_SUITE,DESISTER_PAR_LE_DEMANDEUR,MODIFIER_DEMANDE,RECEVOIR_EXPERTISE_SERVICE_EAU,RECEVOIR_EXPERTISE_SERVICE_MINES,RENDRE_AVIS_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES']`
     )
   })
   test('la demande ne peut pas être effectuée après une modification de la demande', () => {
diff --git a/packages/api/src/business/rules-demarches/arm/oct.machine.ts b/packages/api/src/business/rules-demarches/arm/oct.machine.ts
index d7d69033cf011be421453cf5b077f1b97b531e05..af45e71cf3ca4ecc52aff2d6cab3a15bf82444f5 100644
--- a/packages/api/src/business/rules-demarches/arm/oct.machine.ts
+++ b/packages/api/src/business/rules-demarches/arm/oct.machine.ts
@@ -178,15 +178,12 @@ const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
   NOTIFIER_AVENANT_ARM: { db: EtapesTypesEtapesStatuts.notificationAuDemandeur_SignatureDeLavenantALautorisationDeRechercheMiniere_, mainStep: false },
 } as const
 
-// Related to https://github.com/Microsoft/TypeScript/issues/12870
-const EVENTS = Object.keys(trad) as Array<Extract<keyof typeof trad, string>>
-
 export class ArmOctMachine extends CaminoMachine<OctARMContext, XStateEvent> {
   constructor() {
     super(armOctMachine, trad)
   }
 
-  caminoXStateEventToEtapes(event: XStateEvent): (Omit<Etape, 'date'> & { mainStep: boolean })[] {
+  override caminoXStateEventToEtapes(event: XStateEvent): (Omit<Etape, 'date' | 'titreTypeId' | 'demarcheTypeId'> & { mainStep: boolean })[] {
     const dbEtat: DBEtat = trad[event.type].db
     let contenu: IContenu | undefined
     switch (event.type) {
@@ -214,49 +211,36 @@ export class ArmOctMachine extends CaminoMachine<OctARMContext, XStateEvent> {
     }))
   }
 
-  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 'FAIRE_DEMANDE': {
-          let mecanise = false
-          let franchissements = null
-          if (typeof etape.contenu?.arm?.mecanise === 'boolean') {
-            mecanise = etape.contenu?.arm.mecanise
-          }
-          if (typeof etape.contenu?.arm?.franchissements === 'number') {
-            franchissements = etape.contenu?.arm?.franchissements
-          }
-
-          return { type: eventFromEntry, mecanise, franchissements }
+  override eventFromEntry(eventFromEntry: XStateEvent['type'], etape: Etape): XStateEvent {
+    switch (eventFromEntry) {
+      case 'FAIRE_DEMANDE': {
+        let mecanise = false
+        let franchissements = null
+        if (typeof etape.contenu?.arm?.mecanise === 'boolean') {
+          mecanise = etape.contenu?.arm.mecanise
+        }
+        if (typeof etape.contenu?.arm?.franchissements === 'number') {
+          franchissements = etape.contenu?.arm?.franchissements
         }
-        case 'ACCEPTER_RDE':
-        case 'REFUSER_RDE':
-        case 'RECEVOIR_COMPLEMENTS_RDE': {
-          let franchissements = null
-          if (typeof etape.contenu?.arm?.franchissements === 'number') {
-            franchissements = etape.contenu?.arm?.franchissements
-          }
-
-          return { type: eventFromEntry, franchissements }
+
+        return { type: eventFromEntry, mecanise, franchissements }
+      }
+      case 'ACCEPTER_RDE':
+      case 'REFUSER_RDE':
+      case 'RECEVOIR_COMPLEMENTS_RDE': {
+        let franchissements = null
+        if (typeof etape.contenu?.arm?.franchissements === 'number') {
+          franchissements = etape.contenu?.arm?.franchissements
         }
-        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 }
+
+        return { type: eventFromEntry, franchissements }
       }
+      default:
+        return super.eventFromEntry(eventFromEntry, etape)
     }
-    throw new Error(`no event from ${JSON.stringify(etape)}`)
   }
 
-  toPotentialCaminoXStateEvent(event: XStateEvent['type'], _date: CaminoDate): XStateEvent[] {
+  override toPotentialCaminoXStateEvent(event: XStateEvent['type'], _date: CaminoDate): XStateEvent[] {
     switch (event) {
       case 'FAIRE_DEMANDE': {
         return [
diff --git a/packages/api/src/business/rules-demarches/arm/ren-pro.machine.test.ts b/packages/api/src/business/rules-demarches/arm/ren-pro.machine.test.ts
index 09731f27de9cdc9c882cc3cdcc487837b2ec2c51..0c3a6b314cf2c3ba545c35197576d72c17ebc121 100644
--- a/packages/api/src/business/rules-demarches/arm/ren-pro.machine.test.ts
+++ b/packages/api/src/business/rules-demarches/arm/ren-pro.machine.test.ts
@@ -17,7 +17,7 @@ describe('vérifie l’arbre de renonciation et de prolongation d’ARM', () =>
     expect(() =>
       setDateAndOrderAndInterpretMachine(armRenProMachine, '2020-05-26', [ETES.demande.FAIT, ETES.depotDeLaDemande.FAIT, ETES.recevabiliteDeLaDemande.FAVORABLE, ETES.modificationDeLaDemande.FAIT])
     ).toThrowErrorMatchingInlineSnapshot(
-      `[Error: Error: cannot execute step: '{"etapeTypeId":"mod","etapeStatutId":"fai","date":"2020-05-30"}' after '["mfr_fai","mdp_fai","mcr_fav"]'. The event {"type":"RECEVOIR_MODIFICATION_DE_LA_DEMANDE"} should be one of 'CLASSER_SANS_SUITE,DESISTER_PAR_LE_DEMANDEUR,RENDRE_AVIS_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES']`
+      `[Error: Error: cannot execute step: '{"etapeTypeId":"mod","etapeStatutId":"fai","date":"2020-05-30"}' after '["mfr_fai","mdp_fai","mcr_fav"]'. The event {"type":"RECEVOIR_MODIFICATION_DE_LA_DEMANDE","date":"2020-05-30","status":"fai"} should be one of 'CLASSER_SANS_SUITE,DESISTER_PAR_LE_DEMANDEUR,RENDRE_AVIS_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES']`
     )
   })
 
@@ -31,7 +31,7 @@ describe('vérifie l’arbre de renonciation et de prolongation d’ARM', () =>
         // {...ETES.recevabiliteDeLaDemande.DEFAVORABLE, date: toCaminoDate('2020-05-30') },
       ])
     ).toThrowErrorMatchingInlineSnapshot(
-      `[Error: Error: cannot execute step: '{"etapeTypeId":"mca","etapeStatutId":"fai","date":"2020-05-31"}' after '["mfr_fai","mdp_fai","mca_fai"]'. The event {"type":"DEMANDER_COMPLEMENTS_POUR_RECEVABILITE"} should be one of 'DESISTER_PAR_LE_DEMANDEUR,FAIRE_RECEVABILITE_DEMANDE_DEFAVORABLE,FAIRE_RECEVABILITE_DEMANDE_FAVORABLE,RECEVOIR_COMPLEMENTS_POUR_RECEVABILITE']`
+      `[Error: Error: cannot execute step: '{"etapeTypeId":"mca","etapeStatutId":"fai","date":"2020-05-31"}' after '["mfr_fai","mdp_fai","mca_fai"]'. The event {"type":"DEMANDER_COMPLEMENTS_POUR_RECEVABILITE","date":"2020-05-31","status":"fai"} should be one of 'DESISTER_PAR_LE_DEMANDEUR,FAIRE_RECEVABILITE_DEMANDE_DEFAVORABLE,FAIRE_RECEVABILITE_DEMANDE_FAVORABLE,RECEVOIR_COMPLEMENTS_POUR_RECEVABILITE']`
     )
   })
 
diff --git a/packages/api/src/business/rules-demarches/arm/ren-pro.machine.ts b/packages/api/src/business/rules-demarches/arm/ren-pro.machine.ts
index f2009fb4f6102ca627dbeaa73bf85d540dd9478e..da8edff1ff9e8b192626244d180d118742eb3b77 100644
--- a/packages/api/src/business/rules-demarches/arm/ren-pro.machine.ts
+++ b/packages/api/src/business/rules-demarches/arm/ren-pro.machine.ts
@@ -1,7 +1,7 @@
 import { assign, createMachine } from 'xstate'
 import { EtapesTypesEtapesStatuts } from 'camino-common/src/static/etapesTypesEtapesStatuts'
 import { CaminoMachine } from '../machine-helper'
-import { CaminoCommonContext, DBEtat, Etape } from '../machine-common'
+import { CaminoCommonContext, DBEtat } from '../machine-common'
 import { DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts'
 
 type XStateEvent =
@@ -48,31 +48,10 @@ const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
   NOTIFIER_DEMANDEUR_APRES_CLASSEMENT_SANS_SUITE: { db: EtapesTypesEtapesStatuts.notificationAuDemandeur_ClassementSansSuite_, mainStep: true },
 } as const
 
-// Related to https://github.com/Microsoft/TypeScript/issues/12870
-const EVENTS = Object.keys(trad) as Array<Extract<keyof typeof trad, string>>
-
 export class ArmRenProMachine extends CaminoMachine<CaminoCommonContext, XStateEvent> {
   constructor() {
     super(armRenProMachine, trad)
   }
-
-  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]
-
-      // 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)}`)
-  }
 }
 
 const armRenProMachine = createMachine({
diff --git a/packages/api/src/business/rules-demarches/axm/__snapshots__/oct.machine.test.ts.snap b/packages/api/src/business/rules-demarches/axm/__snapshots__/oct.machine.test.ts.snap
index f41eebd830c843abf862c1f7d9b3fb21e5b949ca..12c23804ac77d81a871c6a3069b1cdee6c2ddd1d 100644
--- a/packages/api/src/business/rules-demarches/axm/__snapshots__/oct.machine.test.ts.snap
+++ b/packages/api/src/business/rules-demarches/axm/__snapshots__/oct.machine.test.ts.snap
@@ -1,3 +1,3 @@
 // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
 
-exports[`vérifie l’arbre d’octroi d’AXM > ne peut pas faire deux fois la même étape à la même date 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mfr","etapeStatutId":"fai","date":"2022-04-01"}' after '["mfr_fai"]'. The event {"type":"FAIRE_DEMANDE"} should be one of 'FAIRE_DESISTEMENT_DEMANDEUR,RENDRE_DAE_EXEMPTEE,RENDRE_DAE_REQUISE,RENDRE_DECISION_DU_PROPRIETAIRE_DU_SOL_DEFAVORABLE,RENDRE_DECISION_DU_PROPRIETAIRE_DU_SOL_FAVORABLE,RENDRE_DECISION_DU_PROPRIETAIRE_DU_SOL_FAVORABLE_AVEC_RESERVE']`;
+exports[`vérifie l’arbre d’octroi d’AXM > ne peut pas faire deux fois la même étape à la même date 1`] = `[Error: Error: cannot execute step: '{"etapeTypeId":"mfr","etapeStatutId":"fai","date":"2022-04-01"}' after '["mfr_fai"]'. The event {"type":"FAIRE_DEMANDE","date":"2022-04-01","status":"fai"} should be one of 'FAIRE_DESISTEMENT_DEMANDEUR,RENDRE_DAE_EXEMPTEE,RENDRE_DAE_REQUISE,RENDRE_DECISION_DU_PROPRIETAIRE_DU_SOL_DEFAVORABLE,RENDRE_DECISION_DU_PROPRIETAIRE_DU_SOL_FAVORABLE,RENDRE_DECISION_DU_PROPRIETAIRE_DU_SOL_FAVORABLE_AVEC_RESERVE']`;
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 7f8d9e52eb49c84e08c7d977b21f6f61389a1d30..64b420407927f8da2149b5da72d54dbb00e373a3 100644
--- a/packages/api/src/business/rules-demarches/axm/oct.machine.ts
+++ b/packages/api/src/business/rules-demarches/axm/oct.machine.ts
@@ -1,6 +1,6 @@
 import { assign, createMachine } from 'xstate'
 import { CaminoMachine } from '../machine-helper'
-import { CaminoCommonContext, DBEtat, Etape, tags } from '../machine-common'
+import { CaminoCommonContext, DBEtat, tags } from '../machine-common'
 import { EtapesTypesEtapesStatuts as ETES } from 'camino-common/src/static/etapesTypesEtapesStatuts'
 import { DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts'
 import { ADMINISTRATION_IDS } from 'camino-common/src/static/administrations'
@@ -150,16 +150,13 @@ const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
   FAIRE_CLASSEMENT_SANS_SUITE: { db: ETES.classementSansSuite, mainStep: false },
 }
 
-// Related to https://github.com/Microsoft/TypeScript/issues/12870
-const EVENTS = Object.keys(trad) as Array<Extract<keyof typeof trad, string>>
-
 // basé sur https://cacoo.com/diagrams/iUPEVBYNBjsiirfE/249D0
 export class AxmOctMachine extends CaminoMachine<AxmContext, AXMOctXStateEvent> {
   constructor() {
     super(axmOctMachine, trad)
   }
 
-  toPotentialCaminoXStateEvent(event: AXMOctXStateEvent['type'], date: CaminoDate): AXMOctXStateEvent[] {
+  override toPotentialCaminoXStateEvent(event: AXMOctXStateEvent['type'], date: CaminoDate): AXMOctXStateEvent[] {
     switch (event) {
       case 'RENDRE_AVIS_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES':
       case 'RENDRE_AVIS_DREAL':
@@ -171,30 +168,6 @@ export class AxmOctMachine extends CaminoMachine<AxmContext, AXMOctXStateEvent>
         return [{ type: event }]
     }
   }
-
-  eventFrom(etape: Etape): AXMOctXStateEvent {
-    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_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES':
-        case 'RENDRE_AVIS_DREAL': {
-          return { type: eventFromEntry, date: etape.date }
-        }
-        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)}`)
-  }
 }
 
 type RendreAvisDesServicesEtCommissonsConsultatives = { faite: false } | { faite: true; date: CaminoDate }
diff --git a/packages/api/src/business/rules-demarches/axm/pro.machine.ts b/packages/api/src/business/rules-demarches/axm/pro.machine.ts
index 50d99c9c71c914d1cfe7f122bf3fc4ee8173beba..e8bea2ce3aede69aec74d9b136604249c17f8b7c 100644
--- a/packages/api/src/business/rules-demarches/axm/pro.machine.ts
+++ b/packages/api/src/business/rules-demarches/axm/pro.machine.ts
@@ -1,6 +1,6 @@
 import { assign, createMachine } from 'xstate'
 import { CaminoMachine } from '../machine-helper'
-import { CaminoCommonContext, DBEtat, Etape, tags } from '../machine-common'
+import { CaminoCommonContext, DBEtat, tags } from '../machine-common'
 import { EtapesTypesEtapesStatuts as ETES } from 'camino-common/src/static/etapesTypesEtapesStatuts'
 import { DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts'
 import { ADMINISTRATION_IDS } from 'camino-common/src/static/administrations'
@@ -119,9 +119,6 @@ const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
   },
 }
 
-// Related to https://github.com/Microsoft/TypeScript/issues/12870
-const EVENTS = Object.keys(trad) as Array<Extract<keyof typeof trad, string>>
-
 // basé sur TODO 2023-04-17 mettre le lien vers le bon cacoo
 // TODO 2023-04-17 mettre à jour le cacoo quand on a de nouveau accès avec :
 // - modification de la demande comme pour l'octroi d'AXM
@@ -130,7 +127,7 @@ export class AxmProMachine extends CaminoMachine<AxmProContext, AXMProXStateEven
     super(axmProMachine, trad)
   }
 
-  toPotentialCaminoXStateEvent(event: AXMProXStateEvent['type'], date: CaminoDate): AXMProXStateEvent[] {
+  override toPotentialCaminoXStateEvent(event: AXMProXStateEvent['type'], date: CaminoDate): AXMProXStateEvent[] {
     switch (event) {
       case 'RENDRE_AVIS_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES':
       case 'RENDRE_AVIS_DREAL':
@@ -142,30 +139,6 @@ export class AxmProMachine extends CaminoMachine<AxmProContext, AXMProXStateEven
         return [{ type: event }]
     }
   }
-
-  eventFrom(etape: Etape): AXMProXStateEvent {
-    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_DES_SERVICES_ET_COMMISSIONS_CONSULTATIVES':
-        case 'RENDRE_AVIS_DREAL': {
-          return { type: eventFromEntry, date: etape.date }
-        }
-        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)}`)
-  }
 }
 
 type AvisDesServicesEtCommissionsConsultatives = { faite: false } | { faite: true; date: CaminoDate }
diff --git a/packages/api/src/business/rules-demarches/definitions.test.ts b/packages/api/src/business/rules-demarches/definitions.test.ts
index 7f82b93bc778b71eadb7c9bd1e0593923da7680f..dabf58e84d4712f110333a25f8e80c44a259d4c7 100644
--- a/packages/api/src/business/rules-demarches/definitions.test.ts
+++ b/packages/api/src/business/rules-demarches/definitions.test.ts
@@ -1,24 +1,24 @@
 import { test, expect } from 'vitest'
-import { demarcheDefinitionFind } from './definitions'
+import { machineFind } from './definitions'
 import { toCaminoDate } from 'camino-common/src/date'
 import { newDemarcheId } from '../../database/models/_format/id-create'
 
 test('demarcheDefinitionFind retourne une machine', () => {
-  expect(demarcheDefinitionFind('prm', 'oct', [{ date: toCaminoDate('2023-06-07'), typeId: 'mdp' }], newDemarcheId('demarcheId'))).not.toBe(undefined)
+  expect(machineFind('prm', 'oct', [{ date: toCaminoDate('2023-06-07'), typeId: 'mdp' }], newDemarcheId('demarcheId'))).not.toBe(undefined)
 })
 
 test("demarcheDefinitionFind retourne une machine quand il n'y a pas d'étape", () => {
-  expect(demarcheDefinitionFind('prm', 'oct', [], newDemarcheId('demarcheId'))).not.toBe(undefined)
+  expect(machineFind('prm', 'oct', [], newDemarcheId('demarcheId'))).not.toBe(undefined)
 })
 
 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'))).toBe(undefined)
+  expect(machineFind('prm', 'oct', [{ date: toCaminoDate('2023-06-07'), typeId: 'mdp' }], newDemarcheId('FfJTtP9EEfvf3VZy81hpF7ms'))).toBe(undefined)
 })
 
 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'))).toBe(undefined)
+  expect(machineFind('prm', 'oct', [{ date: toCaminoDate('2010-06-07'), typeId: 'mdp' }], newDemarcheId('FfJTtP9EEfvf3VZy81hpF7ms'))).toBe(undefined)
 })
 
 test('demarcheDefinitionFind', () => {
-  expect(demarcheDefinitionFind('arm', 'pro', [{ date: toCaminoDate('2018-10-22'), typeId: 'def' }], newDemarcheId('Anything'))).toBe(undefined)
+  expect(machineFind('arm', 'pro', [{ date: toCaminoDate('2018-10-22'), typeId: 'def' }], newDemarcheId('Anything'))).toBe(undefined)
 })
diff --git a/packages/api/src/business/rules-demarches/definitions.ts b/packages/api/src/business/rules-demarches/definitions.ts
index 3a06b933853fccb30a5fcf6132995c3282e39ae3..99e9ec70c6db1425bb9f7aa8b8cd5cf88b851502 100644
--- a/packages/api/src/business/rules-demarches/definitions.ts
+++ b/packages/api/src/business/rules-demarches/definitions.ts
@@ -13,15 +13,14 @@ import { ArmRenProMachine } from './arm/ren-pro.machine'
 import { PrmOctMachine } from './prm/oct.machine'
 import { DeepReadonly, NonEmptyArray, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefinedOrEmpty } from 'camino-common/src/typescript-tools'
 import { ProcedureSimplifieeMachine } from './procedure-simplifiee/ps.machine'
+import { ProcedureSpecifiqueMachine } from './procedure-specifique/procedure-specifique.machine'
 
-interface DemarcheDefinitionCommon {
+interface DemarcheDefinition {
   titreTypeIds: NonEmptyArray<TitreTypeId>
   demarcheTypeIds: DemarcheTypeId[]
   dateDebut: CaminoDate
   demarcheIdExceptions: DemarcheId[]
-}
-export interface DemarcheDefinition extends DemarcheDefinitionCommon {
-  machine: CaminoMachines
+  machine: (titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId) => CaminoMachines
 }
 const allDemarcheNotTravaux = Object.values(DEMARCHES_TYPES_IDS).filter(demarcheTypeId => !DemarchesTypes[demarcheTypeId].travaux)
 const demarcheTypeIdsCxPr_G: DemarcheTypeId[] = [
@@ -43,21 +42,21 @@ export const demarchesDefinitions = [
   {
     titreTypeIds: ['arm'],
     demarcheTypeIds: ['oct'],
-    machine: new ArmOctMachine(),
+    machine: () => new ArmOctMachine(),
     dateDebut: toCaminoDate('2019-10-31'),
     demarcheIdExceptions: [],
   },
   {
     titreTypeIds: ['arm'],
     demarcheTypeIds: ['ren', 'pro'],
-    machine: new ArmRenProMachine(),
+    machine: () => new ArmRenProMachine(),
     dateDebut: toCaminoDate('2019-10-31'),
     demarcheIdExceptions: [],
   },
   {
     titreTypeIds: ['prm'],
     demarcheTypeIds: ['oct'],
-    machine: new PrmOctMachine(),
+    machine: () => new PrmOctMachine(),
     dateDebut: toCaminoDate('2019-10-31'),
     demarcheIdExceptions: [
       newDemarcheId('FfJTtP9EEfvf3VZy81hpF7ms'),
@@ -71,7 +70,7 @@ export const demarchesDefinitions = [
   {
     titreTypeIds: ['axm'],
     demarcheTypeIds: ['oct'],
-    machine: new AxmOctMachine(),
+    machine: () => new AxmOctMachine(),
     // https://camino.beta.gouv.fr/titres/m-ax-crique-tumuc-humac-2020
     dateDebut: toCaminoDate('2020-09-30'),
     demarcheIdExceptions: [
@@ -84,7 +83,7 @@ export const demarchesDefinitions = [
   {
     titreTypeIds: ['axm'],
     demarcheTypeIds: ['pro'],
-    machine: new AxmProMachine(),
+    machine: () => new AxmProMachine(),
     dateDebut: toCaminoDate('2000-01-01'),
     demarcheIdExceptions: [
       // Complète mais ne respectant pas le cacoo
@@ -110,26 +109,43 @@ export const demarchesDefinitions = [
   {
     titreTypeIds: ['pxg', 'arg', 'cxr', 'inr', 'prr', 'pxr', 'cxf', 'prf', 'pxf', 'arc', 'apc', 'pcc'],
     demarcheTypeIds: allDemarcheNotTravaux,
-    machine: new ProcedureSimplifieeMachine(),
+    machine: () => new ProcedureSimplifieeMachine(),
     dateDebut: plusVieilleDateEnBase,
     demarcheIdExceptions: [],
   },
   {
     titreTypeIds: ['cxg', 'prg', 'cxs', 'prs', 'aph', 'cxh', 'prh', 'pxh'],
     demarcheTypeIds: demarcheTypeIdsCxPr_G,
-    machine: new ProcedureSimplifieeMachine(),
+    machine: () => new ProcedureSimplifieeMachine(),
     dateDebut: plusVieilleDateEnBase,
     demarcheIdExceptions: [],
   },
+  {
+    titreTypeIds: ['arm', 'arc', 'axm', 'cxg', 'cxw', 'cxh', 'cxm', 'cxs', 'pcc', 'prg', 'prw', 'prh', 'prm', 'prs'],
+    demarcheTypeIds: [
+      DEMARCHES_TYPES_IDS.Octroi,
+      DEMARCHES_TYPES_IDS.Prolongation,
+      DEMARCHES_TYPES_IDS.Prolongation1,
+      DEMARCHES_TYPES_IDS.Prolongation2,
+      DEMARCHES_TYPES_IDS.ProlongationExceptionnelle,
+      DEMARCHES_TYPES_IDS.ExtensionDePerimetre,
+      DEMARCHES_TYPES_IDS.ExtensionDeSubstance,
+      DEMARCHES_TYPES_IDS.Prorogation,
+    ],
+    machine: (titreTypeId, demarcheTypeId) => new ProcedureSpecifiqueMachine(titreTypeId, demarcheTypeId),
+    dateDebut: toCaminoDate('4000-01-01'),
+    demarcheIdExceptions: [],
+  },
 ] as const satisfies readonly DemarcheDefinition[]
 
-export const demarcheDefinitionFind = (
+export const machineFind = (
   titreTypeId: TitreTypeId,
   demarcheTypeId: DemarcheTypeId,
   titreEtapes: DeepReadonly<Pick<ITitreEtape, 'date' | 'typeId'>[]> | undefined,
-  demarcheId: DemarcheId
-): DemarcheDefinition | undefined => {
-  const date = titreDemarcheDepotDemandeDateFind(titreEtapes)
+  demarcheId: DemarcheId,
+  overrideDate: CaminoDate | null = null
+): CaminoMachines | undefined => {
+  const date = titreDemarcheDepotDemandeDateFind(titreEtapes) ?? overrideDate
 
   const definition = demarchesDefinitions
     .toSorted((a, b) => b.dateDebut.localeCompare(a.dateDebut))
@@ -138,5 +154,5 @@ export const demarcheDefinitionFind = (
     return undefined
   }
 
-  return definition
+  return definition?.machine(titreTypeId, demarcheTypeId)
 }
diff --git a/packages/api/src/business/rules-demarches/machine-helper.ts b/packages/api/src/business/rules-demarches/machine-helper.ts
index fb3163c899a4e5965fc1c8d5768e28519ac54c42..ff20e1b0c376a6ce3203b440409b1e432aa305d6 100644
--- a/packages/api/src/business/rules-demarches/machine-helper.ts
+++ b/packages/api/src/business/rules-demarches/machine-helper.ts
@@ -21,9 +21,29 @@ export abstract class CaminoMachine<CaminoContext extends CaminoCommonContext, C
     this.events = Object.keys(trad) as Array<CaminoEvent['type']>
   }
 
-  abstract eventFrom(etape: Etape): CaminoEvent
+  public eventFrom(etape: Etape): CaminoEvent {
+    const entries = Object.entries(this.trad).filter((entry): entry is [CaminoEvent['type'], { db: DBEtat; mainStep: boolean }] => this.events.includes(entry[0]))
 
-  protected caminoXStateEventToEtapes(event: CaminoEvent): (OmitDistributive<Etape, 'date'> & { mainStep: boolean })[] {
+    const entry = entries.find(([_key, { db: dbEtat }]) => {
+      return Object.values(dbEtat).some(dbEtatSingle => dbEtatSingle.etapeTypeId === etape.etapeTypeId && dbEtatSingle.etapeStatutId === etape.etapeStatutId)
+    })
+
+    if (entry) {
+      const eventFromEntr = entry[0]
+
+      return { ...this.eventFromEntry(eventFromEntr, etape), date: etape.date, status: etape.etapeStatutId }
+    }
+    throw new Error(`no event from ${JSON.stringify(etape)}`)
+  }
+
+  protected eventFromEntry(entryType: CaminoEvent['type'], _etape: Etape): CaminoEvent {
+    // @ts-ignore FIXMACHINE à voir si on repasse dessus ou si on laisse le ts-ignore
+    const result: CaminoEvent = { type: entryType }
+
+    return result
+  }
+
+  protected caminoXStateEventToEtapes(event: CaminoEvent): (OmitDistributive<Etape, 'date' | 'titreTypeId' | 'demarcheTypeId'> & { mainStep: boolean })[] {
     const dbEtat: { db: DBEtat; mainStep: boolean } = this.trad[event.type as CaminoEvent['type']]
 
     return Object.values(dbEtat.db).map(({ etapeTypeId, etapeStatutId }) => ({
@@ -194,7 +214,7 @@ export abstract class CaminoMachine<CaminoContext extends CaminoCommonContext, C
     return intervenants.filter(r => responsables.includes(tags.responsable[r]))
   }
 
-  public possibleNextEtapes(etapes: readonly Etape[], date: CaminoDate): (OmitDistributive<Etape, 'date'> & { mainStep: boolean })[] {
+  public possibleNextEtapes(etapes: readonly Etape[], date: CaminoDate): (OmitDistributive<Etape, 'date' | 'titreTypeId' | 'demarcheTypeId'> & { mainStep: boolean })[] {
     const state = this.assertGoTo(etapes)
 
     if (state !== undefined) {
diff --git a/packages/api/src/business/rules-demarches/machine-test-helper.ts b/packages/api/src/business/rules-demarches/machine-test-helper.ts
index b779c76ccd16406675f92758efe68b9f5b1d0b96..b58c10e0ae7d18fc0632eb2b0d1eaf65b0e6391b 100644
--- a/packages/api/src/business/rules-demarches/machine-test-helper.ts
+++ b/packages/api/src/business/rules-demarches/machine-test-helper.ts
@@ -81,7 +81,7 @@ export const interpretMachine = <T extends EventObject, C extends CaminoCommonCo
 export const setDateAndOrderAndInterpretMachine = <T extends EventObject, C extends CaminoCommonContext>(
   machine: CaminoMachine<C, T>,
   initDate: `${number}-${number}-${number}`,
-  etapes: readonly (EtapeTypeEtapeStatutValidPair & Omit<Etape, 'date' | 'etapeTypeId' | 'etapeStatutId'> & { addDays?: number })[]
+  etapes: readonly (EtapeTypeEtapeStatutValidPair & Omit<Etape, 'date' | 'etapeTypeId' | 'etapeStatutId' | 'titreTypeId' | 'demarcheTypeId'> & { addDays?: number })[]
 ): { service: Actor<(typeof machine)['machine']>; dateFin: CaminoDate; etapes: Etape[] } => {
   const firstDate = toCaminoDate(initDate)
   let index = 0
@@ -98,6 +98,9 @@ export const setDateAndOrderAndInterpretMachine = <T extends EventObject, C exte
 
   return { service, dateFin: dateAddDays(firstDate, etapes.length), etapes: fullEtapes }
 }
-export const orderAndInterpretMachine = <T extends EventObject, C extends CaminoCommonContext>(machine: CaminoMachine<C, T>, etapes: readonly Etape[]): Actor<(typeof machine)['machine']> => {
+export const orderAndInterpretMachine = <T extends EventObject, C extends CaminoCommonContext>(
+  machine: CaminoMachine<C, T>,
+  etapes: readonly Omit<Etape, 'titreTypeId' | 'demarcheTypeId'>[]
+): Actor<(typeof machine)['machine']> => {
   return interpretMachine(machine, machine.orderMachine(etapes))
 }
diff --git a/packages/api/src/business/rules-demarches/machines.ts b/packages/api/src/business/rules-demarches/machines.ts
index 5302799e07fced62ec13d5128ae96ea26dfb0984..23072ef3f50bd937349ab3bbeaa7918b3df2fcc1 100644
--- a/packages/api/src/business/rules-demarches/machines.ts
+++ b/packages/api/src/business/rules-demarches/machines.ts
@@ -4,5 +4,6 @@ import type { AxmOctMachine } from './axm/oct.machine'
 import type { AxmProMachine } from './axm/pro.machine'
 import type { PrmOctMachine } from './prm/oct.machine'
 import type { ProcedureSimplifieeMachine } from './procedure-simplifiee/ps.machine'
+import type { ProcedureSpecifiqueMachine } from './procedure-specifique/procedure-specifique.machine'
 
-export type CaminoMachines = ArmOctMachine | AxmOctMachine | AxmProMachine | ArmRenProMachine | PrmOctMachine | ProcedureSimplifieeMachine
+export type CaminoMachines = ArmOctMachine | AxmOctMachine | AxmProMachine | ArmRenProMachine | PrmOctMachine | ProcedureSimplifieeMachine | ProcedureSpecifiqueMachine
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
index 0545647cab0e3f5d12fe51c748f8921adbd4a9ec..c8c377ab3443219d050fbd3fd788760d8feb58b0 100644
--- a/packages/api/src/business/rules-demarches/prm/oct.machine.test.ts
+++ b/packages/api/src/business/rules-demarches/prm/oct.machine.test.ts
@@ -101,7 +101,7 @@ describe('vérifie l’arbre d’octroi de PRM', () => {
       ETES.avisEtRapportDuDirecteurRegionalChargeDeLenvironnementDeLamenagementEtDuLogement.FAVORABLE,
     ]
     expect(() => setDateAndOrderAndInterpretMachine(prmOctMachine, '2022-04-13', etapes)).toThrowErrorMatchingInlineSnapshot(
-      `[Error: Error: cannot execute step: '{"etapeTypeId":"apd","etapeStatutId":"fav","date":"2022-04-20"}' after '["mfr_fai","mdp_fai","spp_fai","mcr_fav","anf_fai","asc_fai"]'. The event {"type":"RENDRE_RAPPORT_DREAL","date":"2022-04-20"} should be one of 'CLASSER_SANS_SUITE,DEMANDER_INFORMATIONS,DEPOSER_DEMANDE_CONCURRENTE,DESISTER_PAR_LE_DEMANDEUR,MODIFIER_DEMANDE,RECEVOIR_INFORMATIONS']`
+      `[Error: Error: cannot execute step: '{"etapeTypeId":"apd","etapeStatutId":"fav","date":"2022-04-20"}' after '["mfr_fai","mdp_fai","spp_fai","mcr_fav","anf_fai","asc_fai"]'. The event {"type":"RENDRE_RAPPORT_DREAL","date":"2022-04-20","status":"fav"} should be one of 'CLASSER_SANS_SUITE,DEMANDER_INFORMATIONS,DEPOSER_DEMANDE_CONCURRENTE,DESISTER_PAR_LE_DEMANDEUR,MODIFIER_DEMANDE,RECEVOIR_INFORMATIONS']`
     )
   })
 
@@ -116,7 +116,7 @@ describe('vérifie l’arbre d’octroi de PRM', () => {
       ETES.avisDesServicesEtCommissionsConsultatives.FAIT,
     ]
     expect(() => setDateAndOrderAndInterpretMachine(prmOctMachine, '2022-04-12', etapes)).toThrowErrorMatchingInlineSnapshot(
-      `[Error: Error: cannot execute step: '{"etapeTypeId":"asc","etapeStatutId":"fai","date":"2022-04-19"}' after '["mfr_fai","mdp_fai","spp_fai","mcr_fav","anf_fai","asc_fai"]'. The event {"type":"RENDRE_AVIS_SERVICES_ET_COMMISSIONS_CONSULTATIVES","date":"2022-04-19"} should be one of 'CLASSER_SANS_SUITE,DEMANDER_INFORMATIONS,DEPOSER_DEMANDE_CONCURRENTE,DESISTER_PAR_LE_DEMANDEUR,MODIFIER_DEMANDE,RECEVOIR_INFORMATIONS']`
+      `[Error: Error: cannot execute step: '{"etapeTypeId":"asc","etapeStatutId":"fai","date":"2022-04-19"}' after '["mfr_fai","mdp_fai","spp_fai","mcr_fav","anf_fai","asc_fai"]'. The event {"type":"RENDRE_AVIS_SERVICES_ET_COMMISSIONS_CONSULTATIVES","date":"2022-04-19","status":"fai"} should be one of 'CLASSER_SANS_SUITE,DEMANDER_INFORMATIONS,DEPOSER_DEMANDE_CONCURRENTE,DESISTER_PAR_LE_DEMANDEUR,MODIFIER_DEMANDE,RECEVOIR_INFORMATIONS']`
     )
   })
 
@@ -156,7 +156,7 @@ describe('vérifie l’arbre d’octroi de PRM', () => {
     ]
 
     expect(() => setDateAndOrderAndInterpretMachine(prmOctMachine, '2022-04-13', etapes)).toThrowErrorMatchingInlineSnapshot(
-      `[Error: Error: cannot execute step: '{"etapeTypeId":"rpu","etapeStatutId":"fai","date":"2022-05-30"}' after '["mfr_fai","mdp_fai","spp_fai","mcr_fav","anf_fai","asc_fai","ppu_ter","apd_fav","app_fav","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_ABROGATION,RENDRE_DECISION_ANNULATION_PAR_JUGE_ADMINISTRATIF']`
+      `[Error: Error: cannot execute step: '{"etapeTypeId":"rpu","etapeStatutId":"fai","date":"2022-05-30"}' after '["mfr_fai","mdp_fai","spp_fai","mcr_fav","anf_fai","asc_fai","ppu_ter","apd_fav","app_fav","scg_fai","rcg_fav","acg_fav","sas_fai","dex_rej","npp_fai","mno_fai"]'. The event {"type":"PUBLIER_DECISIONS_RECUEIL_ACTES_ADMINISTRATIFS","date":"2022-05-30","status":"fai"} should be one of 'RENDRE_DECISION_ABROGATION,RENDRE_DECISION_ANNULATION_PAR_JUGE_ADMINISTRATIF']`
     )
   })
 
diff --git a/packages/api/src/business/rules-demarches/prm/oct.machine.ts b/packages/api/src/business/rules-demarches/prm/oct.machine.ts
index 92b02e3463298cd92fec825c132f1b71a75beda3..17475eb5a24fd5453ab1e1d931109821963879e0 100644
--- a/packages/api/src/business/rules-demarches/prm/oct.machine.ts
+++ b/packages/api/src/business/rules-demarches/prm/oct.machine.ts
@@ -129,9 +129,6 @@ const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
   RECEVOIR_INFORMATIONS: { db: EtapesTypesEtapesStatuts.receptionDinformation, mainStep: false },
 } as const
 
-// Related to https://github.com/Microsoft/TypeScript/issues/12870
-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> {
@@ -139,7 +136,7 @@ export class PrmOctMachine extends CaminoMachine<PrmOctContext, XStateEvent> {
     super(prmOctMachine, trad)
   }
 
-  toPotentialCaminoXStateEvent(event: XStateEvent['type'], date: CaminoDate): XStateEvent[] {
+  override toPotentialCaminoXStateEvent(event: XStateEvent['type'], date: CaminoDate): XStateEvent[] {
     switch (event) {
       case 'RENDRE_AVIS_DE_MISE_EN_CONCURRENCE_AU_JORF':
       case 'RENDRE_AVIS_SERVICES_ET_COMMISSIONS_CONSULTATIVES':
@@ -167,43 +164,23 @@ export class PrmOctMachine extends CaminoMachine<PrmOctContext, XStateEvent> {
     }
   }
 
-  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 'RENDRE_AVIS_SERVICES_ET_COMMISSIONS_CONSULTATIVES':
-        case 'RENDRE_AVIS_CDM':
-        case 'RENDRE_RAPPORT_DREAL':
-          return { type: eventFromEntry, date: etape.date }
-        case 'OUVRIR_PARTICIPATION_DU_PUBLIC':
-          return { type: eventFromEntry, date: etape.date, status: etape.etapeStatutId }
-        case 'FAIRE_DEMANDE':
-          if (!etape.paysId) {
-            console.info(`paysId is mandatory in etape ${JSON.stringify(etape)}, defaulting to FR.`)
+  override eventFromEntry(eventType: XStateEvent['type'], etape: Etape): XStateEvent {
+    switch (eventType) {
+      case 'FAIRE_DEMANDE':
+        if (!etape.paysId) {
+          console.info(`paysId is mandatory in etape ${JSON.stringify(etape)}, defaulting to FR.`)
 
-            return { type: eventFromEntry, paysId: 'FR', surface: etape.surface ?? 0 }
-          }
+          return { type: eventType, 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)}`)
-          }
+        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 }
-      }
+        return { type: eventType, paysId: etape.paysId, surface: etape.surface ?? 0 }
+      default:
+        return super.eventFromEntry(eventType, etape)
     }
-    throw new Error(`no event from ${JSON.stringify(etape)}`)
   }
 }
 
diff --git a/packages/api/src/business/rules-demarches/procedure-simplifiee/ps.machine.test.ts b/packages/api/src/business/rules-demarches/procedure-simplifiee/ps.machine.test.ts
index c37c3cfa797f8586f38372d7aea8b761bbba2e11..0c89324d1f83bbb113c6d072554d3736d939cc31 100644
--- a/packages/api/src/business/rules-demarches/procedure-simplifiee/ps.machine.test.ts
+++ b/packages/api/src/business/rules-demarches/procedure-simplifiee/ps.machine.test.ts
@@ -87,7 +87,7 @@ describe('vérifie l’arbre des procédures historiques et simplifiées', () =>
   test('ne peut pas faire deux dépôts de la demande', () => {
     const etapes = [ETES.demande.FAIT, ETES.depotDeLaDemande.FAIT, ETES.depotDeLaDemande.FAIT]
     expect(() => setDateAndOrderAndInterpretMachine(psMachine, '2022-04-12', etapes)).toThrowErrorMatchingInlineSnapshot(
-      `[Error: Error: cannot execute step: '{"etapeTypeId":"mdp","etapeStatutId":"fai","date":"2022-04-15"}' after '["mfr_fai","mdp_fai"]'. The event {"type":"DEPOSER_DEMANDE"} should be one of 'CLASSER_SANS_SUITE,DEMANDER_INFORMATION,DESISTER_PAR_LE_DEMANDEUR,OUVRIR_PARTICIPATION_DU_PUBLIC,RECEVOIR_INFORMATION,RENDRE_DECISION_ADMINISTRATION_ACCEPTEE,RENDRE_DECISION_ADMINISTRATION_REJETEE,RENDRE_DECISION_ADMINISTRATION_REJETEE_DECISION_IMPLICITE']`
+      `[Error: Error: cannot execute step: '{"etapeTypeId":"mdp","etapeStatutId":"fai","date":"2022-04-15"}' after '["mfr_fai","mdp_fai"]'. The event {"type":"DEPOSER_DEMANDE","date":"2022-04-15","status":"fai"} should be one of 'CLASSER_SANS_SUITE,DEMANDER_INFORMATION,DESISTER_PAR_LE_DEMANDEUR,OUVRIR_PARTICIPATION_DU_PUBLIC,RECEVOIR_INFORMATION,RENDRE_DECISION_ADMINISTRATION_ACCEPTEE,RENDRE_DECISION_ADMINISTRATION_REJETEE,RENDRE_DECISION_ADMINISTRATION_REJETEE_DECISION_IMPLICITE']`
     )
   })
 
diff --git a/packages/api/src/business/rules-demarches/procedure-simplifiee/ps.machine.ts b/packages/api/src/business/rules-demarches/procedure-simplifiee/ps.machine.ts
index 9e95e63e4e54e53f9e1418b059367621d4e481dd..407583419af9ed06afc36a3fe51c426bd5e6b959 100644
--- a/packages/api/src/business/rules-demarches/procedure-simplifiee/ps.machine.ts
+++ b/packages/api/src/business/rules-demarches/procedure-simplifiee/ps.machine.ts
@@ -1,6 +1,6 @@
 import { assign, createMachine } from 'xstate'
 import { CaminoMachine } from '../machine-helper'
-import { CaminoCommonContext, DBEtat, Etape } from '../machine-common'
+import { CaminoCommonContext, DBEtat } from '../machine-common'
 import { EtapesTypesEtapesStatuts as ETES } from 'camino-common/src/static/etapesTypesEtapesStatuts'
 import { DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts'
 import { CaminoDate, isBefore, toCaminoDate } from 'camino-common/src/date'
@@ -71,16 +71,13 @@ const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
   SAISIR_INFORMATION_HISTORIQUE_INCOMPLETE: { db: ETES.informationsHistoriquesIncompletes, mainStep: false },
 }
 
-// Related to https://github.com/Microsoft/TypeScript/issues/12870
-const EVENTS = Object.keys(trad) as Array<Extract<keyof typeof trad, string>>
-
 // basé sur https://drive.google.com/file/d/16lXyw3pcuiP-rHkBBM0U2Al9sWHKCBP9/view
 export class ProcedureSimplifieeMachine extends CaminoMachine<ProcedureSimplifieeContext, ProcedureSimplifieeXStateEvent> {
   constructor() {
     super(procedureSimplifieeMachine, trad)
   }
 
-  toPotentialCaminoXStateEvent(event: ProcedureSimplifieeXStateEvent['type'], date: CaminoDate): ProcedureSimplifieeXStateEvent[] {
+  override toPotentialCaminoXStateEvent(event: ProcedureSimplifieeXStateEvent['type'], date: CaminoDate): ProcedureSimplifieeXStateEvent[] {
     switch (event) {
       case 'RENDRE_DECISION_ADMINISTRATION_ACCEPTEE':
       case 'RENDRE_DECISION_ADMINISTRATION_REJETEE':
@@ -99,35 +96,6 @@ export class ProcedureSimplifieeMachine extends CaminoMachine<ProcedureSimplifie
         return [{ type: event }]
     }
   }
-
-  eventFrom(etape: Etape): ProcedureSimplifieeXStateEvent {
-    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 'PUBLIER_DECISION_ACCEPTEE_AU_JORF':
-        case 'PUBLIER_DECISION_AU_RECUEIL_DES_ACTES_ADMINISTRATIFS':
-        case 'SAISIR_INFORMATION_HISTORIQUE_INCOMPLETE':
-        case 'RENDRE_DECISION_ADMINISTRATION_ACCEPTEE':
-        case 'RENDRE_DECISION_ADMINISTRATION_REJETEE':
-        case 'RENDRE_DECISION_ADMINISTRATION_REJETEE_DECISION_IMPLICITE': {
-          return { type: eventFromEntry, date: etape.date }
-        }
-        case 'OUVRIR_PARTICIPATION_DU_PUBLIC': {
-          return { type: eventFromEntry, status: etape.etapeStatutId }
-        }
-
-        default:
-          return { type: eventFromEntry }
-      }
-    }
-    throw new Error(`no event from ${JSON.stringify(etape)}`)
-  }
 }
 
 interface ProcedureSimplifieeContext extends CaminoCommonContext {
diff --git a/packages/api/src/business/rules-demarches/procedure-specifique/procedure-specifique.machine.test.ts b/packages/api/src/business/rules-demarches/procedure-specifique/procedure-specifique.machine.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1c5b9bf287f54357e8e06ba96d604d204eb18c57
--- /dev/null
+++ b/packages/api/src/business/rules-demarches/procedure-specifique/procedure-specifique.machine.test.ts
@@ -0,0 +1,92 @@
+import { orderAndInterpretMachine, setDateAndOrderAndInterpretMachine } from '../machine-test-helper'
+import { toCaminoDate } from 'camino-common/src/date'
+import { describe, expect, test } from 'vitest'
+import { DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts'
+import { ProcedureSpecifiqueMachine } from './procedure-specifique.machine'
+import { EtapesTypesEtapesStatuts as ETES } from 'camino-common/src/static/etapesTypesEtapesStatuts'
+
+const psPccOctMachine = new ProcedureSpecifiqueMachine('pcc', 'oct')
+const psCxmOctMachine = new ProcedureSpecifiqueMachine('cxm', 'oct')
+const psPrmProMachine = new ProcedureSpecifiqueMachine('prm', 'pro')
+const psArmProMachine = new ProcedureSpecifiqueMachine('arm', 'pro')
+
+describe('vérifie l’arbre des procédures spécifique', () => {
+  test('statut de la démarche simplifiee sans étape', () => {
+    const service = orderAndInterpretMachine(psPccOctMachine, [])
+    expect(service).canOnlyTransitionTo({ machine: psPccOctMachine, date: toCaminoDate('2024-10-10') }, ['FAIRE_DEMANDE'])
+    expect(service.getSnapshot().context.demarcheStatut).toBe(DemarchesStatutsIds.EnConstruction)
+  })
+  test('demande irrecevable', () => {
+    const { service, dateFin } = setDateAndOrderAndInterpretMachine(psPccOctMachine, '1999-04-14', [
+      ETES.demande.FAIT,
+      ETES.depotDeLaDemande.FAIT,
+      ETES.recevabiliteDeLaDemande.DEFAVORABLE,
+      ETES.demandeDeComplements.FAIT,
+      ETES.receptionDeComplements.FAIT,
+      ETES.declarationDIrrecevabilite.FAIT,
+    ])
+    expect(service).canOnlyTransitionTo({ machine: psPccOctMachine, date: dateFin }, [])
+    expect(service.getSnapshot().context.demarcheStatut).toBe(DemarchesStatutsIds.Rejete)
+    expect(service.getSnapshot().context.visibilite).toBe('confidentielle')
+  })
+  test('on peut notifier le demandeur apres une recevabilité favorable pour un PER ou une concession', () => {
+    const { service, dateFin } = setDateAndOrderAndInterpretMachine(psCxmOctMachine, '1999-04-14', [
+      ETES.demande.FAIT,
+      ETES.depotDeLaDemande.FAIT,
+      ETES.recevabiliteDeLaDemande.FAVORABLE,
+      ETES.notificationAuDemandeur.FAIT,
+    ])
+    expect(service).canOnlyTransitionTo({ machine: psCxmOctMachine, date: dateFin }, ['NOTIFIER_DEMANDEUR'])
+  })
+  test('on ne peut pas notifier le demandeur apres une recevabilité favorable pour pcc', () => {
+    expect(() =>
+      setDateAndOrderAndInterpretMachine(psPccOctMachine, '1999-04-14', [ETES.demande.FAIT, ETES.depotDeLaDemande.FAIT, ETES.recevabiliteDeLaDemande.FAVORABLE, ETES.notificationAuDemandeur.FAIT])
+    ).toThrowErrorMatchingInlineSnapshot(
+      `[Error: Error: cannot execute step: '{"etapeTypeId":"mno","etapeStatutId":"fai","date":"1999-04-18"}' after '["mfr_fai","mdp_fai","mcr_fav"]'. The event {"type":"NOTIFIER_DEMANDEUR","date":"1999-04-18","status":"fai"} should be one of '']`
+    )
+  })
+  test("après la recevabilité favorable la démarche devient publique si il n'y a pas de mise en concurrence", () => {
+    const { service, dateFin } = setDateAndOrderAndInterpretMachine(psPrmProMachine, '1999-04-14', [ETES.demande.FAIT, ETES.depotDeLaDemande.FAIT, ETES.recevabiliteDeLaDemande.FAVORABLE])
+
+    expect(service).canOnlyTransitionTo({ machine: psPrmProMachine, date: dateFin }, ['RENDRE_AVIS_CGE_IGEDD', 'NOTIFIER_DEMANDEUR'])
+    expect(service.getSnapshot().context.visibilite).toBe('publique')
+  })
+  test('après la recevabilité favorable la démarche reste confidentielle si il y a une mise en concurrence', () => {
+    const { service, dateFin } = setDateAndOrderAndInterpretMachine(psCxmOctMachine, '1999-04-14', [ETES.demande.FAIT, ETES.depotDeLaDemande.FAIT, ETES.recevabiliteDeLaDemande.FAVORABLE])
+
+    expect(service).canOnlyTransitionTo({ machine: psCxmOctMachine, date: dateFin }, ['NOTIFIER_DEMANDEUR'])
+    expect(service.getSnapshot().context.visibilite).toBe('confidentielle')
+  })
+  test("ne peut pas rendre la décision de l'administration si la participation du public n'est pas terminée", () => {
+    const { service, dateFin } = setDateAndOrderAndInterpretMachine(psArmProMachine, '1999-04-14', [
+      ETES.demande.FAIT,
+      ETES.depotDeLaDemande.FAIT,
+      ETES.recevabiliteDeLaDemande.FAVORABLE,
+      ETES.avisDesCollectivites.FAIT,
+      ETES.avisDesServicesEtCommissionsConsultatives.FAIT,
+      ETES.avisDuPrefet.FAVORABLE,
+      ETES.participationDuPublic.EN_COURS,
+    ])
+
+    expect(service).canOnlyTransitionTo({ machine: psArmProMachine, date: dateFin }, [])
+    expect(service.getSnapshot().context.visibilite).toBe('publique')
+  })
+  test("réalise une demande de prolongation d'ARM complète", () => {
+    const { service, dateFin } = setDateAndOrderAndInterpretMachine(psArmProMachine, '1999-04-14', [
+      ETES.demande.FAIT,
+      ETES.depotDeLaDemande.FAIT,
+      ETES.recevabiliteDeLaDemande.FAVORABLE,
+      ETES.avisDesCollectivites.FAIT,
+      ETES.avisDesServicesEtCommissionsConsultatives.FAIT,
+      ETES.avisDuPrefet.FAVORABLE,
+      ETES.participationDuPublic.TERMINE,
+      ETES.decisionDeLadministration.ACCEPTE,
+    ])
+
+    expect(service).canOnlyTransitionTo({ machine: psArmProMachine, date: dateFin }, [])
+    expect(service.getSnapshot().context.visibilite).toBe('publique')
+  })
+
+  // FIXMACHINE tester que la participation du public peut-être optionnelle
+  // FIXMACHINE migrer l'enquête publique sur master
+})
diff --git a/packages/api/src/business/rules-demarches/procedure-specifique/procedure-specifique.machine.ts b/packages/api/src/business/rules-demarches/procedure-specifique/procedure-specifique.machine.ts
new file mode 100644
index 0000000000000000000000000000000000000000..df51a4fd00fd56985c01e3b27f7e857d303daada
--- /dev/null
+++ b/packages/api/src/business/rules-demarches/procedure-specifique/procedure-specifique.machine.ts
@@ -0,0 +1,367 @@
+import { and, assign, not, or, setup } from 'xstate'
+import { CaminoMachine } from '../machine-helper'
+import { CaminoCommonContext, DBEtat } from '../machine-common'
+import { EtapesTypesEtapesStatuts as ETES } from 'camino-common/src/static/etapesTypesEtapesStatuts'
+import { DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts'
+import { TITRES_TYPES_IDS, TitreTypeId, getTitreTypeType } from 'camino-common/src/static/titresTypes'
+import { DEMARCHES_TYPES_IDS, DemarcheTypeId, isDemarcheTypeProlongations } from 'camino-common/src/static/demarchesTypes'
+import { TITRES_TYPES_TYPES_IDS } from 'camino-common/src/static/titresTypesTypes'
+import { ETAPES_STATUTS, EtapeStatutId } from 'camino-common/src/static/etapesStatuts'
+import { KM2, km2Validator } from 'camino-common/src/number'
+import { CaminoDate } from 'camino-common/src/date'
+// type SaisirInformationHistoriqueIncomplete = {
+//   date: CaminoDate
+//   type: 'SAISIR_INFORMATION_HISTORIQUE_INCOMPLETE'
+// }
+// type RendreDecisionAdministrationAcceptee = {
+//   date: CaminoDate
+//   type: 'RENDRE_DECISION_ADMINISTRATION_ACCEPTEE'
+// }
+// type RendreDecisionAdministrationRejetee = {
+//   date: CaminoDate
+//   type: 'RENDRE_DECISION_ADMINISTRATION_REJETEE'
+// }
+// type RendreDecisionAdministrationRejeteeDecisionImplicite = {
+//   date: CaminoDate
+//   type: 'RENDRE_DECISION_ADMINISTRATION_REJETEE_DECISION_IMPLICITE'
+// }
+// type PublierDecisionAccepteeAuJORF = {
+//   date: CaminoDate
+//   type: 'PUBLIER_DECISION_ACCEPTEE_AU_JORF'
+// }
+// type PublierDecisionAuRecueilDesActesAdministratifs = {
+//   date: CaminoDate
+//   type: 'PUBLIER_DECISION_AU_RECUEIL_DES_ACTES_ADMINISTRATIFS'
+// }
+
+type ParticipationDuPublic = {
+  surface: KM2
+  status: EtapeStatutId
+  type: 'OUVRIR_PARTICIPATION_DU_PUBLIC'
+}
+
+type EnqueteDuPublic = {
+  surface: KM2
+  status: EtapeStatutId
+  type: 'OUVRIR_ENQUETE_PUBLIQUE'
+}
+type ProcedureSpecifiqueXStateEvent =
+  | { type: 'FAIRE_DEMANDE' }
+  | { type: 'DEPOSER_DEMANDE' }
+  | { type: 'FAIRE_RECEVABILITE_FAVORABLE' }
+  | { type: 'FAIRE_RECEVABILITE_DEFAVORABLE' }
+  | { type: 'FAIRE_DEMANDE_DE_COMPLEMENTS' }
+  | { type: 'RECEVOIR_COMPLEMENTS' }
+  | { type: 'FAIRE_DECLARATION_IRRECEVABILITE' }
+  | { type: 'NOTIFIER_DEMANDEUR' }
+  | { type: 'RENDRE_AVIS_CGE_IGEDD' }
+  | { type: 'FAIRE_LETTRE_SAISINE_PREFET' }
+  | { type: 'RENDRE_AVIS_COLLECTIVITES' }
+  | { type: 'RENDRE_AVIS_SERVICES_COMMISSIONS' }
+  | { type: 'RENDRE_AVIS_PREFET' }
+  | ParticipationDuPublic
+  | EnqueteDuPublic
+  | { type: 'RENDRE_DECISION_ADMINISTRATION_ACCEPTEE' }
+// | RendreDecisionAdministrationAcceptee
+// | RendreDecisionAdministrationRejetee
+// | RendreDecisionAdministrationRejeteeDecisionImplicite
+// | SaisirInformationHistoriqueIncomplete
+// | PublierDecisionAccepteeAuJORF
+// | PublierDecisionAuRecueilDesActesAdministratifs
+// | { type: 'CLASSER_SANS_SUITE' }
+// | { type: 'DESISTER_PAR_LE_DEMANDEUR' }
+// | { type: 'DEMANDER_INFORMATION' }
+// | { type: 'RECEVOIR_INFORMATION' }
+// | { type: 'FAIRE_ABROGATION' }
+
+type Event = ProcedureSpecifiqueXStateEvent['type']
+
+const trad: { [key in Event]: { db: DBEtat; mainStep: boolean } } = {
+  FAIRE_DEMANDE: { db: ETES.demande, mainStep: true },
+  DEPOSER_DEMANDE: { db: ETES.depotDeLaDemande, mainStep: true },
+  FAIRE_RECEVABILITE_FAVORABLE: { db: { FAVORABLE: ETES.recevabiliteDeLaDemande.FAVORABLE }, mainStep: true },
+  FAIRE_RECEVABILITE_DEFAVORABLE: { db: { DEFAVORABLE: ETES.recevabiliteDeLaDemande.DEFAVORABLE }, mainStep: false },
+  FAIRE_DEMANDE_DE_COMPLEMENTS: { db: ETES.demandeDeComplements, mainStep: false },
+  RECEVOIR_COMPLEMENTS: { db: ETES.receptionDeComplements, mainStep: false },
+  FAIRE_DECLARATION_IRRECEVABILITE: { db: ETES.declarationDIrrecevabilite, mainStep: false },
+  NOTIFIER_DEMANDEUR: { db: ETES.notificationAuDemandeur, mainStep: false },
+  RENDRE_AVIS_CGE_IGEDD: { db: ETES.avisDuConseilGeneralDeLeconomie_CGE_, mainStep: true },
+  FAIRE_LETTRE_SAISINE_PREFET: { db: ETES.saisineDuPrefet, mainStep: true },
+  RENDRE_AVIS_COLLECTIVITES: { db: ETES.avisDesCollectivites, mainStep: true },
+  RENDRE_AVIS_SERVICES_COMMISSIONS: { db: ETES.avisDesServicesEtCommissionsConsultatives, mainStep: true },
+  RENDRE_AVIS_PREFET: { db: ETES.avisDuPrefet, mainStep: true },
+  OUVRIR_ENQUETE_PUBLIQUE: { db: ETES.ouvertureDeLenquetePublique, mainStep: true },
+  OUVRIR_PARTICIPATION_DU_PUBLIC: { db: ETES.participationDuPublic, mainStep: true },
+  RENDRE_DECISION_ADMINISTRATION_ACCEPTEE: { db: { ACCEPTE: ETES.decisionDeLadministration.ACCEPTE }, mainStep: true },
+  // RECEVOIR_REPONSE_DEMANDEUR: {db: ETES.demandeur}
+
+  // OUVRIR_PARTICIPATION_DU_PUBLIC: { db: ETES.participationDuPublic, mainStep: true },
+  // RENDRE_DECISION_ADMINISTRATION_ACCEPTEE: { db: { ACCEPTE: ETES.decisionDeLadministration.ACCEPTE }, mainStep: true },
+  // RENDRE_DECISION_ADMINISTRATION_REJETEE: { db: { REJETE: ETES.decisionDeLadministration.REJETE }, mainStep: true },
+  // RENDRE_DECISION_ADMINISTRATION_REJETEE_DECISION_IMPLICITE: { db: { REJETE_DECISION_IMPLICITE: ETES.decisionDeLadministration.REJETE_DECISION_IMPLICITE }, mainStep: true },
+  // PUBLIER_DECISION_ACCEPTEE_AU_JORF: { db: { FAIT: ETES.publicationDeDecisionAuJORF.FAIT }, mainStep: true },
+  // PUBLIER_DECISION_AU_RECUEIL_DES_ACTES_ADMINISTRATIFS: { db: ETES.publicationDeDecisionAuRecueilDesActesAdministratifs, mainStep: true },
+  // CLASSER_SANS_SUITE: { db: ETES.classementSansSuite, mainStep: false },
+  // DESISTER_PAR_LE_DEMANDEUR: { db: ETES.desistementDuDemandeur, mainStep: false },
+  // DEMANDER_INFORMATION: { db: ETES.demandeDinformations, mainStep: false },
+  // RECEVOIR_INFORMATION: { db: ETES.receptionDinformation, mainStep: false },
+  // FAIRE_ABROGATION: { db: ETES.abrogationDeLaDecision, mainStep: true },
+  // SAISIR_INFORMATION_HISTORIQUE_INCOMPLETE: { db: ETES.informationsHistoriquesIncompletes, mainStep: false },
+}
+
+// basé sur https://drive.google.com/drive/u/1/folders/1U_in35zSb837xCp_fp31I0vOmb36QguL
+export class ProcedureSpecifiqueMachine extends CaminoMachine<ProcedureSpecifiqueContext, ProcedureSpecifiqueXStateEvent> {
+  constructor(titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId) {
+    super(procedureSpecifiqueMachine(titreTypeId, demarcheTypeId), trad)
+  }
+
+  override toPotentialCaminoXStateEvent(event: ProcedureSpecifiqueXStateEvent['type'], date: CaminoDate): ProcedureSpecifiqueXStateEvent[] {
+    switch (event) {
+      // case 'FAIRE_DEMANDE':
+      // case 'NOTIFIER_DEMANDEUR':
+      //   return [
+      //     { type: event, titreTypeId: 'cxm', demarcheTypeId: 'oct' },
+      //     { type: event, titreTypeId: 'arm', demarcheTypeId: 'oct' },
+      //   ]
+      // case 'RENDRE_DECISION_ADMINISTRATION_ACCEPTEE':
+      // case 'RENDRE_DECISION_ADMINISTRATION_REJETEE':
+      // case 'RENDRE_DECISION_ADMINISTRATION_REJETEE_DECISION_IMPLICITE':
+      // case 'SAISIR_INFORMATION_HISTORIQUE_INCOMPLETE':
+      // case 'PUBLIER_DECISION_ACCEPTEE_AU_JORF':
+      // case 'PUBLIER_DECISION_AU_RECUEIL_DES_ACTES_ADMINISTRATIFS':
+      //   return [{ type: event, date }]
+      case 'OUVRIR_ENQUETE_PUBLIQUE':
+      case 'OUVRIR_PARTICIPATION_DU_PUBLIC':
+        return [
+          { type: event, status: ETAPES_STATUTS.PROGRAMME, surface: km2Validator.parse(0.24) },
+          { type: event, status: ETAPES_STATUTS.EN_COURS, surface: km2Validator.parse(0.24) },
+          { type: event, status: ETAPES_STATUTS.TERMINE, surface: km2Validator.parse(0.24) },
+          { type: event, status: ETAPES_STATUTS.PROGRAMME, surface: km2Validator.parse(0.26) },
+          { type: event, status: ETAPES_STATUTS.EN_COURS, surface: km2Validator.parse(0.26) },
+          { type: event, status: ETAPES_STATUTS.TERMINE, surface: km2Validator.parse(0.26) },
+        ]
+      default:
+        return super.toPotentialCaminoXStateEvent(event, date)
+    }
+  }
+}
+
+interface ProcedureSpecifiqueContext extends CaminoCommonContext {}
+const defaultDemarcheStatut = DemarchesStatutsIds.EnConstruction
+const procedureSpecifiqueMachine = (titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId) =>
+  setup({
+    types: {} as { context: ProcedureSpecifiqueContext; events: ProcedureSpecifiqueXStateEvent },
+    guards: {
+      isPublique: ({ context }) => context.visibilite === 'publique',
+      isPerOuConcession: () => [TITRES_TYPES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES, TITRES_TYPES_TYPES_IDS.CONCESSION].includes(getTitreTypeType(titreTypeId)),
+      hasMiseEnConcurrence: () =>
+        [DEMARCHES_TYPES_IDS.Octroi, DEMARCHES_TYPES_IDS.ExtensionDePerimetre].includes(demarcheTypeId) ||
+        (isDemarcheTypeProlongations(demarcheTypeId) && getTitreTypeType(titreTypeId) === TITRES_TYPES_TYPES_IDS.CONCESSION),
+      isAxmOuAr: () => TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX === titreTypeId || TITRES_TYPES_TYPES_IDS.AUTORISATION_DE_RECHERCHE === getTitreTypeType(titreTypeId),
+      // FIXMACHINE à vérifier et à tester
+      isEnquetePubliqueRequired: ({ event }) =>
+        ((DEMARCHES_TYPES_IDS.Octroi === demarcheTypeId || isDemarcheTypeProlongations(demarcheTypeId)) &&
+          [
+            TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS,
+            TITRES_TYPES_IDS.CONCESSION_METAUX,
+            TITRES_TYPES_IDS.CONCESSION_GRANULATS_MARINS,
+            TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE,
+            TITRES_TYPES_IDS.CONCESSION_SOUTERRAIN,
+            TITRES_TYPES_IDS.CONCESSION_GEOTHERMIE,
+          ].includes(titreTypeId)) ||
+        (titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX && (event.type === 'OUVRIR_PARTICIPATION_DU_PUBLIC' || event.type === 'OUVRIR_ENQUETE_PUBLIQUE') && event.surface > 0.25),
+      isEnquetePubliquePossible: ({ event }) =>
+        titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX && (event.type === 'OUVRIR_PARTICIPATION_DU_PUBLIC' || event.type === 'OUVRIR_ENQUETE_PUBLIQUE') && event.surface <= 0.25,
+    },
+  }).createMachine({
+    id: 'ProcedureSpecifique',
+    initial: 'demandeAFaire',
+    context: {
+      demarcheStatut: defaultDemarcheStatut,
+      visibilite: 'confidentielle',
+    },
+    states: {
+      demandeAFaire: {
+        on: {
+          FAIRE_DEMANDE: {
+            target: 'depotDeLaDemandeAFaire',
+            actions: assign({
+              demarcheStatut: DemarchesStatutsIds.EnInstruction,
+            }),
+          },
+        },
+      },
+      depotDeLaDemandeAFaire: {
+        on: {
+          DEPOSER_DEMANDE: 'recevabiliteOuInformationDuPrefetEtCollectivitesAFaire',
+        },
+      },
+
+      recevabiliteOuInformationDuPrefetEtCollectivitesAFaire: {
+        on: {
+          // FIXMACHINE
+          // RENDRE_INFORMATION_DU_PREFET_ET_DES_COLLECTIVITES: {
+          //   target: 'recevabiliteOuInformationDuPrefetEtCollectivitesAFaire',
+          // guard: 'isPerOuConcession'
+          // },
+          FAIRE_RECEVABILITE_FAVORABLE: 'recevabiliteFavorableFaite',
+          FAIRE_RECEVABILITE_DEFAVORABLE: 'demandeDeComplementsAFaire',
+        },
+      },
+      demandeDeComplementsAFaire: {
+        on: {
+          FAIRE_DEMANDE_DE_COMPLEMENTS: 'reponseALaDemandeDeComplements',
+        },
+      },
+      // FIXMACHINE brouillonable
+      reponseALaDemandeDeComplements: {
+        on: {
+          RECEVOIR_COMPLEMENTS: 'recevabiliteOuIrrecevabiliteAFaire',
+        },
+      },
+      recevabiliteOuIrrecevabiliteAFaire: {
+        on: {
+          FAIRE_RECEVABILITE_FAVORABLE: 'recevabiliteFavorableFaite',
+          FAIRE_RECEVABILITE_DEFAVORABLE: 'demandeDeComplementsAFaire',
+          FAIRE_DECLARATION_IRRECEVABILITE: {
+            target: 'finDeMachine',
+            actions: assign({
+              demarcheStatut: DemarchesStatutsIds.Rejete,
+            }),
+          },
+        },
+      },
+      recevabiliteFavorableFaite: {
+        always: [
+          {
+            guard: and([not('hasMiseEnConcurrence'), not('isPublique')]),
+            actions: assign({ visibilite: 'publique' }),
+          },
+          {
+            target: 'avisCollectivitesEtServicesEtCommissionsAFaireMachine',
+            guard: and([not('hasMiseEnConcurrence'), 'isAxmOuAr']),
+          },
+        ],
+        on: {
+          // FIXMACHINE ajouter la mise en concurrence
+          RENDRE_AVIS_CGE_IGEDD: {
+            // FIXMACHINE ajouter la demande de modification de l'aes
+            target: 'notificationAuDemandeurAFaire',
+            guard: and([not('hasMiseEnConcurrence'), not('isAxmOuAr')]),
+          },
+          NOTIFIER_DEMANDEUR: {
+            target: 'recevabiliteFavorableFaite',
+            guard: 'isPerOuConcession',
+          },
+        },
+      },
+
+      notificationAuDemandeurAFaire: {
+        on: { NOTIFIER_DEMANDEUR: 'lettreDeSaisineDuPrefetOuReponseDuDemandeurAFaire' },
+      },
+      lettreDeSaisineDuPrefetOuReponseDuDemandeurAFaire: {
+        on: {
+          // FIXMACHINE brouillon
+          // FIXMACHINE 'RECEVOIR_REPONSE_DEMANDEUR': 'lettreDeSaisineDuPrefetOuReponseDuDemandeurAFaire',
+          FAIRE_LETTRE_SAISINE_PREFET: 'avisCollectivitesEtServicesEtCommissionsAFaireMachine',
+        },
+      },
+
+      avisCollectivitesEtServicesEtCommissionsAFaireMachine: {
+        type: 'parallel',
+        states: {
+          avisARendreMachine: {
+            initial: 'avisARendre',
+            states: {
+              avisARendre: {
+                type: 'parallel',
+
+                states: {
+                  avisCollectivitesARendreMachine: {
+                    initial: 'avisCollectivitesARendre',
+                    states: {
+                      avisCollectivitesARendre: {
+                        // FIXMACHINE brouillon
+                        on: { RENDRE_AVIS_COLLECTIVITES: 'fin' },
+                      },
+                      fin: { type: 'final' },
+                    },
+                  },
+                  avisServicesEtCommissionsRendreMachine: {
+                    initial: 'avisServicesEtCommissionsRendre',
+                    states: {
+                      avisServicesEtCommissionsRendre: {
+                        // FIXMACHINE brouillon
+                        on: { RENDRE_AVIS_SERVICES_COMMISSIONS: 'fin' },
+                      },
+                      fin: { type: 'final' },
+                    },
+                  },
+                },
+                onDone: 'avisDuPrefetARendre',
+              },
+              avisDuPrefetARendre: {
+                // FIXMACHINE gérer l'avis de la commission CDM
+                on: { RENDRE_AVIS_PREFET: 'fin' },
+              },
+              fin: {
+                type: 'final',
+              },
+            },
+          },
+          participationOuEnqueteDuPublicMachine: {
+            initial: 'participationOuEnquetePublicAFaire',
+            states: {
+              participationOuEnquetePublicAFaire: {
+                on: {
+                  OUVRIR_ENQUETE_PUBLIQUE: [
+                    {
+                      target: 'fin',
+                      guard: and([or(['isEnquetePubliqueRequired', 'isEnquetePubliquePossible']), ({ event }) => event.status === ETAPES_STATUTS.TERMINE]),
+                    },
+                    {
+                      target: 'enAttente',
+                      guard: ({ event }) => event.status !== ETAPES_STATUTS.TERMINE,
+                    },
+                  ],
+                  OUVRIR_PARTICIPATION_DU_PUBLIC: [
+                    {
+                      target: 'fin',
+                      guard: and([not('isEnquetePubliqueRequired'), ({ event }) => event.status === ETAPES_STATUTS.TERMINE]),
+                    },
+                    {
+                      target: 'enAttente',
+                      guard: ({ event }) => event.status !== ETAPES_STATUTS.TERMINE,
+                    },
+                  ],
+                },
+              },
+              enAttente: {},
+              fin: {
+                type: 'final',
+              },
+            },
+          },
+        },
+        onDone: 'decisionAdministrationAFaire',
+      },
+      decisionAdministrationAFaire: {
+        on: {
+          RENDRE_DECISION_ADMINISTRATION_ACCEPTEE: 'finDeMachine',
+        },
+      },
+      finDeMachine: {
+        type: 'final',
+      },
+    },
+  })
+
+// FIXMACHINE questions POH
+// - L'irrecevabilité est faisable que après une demande de compléments ? -> OUI
+// - C'est une toute nouvelle étape « Information du préfet et des collectivités » ? Est-ce que ça serait pas une fusion d'anciennes étapes ? -> c'est tout nouveau
+// - Est-ce que l'information du préfet et des collectivités est faite 2 fois ? -> Non que une fois
+//
+// - « avisDuConseilGeneralDeLeconomie_CGE_ » ça passe pour l'étape « avis du CGE et de l'IGEDD » ? => Renommer l'étape
+// - l'étape « avis du CGE et de l'IGEDD » n'a pas de statut favorable / défavorable ? => C'est une étape d'avis donc c'est FAIT
+// - comment on peut avoir une mise en concurrence si la démarche n'est pas publique ? => Modif du logigramme, ça devient publique dés que la mise en concurrence est « en cours »
+// - Pour l'enquête et la participation du public, la démarche est déjà publique => Heuuuu non, modif à faire dans le logigramme
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 ed29958ae7ed2c62be977bbfd4ec4df61e5a2633..47b3adbdbb0cc3e20b4954b948b219870eb31b0a 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
@@ -18,6 +18,7 @@ const etapesBuild = (etapesProps: Partial<ITitreEtape>[]) =>
         contenu: null,
         ...etapeProps,
         ordre: i + 1,
+        date: toCaminoDate('0001-01-01'),
       }) as unknown as ITitreEtape
   )
 
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 9f93cd92ace74d15db6af9039d2f6ae0a13f2ceb..0316d13780efef468e5b784702832186da5c337c 100644
--- a/packages/api/src/business/rules/titre-demarche-public-find.ts
+++ b/packages/api/src/business/rules/titre-demarche-public-find.ts
@@ -3,7 +3,7 @@ import { EtapeTypeId } from 'camino-common/src/static/etapesTypes'
 import { getDomaineId, TitreTypeId } from 'camino-common/src/static/titresTypes'
 import { getEtapesTDE } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index'
 import { ITitreEtape, ITitreDemarche } from '../../types'
-import { demarcheDefinitionFind } from '../rules-demarches/definitions'
+import { machineFind } from '../rules-demarches/definitions'
 import { titreEtapeForMachineValidator, toMachineEtapes } from '../rules-demarches/machine-common'
 import { titreEtapesSortAscByOrdre } from '../utils/titre-etapes-sort'
 import { titreInModificationEnInstance } from './titre-statut-id-find'
@@ -154,7 +154,10 @@ const titreDemarchePublicLectureFind = (
  * @param titreTypeId - id du type de titre
  */
 
-export const titreDemarchePublicFind = (titreDemarche: Pick<ITitreDemarche, 'titreId' | 'demarcheDateDebut' | 'demarcheDateFin' | 'id' | 'typeId' | 'etapes'>, titreTypeId: TitreTypeId) => {
+export const titreDemarchePublicFind = (
+  titreDemarche: Pick<ITitreDemarche, 'titreId' | 'demarcheDateDebut' | 'demarcheDateFin' | 'id' | 'typeId' | 'etapes'>,
+  titreTypeId: TitreTypeId
+): { publicLecture: boolean; entreprisesLecture: boolean } => {
   const titreDemarcheEtapes = titreEtapesSortAscByOrdre(titreDemarche.etapes ?? [])
 
   // calcule la visibilité publique ou non de la démarche
@@ -165,10 +168,10 @@ export const titreDemarchePublicFind = (titreDemarche: Pick<ITitreDemarche, 'tit
   if (titreDemarche.titreId === 'WQaZgPfDcQw9tFliMgBIDH3Z') {
     publicLecture = false
   } else {
-    const demarcheDefinition = demarcheDefinitionFind(titreTypeId, titreDemarche.typeId, titreDemarcheEtapes, titreDemarche.id)
+    const machine = machineFind(titreTypeId, titreDemarche.typeId, titreDemarcheEtapes, titreDemarche.id)
 
-    if (demarcheDefinition) {
-      publicLecture = demarcheDefinition.machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes.map(etape => titreEtapeForMachineValidator.parse(etape)))).publique
+    if (machine) {
+      publicLecture = 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 baa21f81bc5df249499d9ecfeaa618cdf5323649..0a1741b92973877145a4be2a1bf99c650cf778aa 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
@@ -9,13 +9,18 @@ import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts'
 import { TitreEtapeForMachine } from '../rules-demarches/machine-common'
 import { ETAPE_IS_BROUILLON, ETAPE_IS_NOT_BROUILLON } from 'camino-common/src/etape'
 import { EtapeTypeId } from 'camino-common/src/static/etapesTypes'
-const etapesBuild = (etapesProps: Partial<ITitreEtape>[]): TitreEtapeForMachine[] =>
+import { TitreTypeId } from 'camino-common/src/static/titresTypes'
+import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes'
+const etapesBuild = (etapesProps: Partial<ITitreEtape>[], demarcheTypeId: DemarcheTypeId = 'oct', titreTypeId: TitreTypeId = 'axm'): TitreEtapeForMachine[] =>
   etapesProps.map(
     (etapeProps, i) =>
       ({
         ...etapeProps,
         isBrouillon: etapeProps.isBrouillon ?? ETAPE_IS_NOT_BROUILLON,
         ordre: i + 1,
+        titreTypeId,
+        demarcheTypeId,
+        date: toCaminoDate('0001-01-01'),
       }) as unknown as TitreEtapeForMachine
   )
 
@@ -25,17 +30,21 @@ describe("statut d'une démarche", () => {
   })
 
   test("une démarche d'octroi sans étape décisive a le statut “indéfini”", () => {
-    expect(titreDemarcheStatutIdFind('oct', etapesBuild([{ typeId: 'anf' }]), 'pxm', newDemarcheId())).toEqual('ind')
+    expect(titreDemarcheStatutIdFind('oct', etapesBuild([{ typeId: 'anf' }], 'oct', 'pxm'), 'pxm', newDemarcheId())).toEqual('ind')
   })
 
   test("une démarche d'octroi dont l'étape de dpu la plus récente est acceptée a le statut “accepté”", () => {
     expect(
       titreDemarcheStatutIdFind(
         'oct',
-        etapesBuild([
-          { typeId: 'dex', statutId: 'acc' },
-          { typeId: 'dpu', statutId: 'acc' },
-        ]),
+        etapesBuild(
+          [
+            { typeId: 'dex', statutId: 'acc' },
+            { typeId: 'dpu', statutId: 'acc' },
+          ],
+          'oct',
+          'pxm'
+        ),
         'pxm',
         newDemarcheId()
       )
@@ -43,7 +52,7 @@ describe("statut d'une démarche", () => {
   })
 
   test("une démarche d'octroi d'un titre AXM dont l'étape de dex la plus récente est acceptée a le statut “accepté”", () => {
-    expect(titreDemarcheStatutIdFind('oct', etapesBuild([{ typeId: 'dex', date: toCaminoDate('2010-01-01'), statutId: 'acc' }]), 'axm', newDemarcheId())).toEqual('acc')
+    expect(titreDemarcheStatutIdFind('oct', etapesBuild([{ typeId: 'dex', date: toCaminoDate('2010-01-01'), statutId: 'acc' }], 'oct', 'axm'), 'axm', newDemarcheId())).toEqual('acc')
   })
 
   test("une démarche d'octroi d'un titre ARM dont l'étape de def la plus récente est acceptée a le statut “accepté”", () => {
@@ -64,7 +73,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', date: toCaminoDate('2010-01-01'), statutId: 'acc' }]), 'prm', newDemarcheId())).toEqual('acc')
+    expect(titreDemarcheStatutIdFind('oct', etapesBuild([{ typeId: 'rpu', date: toCaminoDate('2010-01-01'), statutId: 'acc' }], 'oct', 'prm'), '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é”", () => {
@@ -166,10 +175,14 @@ describe("statut d'une démarche", () => {
     expect(
       titreDemarcheStatutIdFind(
         'oct',
-        etapesBuild([
-          { typeId: 'mfr', statutId: 'fai' },
-          { typeId: 'mdp', statutId: 'fai' },
-        ]),
+        etapesBuild(
+          [
+            { typeId: 'mfr', statutId: 'fai' },
+            { typeId: 'mdp', statutId: 'fai' },
+          ],
+          'oct',
+          'arm'
+        ),
         'arm',
         newDemarcheId()
       )
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 cc28248481b1d0b11c65b1d58094d6a9a7cee9e1..75e360419999f9fb8c3bb8180d7b20692096a1cc 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,13 +3,14 @@ import { DemarcheId } from 'camino-common/src/demarche'
 
 import { titreEtapesSortDescByOrdre } from '../utils/titre-etapes-sort'
 import { titreEtapePublicationCheck } from './titre-etape-publication-check'
-import { demarcheDefinitionFind } from '../rules-demarches/definitions'
+import { machineFind } from '../rules-demarches/definitions'
 import { TitreEtapeForMachine, toMachineEtapes } from '../rules-demarches/machine-common'
 import { DemarcheStatutId, DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts'
 import { TitreTypeId } from 'camino-common/src/static/titresTypes'
 import { DemarcheTypeId, TravauxIds } from 'camino-common/src/static/demarchesTypes'
 import { EtapeTypeId } from 'camino-common/src/static/etapesTypes'
 import { isEtapeStatusRejete } from 'camino-common/src/static/etapesStatuts'
+import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools'
 
 const titreEtapesDecisivesCommunesTypes: EtapeTypeId[] = ['css', 'abd', 'and']
 
@@ -283,10 +284,10 @@ export const titreDemarcheStatutIdFind = (demarcheTypeId: DemarcheTypeId, titreD
     return titreDemarcheTravauxStatutIdFind(titreDemarcheEtapes, demarcheTypeId)
   }
 
-  const demarcheDefinition = demarcheDefinitionFind(titreTypeId, demarcheTypeId, titreDemarcheEtapes, demarcheId)
+  const machine = machineFind(titreTypeId, demarcheTypeId, titreDemarcheEtapes, demarcheId)
 
-  if (demarcheDefinition) {
-    return demarcheDefinition.machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes)).demarcheStatut
+  if (isNotNullNorUndefined(machine)) {
+    return machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes)).demarcheStatut
   }
 
   //  si la démarche fait l’objet d’une demande
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 90da1d1043c77264e336fa16ca6de9ef47db3272..0944ce5d67c0488aec1311e0a3f0463c7f19dd31 100644
--- a/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts
+++ b/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts
@@ -21,7 +21,7 @@ const titreEtapesFilter = (titreEtapes: ITitreEtape[], date: string) => titreEta
  * @returns démarches du titre
  */
 
-export const titreDemarchesEtapesRebuild = (date: CaminoDate, titreDemarches: ITitreDemarche[], titreTypeId: TitreTypeId) => {
+export const titreDemarchesEtapesRebuild = (date: CaminoDate, titreDemarches: ITitreDemarche[], titreTypeId: TitreTypeId): ITitreDemarche[] => {
   const titreDemarchesRebuilt = titreDemarches.reduce((acc: ITitreDemarche[], td) => {
     if (!td.etapes) return acc
 
diff --git a/packages/api/src/business/utils/titre-etapes-sort.ts b/packages/api/src/business/utils/titre-etapes-sort.ts
index 65fce52b8cda72a13a0346c7ca87b40e6eb44c46..062bbce8b1864a7b50e6309b098c97d3a83943fd 100644
--- a/packages/api/src/business/utils/titre-etapes-sort.ts
+++ b/packages/api/src/business/utils/titre-etapes-sort.ts
@@ -1,5 +1,5 @@
 import { ITitreEtape } from '../../types'
-import { demarcheDefinitionFind } from '../rules-demarches/definitions'
+import { machineFind } from '../rules-demarches/definitions'
 import { TitreEtapeForMachine, toMachineEtapes } from '../rules-demarches/machine-common'
 import { TitreTypeId } from 'camino-common/src/static/titresTypes'
 import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes'
@@ -16,10 +16,10 @@ export const titreEtapesSortDescByOrdre = <T extends Pick<ITitreEtape, 'ordre'>>
 export const titreEtapesSortAscByOrdre = <T extends Pick<ITitreEtape, 'ordre'>>(titreEtapes: T[]): T[] => titreEtapes.toSorted((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 TitreEtapeForMachine>(titreEtapes: T[], demarcheId: DemarcheId, demarcheTypeId: DemarcheTypeId, titreTypeId: TitreTypeId): T[] => {
-  const demarcheDefinition = demarcheDefinitionFind(titreTypeId, demarcheTypeId, titreEtapes, demarcheId)
-  if (demarcheDefinition) {
-    const etapes = demarcheDefinition.machine.orderMachine(toMachineEtapes(titreEtapes))
-    if (!demarcheDefinition.machine.isEtapesOk(etapes)) {
+  const machine = machineFind(titreTypeId, demarcheTypeId, titreEtapes, demarcheId)
+  if (machine) {
+    const etapes = machine.orderMachine(toMachineEtapes(titreEtapes))
+    if (!machine.isEtapesOk(etapes)) {
       console.error(`impossible de trouver un ordre pour la démarche '${demarcheId}' où ces étapes sont valides ${JSON.stringify(etapes)}`)
     }
 
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 5de2024c69249bdb175b0f7f62055cb5f45e5f0c..80845836d945270ebcf27cae4ee4577cc193d964 100644
--- a/packages/api/src/business/validations/titre-demarche-etat-validate.ts
+++ b/packages/api/src/business/validations/titre-demarche-etat-validate.ts
@@ -2,7 +2,7 @@
 import { DeepReadonly, NonEmptyArray, isNonEmptyArray, isNotNullNorUndefined, isNullOrUndefinedOrEmpty, onlyUnique } from 'camino-common/src/typescript-tools'
 import type { ITitre, ITitreEtape } from '../../types'
 
-import { DemarcheDefinition, demarcheDefinitionFind } from '../rules-demarches/definitions'
+import { machineFind } from '../rules-demarches/definitions'
 import { Etape, TitreEtapeForMachine, titreEtapeForMachineValidator, toMachineEtapes } from '../rules-demarches/machine-common'
 import { DemarcheId } from 'camino-common/src/demarche'
 import { DemarchesTypes, DemarcheTypeId } from 'camino-common/src/static/demarchesTypes'
@@ -56,7 +56,7 @@ export const titreDemarcheUpdatedEtatValidate = (
   suppression = false
 ): { valid: true; errors: null } | { valid: false; errors: NonEmptyArray<string> } => {
   const titreDemarcheEtapesNew = titreDemarcheEtapesBuild(titreEtape, suppression, titreDemarcheEtapes)
-  const demarcheDefinition = demarcheDefinitionFind(titre.typeId, demarcheTypeId, titreDemarcheEtapesNew, demarcheId)
+  const machine = machineFind(titre.typeId, demarcheTypeId, titreDemarcheEtapesNew, demarcheId)
   const titreDemarchesErrors: string[] = []
 
   // vérifie que la démarche existe dans le titre
@@ -66,10 +66,10 @@ export const titreDemarcheUpdatedEtatValidate = (
   }
   // on récupère tous les type d'étapes et les statuts associés applicable à la date souhaitée
   try {
-    const etapeTypesWithStatusPossibles = getPossiblesEtapesTypes(demarcheDefinition, titre.typeId, demarcheTypeId, titreEtape.typeId, titreEtape.id, titreEtape.date, titreDemarcheEtapes ?? [])
+    const etapeTypesWithStatusPossibles = getPossiblesEtapesTypes(machine, titre.typeId, demarcheTypeId, titreEtape.typeId, titreEtape.id, titreEtape.date, titreDemarcheEtapes ?? [])
 
     if (!etapeTypesWithStatusPossibles.some(({ etapeStatutId, etapeTypeId }) => etapeStatutId === titreEtape.statutId && etapeTypeId === titreEtape.typeId)) {
-      if (isNotNullNorUndefined(demarcheDefinition)) {
+      if (isNotNullNorUndefined(machine)) {
         return { valid: false, errors: ['les étapes de la démarche machine ne sont pas valides'] }
       } else {
         return { valid: false, errors: ['les étapes de la démarche TDE ne sont pas valides'] }
@@ -80,11 +80,11 @@ export const titreDemarcheUpdatedEtatValidate = (
     titreDemarchesErrors.push(e.message)
   }
 
-  if (isNotNullNorUndefined(demarcheDefinition)) {
+  if (isNotNullNorUndefined(machine)) {
     // vérifie que toutes les étapes existent dans l’arbre
     try {
       const etapes = titreDemarcheEtapesNew.map(etape => titreEtapeForMachineValidator.omit({ id: true, ordre: true }).parse(etape))
-      const ok = demarcheDefinition.machine.isEtapesOk(demarcheDefinition.machine.orderMachine(toMachineEtapes(etapes)))
+      const ok = machine.isEtapesOk(machine.orderMachine(toMachineEtapes(etapes)))
       if (!ok) {
         titreDemarchesErrors.push('la démarche machine n’est pas valide')
       }
@@ -102,7 +102,7 @@ export const titreDemarcheUpdatedEtatValidate = (
 }
 
 export const getPossiblesEtapesTypes = (
-  demarcheDefinition: DemarcheDefinition | undefined,
+  machine: CaminoMachines | undefined,
   titreTypeId: TitreTypeId,
   demarcheTypeId: DemarcheTypeId,
   etapeTypeId: EtapeTypeId | undefined,
@@ -111,10 +111,10 @@ export const getPossiblesEtapesTypes = (
   demarcheEtapes: Pick<ITitreEtape, 'typeId' | 'date' | 'isBrouillon' | 'id' | 'ordre' | 'statutId' | 'communes'>[]
 ): EtapeTypeEtapeStatutWithMainStep[] => {
   const etapesTypes: EtapeTypeEtapeStatutWithMainStep[] = []
-  if (isNotNullNorUndefined(demarcheDefinition)) {
+  if (isNotNullNorUndefined(machine)) {
     const etapes = demarcheEtapes.map(etape => titreEtapeForMachineValidator.parse(etape))
 
-    etapesTypes.push(...etapesTypesPossibleACetteDateOuALaPlaceDeLEtape(demarcheDefinition.machine, etapes, etapeId ?? null, date))
+    etapesTypes.push(...etapesTypesPossibleACetteDateOuALaPlaceDeLEtape(machine, etapes, etapeId ?? null, date))
   } else {
     // si on modifie une étape
     // vérifie que son type est possible sur la démarche
diff --git a/packages/api/src/database/models/entreprises-etablissements.ts b/packages/api/src/database/models/entreprises-etablissements.ts
index 438a79b675d95707c39e83da18e94599f3f627d5..7d87c52ef252003cc17fda03965b04462ba03ec2 100644
--- a/packages/api/src/database/models/entreprises-etablissements.ts
+++ b/packages/api/src/database/models/entreprises-etablissements.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 import { Model, Modifiers } from 'objection'
 
 import { IEntrepriseEtablissement } from '../../types'
@@ -5,9 +6,9 @@ import { IEntrepriseEtablissement } from '../../types'
 interface EntreprisesEtablissements extends IEntrepriseEtablissement {}
 
 class EntreprisesEtablissements extends Model {
-  public static tableName = 'entreprisesEtablissements'
+  public static override tableName = 'entreprisesEtablissements'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
     required: ['id', 'entrepriseId', 'dateDebut'],
 
@@ -21,7 +22,7 @@ class EntreprisesEtablissements extends Model {
     },
   }
 
-  public static modifiers: Modifiers = {
+  public static override modifiers: Modifiers = {
     orderDesc: builder => {
       builder.orderBy('dateDebut', 'desc')
     },
diff --git a/packages/api/src/database/models/entreprises.ts b/packages/api/src/database/models/entreprises.ts
index 2d41c46d1dd21dcad9897161055c0fc7122ed42a..993ac74a30f8e5aff0de428dc2e986c6d945f72b 100644
--- a/packages/api/src/database/models/entreprises.ts
+++ b/packages/api/src/database/models/entreprises.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 import { Model, Pojo } from 'objection'
 
 import { IEntreprise } from '../../types'
@@ -8,9 +9,9 @@ import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools'
 interface Entreprises extends IEntreprise {}
 
 class Entreprises extends Model {
-  public static tableName = 'entreprises'
+  public static override tableName = 'entreprises'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
     required: ['id', 'nom'],
 
@@ -34,7 +35,7 @@ class Entreprises extends Model {
     },
   }
 
-  static relationMappings = () => ({
+  static override relationMappings = () => ({
     etablissements: {
       relation: Model.HasManyRelation,
       modelClass: EntreprisesEtablissements,
@@ -58,7 +59,7 @@ class Entreprises extends Model {
     },
   })
 
-  public $parseJson(json: Pojo) {
+  public override $parseJson(json: Pojo) {
     json = super.$parseJson(json)
     // TODO 2024-06-03 à supprimer et vérifier que l'api sirene a bien des Ids en minuscule (lancer le monthly)
     if (isNotNullNorUndefined(json.id)) {
diff --git a/packages/api/src/database/models/journaux.ts b/packages/api/src/database/models/journaux.ts
index 65025434ddc2c0168e7d758c28b52049ab2e8bc4..748276a333043e6709c13aa01024f9b73fd48ff3 100644
--- a/packages/api/src/database/models/journaux.ts
+++ b/packages/api/src/database/models/journaux.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 import { Model } from 'objection'
 
 import { IJournaux } from '../../types'
@@ -8,9 +9,9 @@ import Titres from './titres'
 interface Journaux extends IJournaux {}
 
 class Journaux extends Model {
-  public static tableName = 'journaux'
+  public static override tableName = 'journaux'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
 
     properties: {
@@ -24,7 +25,7 @@ class Journaux extends Model {
     },
   }
 
-  static relationMappings = () => ({
+  static override relationMappings = () => ({
     utilisateur: {
       relation: Model.BelongsToOneRelation,
       modelClass: Utilisateurs,
@@ -43,7 +44,7 @@ class Journaux extends Model {
     },
   })
 
-  async $beforeInsert(queryContext: any) {
+  override async $beforeInsert(queryContext: any) {
     await super.$beforeInsert(queryContext)
 
     this.id = idGenerate()
diff --git a/packages/api/src/database/models/titres--titres.ts b/packages/api/src/database/models/titres--titres.ts
index bd402a51c59899f9692f7b1f12bccc24848b85f8..ac17882690488c0473490591b34b7b5dffbd5808 100644
--- a/packages/api/src/database/models/titres--titres.ts
+++ b/packages/api/src/database/models/titres--titres.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 import { Model } from 'objection'
 import { ITitreTitre } from '../../types'
 
@@ -6,9 +7,9 @@ interface TitreTitre extends ITitreTitre {}
 interface TitresTitres extends TitreTitre {}
 
 class TitresTitres extends Model {
-  public static tableName = 'titres__titres'
+  public static override tableName = 'titres__titres'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
     required: ['titreFromId', 'titreToId'],
     properties: {
@@ -17,7 +18,7 @@ class TitresTitres extends Model {
     },
   }
 
-  public static idColumn = ['titreFromId', 'titreToId']
+  public static override idColumn = ['titreFromId', 'titreToId']
 }
 
 export default TitresTitres
diff --git a/packages/api/src/database/models/titres-activites.ts b/packages/api/src/database/models/titres-activites.ts
index 996222ff72bc4b97b6398e39d67eb96f6c8baef2..ca0a33e0c1924ca0d499d45e575533e40173562a 100644
--- a/packages/api/src/database/models/titres-activites.ts
+++ b/packages/api/src/database/models/titres-activites.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 import { Model, Modifiers, Pojo, QueryContext } from 'objection'
 
 import { ITitreActivite } from '../../types'
@@ -9,9 +10,9 @@ import { isNotNullNorUndefined, isNullOrUndefined } from 'camino-common/src/type
 interface TitresActivites extends ITitreActivite {}
 
 class TitresActivites extends Model {
-  public static tableName = 'titresActivites'
+  public static override tableName = 'titresActivites'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
 
     required: ['titreId', 'date', 'typeId', 'activiteStatutId', 'periodeId', 'annee'],
@@ -32,7 +33,7 @@ class TitresActivites extends Model {
     },
   }
 
-  static relationMappings = () => ({
+  static override relationMappings = () => ({
     titre: {
       relation: Model.BelongsToOneRelation,
       modelClass: Titres,
@@ -52,13 +53,13 @@ class TitresActivites extends Model {
     },
   })
 
-  public static modifiers: Modifiers = {
+  public static override modifiers: Modifiers = {
     orderDesc: builder => {
       builder.orderByRaw('date desc')
     },
   }
 
-  async $beforeInsert(context: QueryContext) {
+  override async $beforeInsert(context: QueryContext) {
     if (isNullOrUndefined(this.id)) {
       this.id = idGenerate()
     }
@@ -69,14 +70,14 @@ class TitresActivites extends Model {
     return super.$beforeInsert(context)
   }
 
-  public $parseJson(json: Pojo) {
+  public override $parseJson(json: Pojo) {
     delete json.modification
     json = super.$parseJson(json)
 
     return json
   }
 
-  public $formatDatabaseJson(json: Pojo) {
+  public override $formatDatabaseJson(json: Pojo) {
     delete json.modification
     json = super.$formatDatabaseJson(json)
 
diff --git a/packages/api/src/database/models/titres-demarches.ts b/packages/api/src/database/models/titres-demarches.ts
index 098648752028dff4de0b9559fc40de2d726c6268..7513cc7ef97aca0fce01098df69f3fa5bde31311 100644
--- a/packages/api/src/database/models/titres-demarches.ts
+++ b/packages/api/src/database/models/titres-demarches.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 import { Model, Modifiers, QueryContext } from 'objection'
 
 import { ITitreDemarche } from '../../types'
@@ -13,9 +14,9 @@ export interface DBTitresDemarches extends ITitreDemarche {
 interface TitresDemarches extends DBTitresDemarches {}
 
 class TitresDemarches extends Model {
-  public static tableName = 'titresDemarches'
+  public static override tableName = 'titresDemarches'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
     required: ['titreId', 'typeId'],
 
@@ -33,7 +34,7 @@ class TitresDemarches extends Model {
     },
   }
 
-  static relationMappings = () => ({
+  static override relationMappings = () => ({
     titre: {
       relation: Model.BelongsToOneRelation,
       modelClass: Titres,
@@ -53,13 +54,13 @@ class TitresDemarches extends Model {
     },
   })
 
-  public static modifiers: Modifiers = {
+  public static override modifiers: Modifiers = {
     orderDesc: builder => {
       builder.orderBy('ordre', 'desc')
     },
   }
 
-  async $beforeInsert(context: QueryContext) {
+  override async $beforeInsert(context: QueryContext) {
     if (isNullOrUndefined(this.id)) {
       this.id = newDemarcheId()
     }
diff --git a/packages/api/src/database/models/titres-etapes.ts b/packages/api/src/database/models/titres-etapes.ts
index 767ad481b69e013879d404560ad6a2a51d582965..66ace38975790daedd6626db99661ae75ef4a5ad 100644
--- a/packages/api/src/database/models/titres-etapes.ts
+++ b/packages/api/src/database/models/titres-etapes.ts
@@ -1,4 +1,5 @@
 /* eslint-disable @typescript-eslint/strict-boolean-expressions */
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 
 import { Model, ModelOptions, Pojo, QueryContext } from 'objection'
 
@@ -16,9 +17,9 @@ export interface DBTitresEtapes extends ITitreEtape {
 }
 interface TitresEtapes extends DBTitresEtapes {}
 class TitresEtapes extends Model {
-  public static tableName = 'titresEtapes'
+  public static override tableName = 'titresEtapes'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
     // l’id est généré tout seul
     required: ['titreDemarcheId', 'date'],
@@ -53,7 +54,7 @@ class TitresEtapes extends Model {
     },
   }
 
-  static relationMappings = () => ({
+  static override relationMappings = () => ({
     demarche: {
       relation: Model.BelongsToOneRelation,
       modelClass: TitresDemarches,
@@ -73,7 +74,7 @@ class TitresEtapes extends Model {
     },
   })
 
-  async $beforeInsert(context: QueryContext) {
+  override async $beforeInsert(context: QueryContext) {
     if (!this.id) {
       this.id = idGenerate()
     }
@@ -90,7 +91,7 @@ class TitresEtapes extends Model {
     await super.$beforeInsert(context)
   }
 
-  async $beforeUpdate(opt: ModelOptions, context: QueryContext) {
+  override async $beforeUpdate(opt: ModelOptions, context: QueryContext) {
     if (isNotNullNorUndefined(this.geojson4326Perimetre)) {
       // eslint-disable-next-line sql/no-unsafe-query
       const rawLine = await context.transaction.raw(`select ST_GeomFromGeoJSON('${JSON.stringify(this.geojson4326Perimetre.geometry)}'::text)`)
@@ -100,7 +101,7 @@ class TitresEtapes extends Model {
     return super.$beforeUpdate(opt, context)
   }
 
-  async $afterFind(context: QueryContext) {
+  override async $afterFind(context: QueryContext) {
     if (context.fetchHeritage && this.heritageProps) {
       this.heritageProps = await heritagePropsFormat(this.heritageProps)
     }
@@ -121,7 +122,7 @@ class TitresEtapes extends Model {
     return this
   }
 
-  public $formatDatabaseJson(json: Pojo) {
+  public override $formatDatabaseJson(json: Pojo) {
     delete json.entrepriseDocumentIds
     delete json.etapeDocuments
     delete json.etapeAvis
@@ -134,7 +135,7 @@ class TitresEtapes extends Model {
     return json
   }
 
-  public $parseJson(json: Pojo) {
+  public override $parseJson(json: Pojo) {
     delete json.modification
     delete json.suppression
     json = super.$parseJson(json)
diff --git a/packages/api/src/database/models/titres.ts b/packages/api/src/database/models/titres.ts
index 4105ff14e58e6a2209a4f396f3a2cc6233c5c34e..05d8aaff8a678aeacba0d7303ad99fb321af8044 100644
--- a/packages/api/src/database/models/titres.ts
+++ b/packages/api/src/database/models/titres.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 import { Model, Pojo, QueryContext, ref } from 'objection'
 
 import { ITitre } from '../../types'
@@ -14,9 +15,9 @@ export interface DBTitre extends ITitre {
 interface Titres extends DBTitre {}
 
 class Titres extends Model {
-  public static tableName = 'titres'
+  public static override tableName = 'titres'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
     required: ['nom', 'typeId'],
     properties: {
@@ -32,7 +33,7 @@ class Titres extends Model {
     },
   }
 
-  static relationMappings = () => ({
+  static override relationMappings = () => ({
     demarches: {
       relation: Model.HasManyRelation,
       modelClass: TitresDemarches,
@@ -82,7 +83,7 @@ class Titres extends Model {
     },
   })
 
-  async $beforeInsert(context: QueryContext) {
+  override async $beforeInsert(context: QueryContext) {
     if (isNullOrUndefined(this.id)) {
       this.id = idGenerate()
     }
@@ -94,7 +95,7 @@ class Titres extends Model {
     return super.$beforeInsert(context)
   }
 
-  $afterFind() {
+  override $afterFind() {
     if (this.substancesEtape === null) {
       this.substances = []
     } else if (this.substancesEtape === undefined) {
@@ -141,14 +142,14 @@ class Titres extends Model {
     }
   }
 
-  public $parseJson(json: Pojo) {
+  public override $parseJson(json: Pojo) {
     json = titreInsertFormat(json)
     json = super.$parseJson(json)
 
     return json
   }
 
-  public $formatDatabaseJson(json: Pojo) {
+  public override $formatDatabaseJson(json: Pojo) {
     json = titreInsertFormat(json)
     json = super.$formatDatabaseJson(json)
 
diff --git a/packages/api/src/database/models/utilisateurs--titres.ts b/packages/api/src/database/models/utilisateurs--titres.ts
index 009451366eae194c68d965469c08559facc00604..08df0387cf7ed7c480bfa12f9d0a5a3a6052fc5e 100644
--- a/packages/api/src/database/models/utilisateurs--titres.ts
+++ b/packages/api/src/database/models/utilisateurs--titres.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 import { Model } from 'objection'
 import { IUtilisateurTitre } from '../../types'
 import Utilisateurs from './utilisateurs'
@@ -5,9 +6,9 @@ import Utilisateurs from './utilisateurs'
 interface UtilisateursTitres extends IUtilisateurTitre {}
 
 class UtilisateursTitres extends Model {
-  public static tableName = 'utilisateurs__titres'
+  public static override tableName = 'utilisateurs__titres'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
     required: ['utilisateurId', 'titreId'],
 
@@ -17,9 +18,9 @@ class UtilisateursTitres extends Model {
     },
   }
 
-  public static idColumn = ['utilisateurId', 'titreId']
+  public static override idColumn = ['utilisateurId', 'titreId']
 
-  static relationMappings = () => ({
+  static override relationMappings = () => ({
     utilisateur: {
       relation: Model.BelongsToOneRelation,
       modelClass: Utilisateurs,
diff --git a/packages/api/src/database/models/utilisateurs.ts b/packages/api/src/database/models/utilisateurs.ts
index 258f564de7223a9765b40a937b4edfe49629dab8..a3d4d89cbb638c366e2eb3e7f1a5f677e49fd21c 100644
--- a/packages/api/src/database/models/utilisateurs.ts
+++ b/packages/api/src/database/models/utilisateurs.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
 import { Model, Pojo } from 'objection'
 
 import Entreprises from './entreprises'
@@ -23,9 +24,9 @@ interface IUtilisateur {
 interface Utilisateurs extends IUtilisateur {}
 
 class Utilisateurs extends Model {
-  public static tableName = 'utilisateurs'
+  public static override tableName = 'utilisateurs'
 
-  public static jsonSchema = {
+  public static override jsonSchema = {
     type: 'object',
     required: ['id', 'email', 'role'],
 
@@ -42,7 +43,7 @@ class Utilisateurs extends Model {
     },
   }
 
-  static relationMappings = () => ({
+  static override relationMappings = () => ({
     entreprises: {
       relation: Model.ManyToManyRelation,
       modelClass: Entreprises,
@@ -57,13 +58,13 @@ class Utilisateurs extends Model {
     },
   })
 
-  public $parseJson(json: Pojo) {
+  public override $parseJson(json: Pojo) {
     json = super.$parseJson(json)
 
     return json
   }
 
-  public $formatDatabaseJson(json: Pojo) {
+  public override $formatDatabaseJson(json: Pojo) {
     json = super.$formatDatabaseJson(json)
 
     return json
diff --git a/packages/api/src/tools/demarches/tde-check.ts b/packages/api/src/tools/demarches/tde-check.ts
index 7dc87fe59df487b5c0eb6694bbd054903d6db34c..d0139465c5ebc6604ea67cedb3cbbc3e4836563c 100644
--- a/packages/api/src/tools/demarches/tde-check.ts
+++ b/packages/api/src/tools/demarches/tde-check.ts
@@ -1,10 +1,11 @@
 import { EtapesTypes } from 'camino-common/src/static/etapesTypes'
 import { isTDEExist } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index'
-import { demarcheDefinitionFind } from '../../business/rules-demarches/definitions'
+import { machineFind } from '../../business/rules-demarches/definitions'
 import { titresDemarchesGet } from '../../database/queries/titres-demarches'
 import { userSuper } from '../../database/user-super'
+import { isNullOrUndefined } from 'camino-common/src/typescript-tools'
 
-export const titreTypeDemarcheTypeEtapeTypeCheck = async () => {
+export const titreTypeDemarcheTypeEtapeTypeCheck = async (): Promise<void> => {
   console.info()
   console.info('- - -')
   console.info('vérification de TDE avec les démarches en bdd')
@@ -24,9 +25,9 @@ export const titreTypeDemarcheTypeEtapeTypeCheck = async () => {
   let errorsNb = 0
 
   demarches.forEach(d => {
-    const demarcheDefinition = demarcheDefinitionFind(d.titre!.typeId, d.typeId, d.etapes, d.id)
+    const machine = machineFind(d.titre!.typeId, d.typeId, d.etapes, d.id)
 
-    if (!demarcheDefinition) {
+    if (isNullOrUndefined(machine)) {
       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 18ed1061c1d98d34a5d3a9355e812f198715b855..384a81619834e388ce32c71e1c90c8a3cef310fc 100644
--- a/packages/api/src/tools/demarches/tests-creation.ts
+++ b/packages/api/src/tools/demarches/tests-creation.ts
@@ -4,7 +4,7 @@ import { titresDemarchesGet } from '../../database/queries/titres-demarches'
 import { userSuper } from '../../database/user-super'
 import { mkdirSync, writeFileSync } from 'fs'
 import { Etape, titreEtapeForMachineValidator, toMachineEtapes } from '../../business/rules-demarches/machine-common'
-import { demarcheDefinitionFind, demarchesDefinitions } from '../../business/rules-demarches/definitions'
+import { machineFind, demarchesDefinitions } from '../../business/rules-demarches/definitions'
 import { dateAddDays, daysBetween, setDayInMonth } from 'camino-common/src/date'
 import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes'
 import { toCommuneId } from 'camino-common/src/static/communes'
@@ -30,7 +30,7 @@ const writeEtapesForTest = async () => {
 
     const toutesLesEtapes = demarches
       .filter(demarche => demarche.etapes?.length)
-      .filter(demarche => isNotNullNorUndefined(demarcheDefinitionFind(demarche.titre!.typeId, demarche.typeId, demarche.etapes!, demarche.id)))
+      .filter(demarche => isNotNullNorUndefined(machineFind(demarche.titre!.typeId, demarche.typeId, demarche.etapes!, demarche.id)))
       .map((demarche, index) => {
         const etapes: Etape[] = toMachineEtapes(
           (
@@ -59,9 +59,10 @@ const writeEtapesForTest = async () => {
         const firstSaisineDate = etapes.find(etape => etape.etapeTypeId === ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives)?.date ?? etapes[0].date
         const decalageJour = daysBetween(firstSaisineDate, setDayInMonth(firstSaisineDate, Math.floor(Math.random() * 28)))
         try {
-          if (!demarcheDefinition.machine.isEtapesOk(etapes)) {
-            etapes.splice(0, etapes.length, ...demarcheDefinition.machine.orderMachine(etapes))
-            if (!demarcheDefinition.machine.isEtapesOk(etapes)) {
+          const machine = demarcheDefinition.machine(demarche.titre!.typeId, demarche.typeId)
+          if (!machine.isEtapesOk(etapes)) {
+            etapes.splice(0, etapes.length, ...machine.orderMachine(etapes))
+            if (!machine.isEtapesOk(etapes)) {
               console.warn(`https://camino.beta.gouv.fr/titres/${demarche.titreId} => démarche N*${index} (${demarche.id}) "${demarcheDefinition.titreTypeIds.join(' ou ')}/${demarche.typeId}"`)
             }
           }
diff --git a/packages/api/tsconfig.json b/packages/api/tsconfig.json
index 6f61185a536170e8b845957baf8ed151360f0091..7d16adcf304f1be1a15620b970655cc73a7faab0 100644
--- a/packages/api/tsconfig.json
+++ b/packages/api/tsconfig.json
@@ -16,6 +16,7 @@
     "noImplicitAny": true,
     "noImplicitReturns": true,
     "noImplicitThis": true,
+    "noImplicitOverride": true,
     "outDir": "dist",
     "strict": true,
     "strictNullChecks": true,
diff --git a/packages/common/.eslintignore b/packages/common/.eslintignore
new file mode 100644
index 0000000000000000000000000000000000000000..060e9ebe82a792b942e71082edac8a84eda6c7c2
--- /dev/null
+++ b/packages/common/.eslintignore
@@ -0,0 +1 @@
+vitest.config.ts
diff --git a/packages/common/src/static/__snapshots__/demarchesTypes.test.ts.snap b/packages/common/src/static/__snapshots__/demarchesTypes.test.ts.snap
index dcd7c8a000c334b850dee7e41ba4525094d410e0..2ce7ae6cf08aaa521c6eb6b662fa52ace030a84c 100644
--- a/packages/common/src/static/__snapshots__/demarchesTypes.test.ts.snap
+++ b/packages/common/src/static/__snapshots__/demarchesTypes.test.ts.snap
@@ -303,3 +303,31 @@ exports[`canImpactTitre 1`] = `
   "vut - ter -> true",
 ]
 `;
+
+exports[`isDemarcheTypeProlongations 1`] = `
+[
+  "amo -> false",
+  "aom -> false",
+  "ces -> false",
+  "con -> false",
+  "dam -> false",
+  "dec -> false",
+  "dep -> false",
+  "dot -> false",
+  "exp -> false",
+  "exs -> false",
+  "fus -> false",
+  "mut -> false",
+  "oct -> false",
+  "pr1 -> true",
+  "pr2 -> true",
+  "pre -> true",
+  "pro -> true",
+  "prr -> false",
+  "ren -> false",
+  "res -> false",
+  "ret -> false",
+  "vct -> false",
+  "vut -> false",
+]
+`;
diff --git a/packages/common/src/static/demarchesTypes.test.ts b/packages/common/src/static/demarchesTypes.test.ts
index 6bc0c5447335a95f07c8601d3ea34302e94af42f..c0060e496015a10e3af3a2c67be0de2050703229 100644
--- a/packages/common/src/static/demarchesTypes.test.ts
+++ b/packages/common/src/static/demarchesTypes.test.ts
@@ -1,6 +1,6 @@
 import { getValues } from '../typescript-tools'
 import { sortedDemarchesStatuts } from './demarchesStatuts'
-import { DEMARCHES_TYPES_IDS, isDemarcheTypeId, isDemarcheTypeOctroi, isDemarcheTypeWithPhase, canImpactTitre } from './demarchesTypes'
+import { DEMARCHES_TYPES_IDS, isDemarcheTypeId, isDemarcheTypeOctroi, isDemarcheTypeWithPhase, canImpactTitre, isDemarcheTypeProlongations } from './demarchesTypes'
 import { test, expect } from 'vitest'
 
 test('isDemarcheTypeId', () => {
@@ -39,3 +39,10 @@ test('canImpactTitre', () => {
   })
   expect(result).toMatchSnapshot()
 })
+
+test('isDemarcheTypeProlongations', () => {
+  const result = getValues(DEMARCHES_TYPES_IDS).flatMap(demarcheType => {
+    return `${demarcheType} -> ${isDemarcheTypeProlongations(demarcheType)}`
+  })
+  expect(result).toMatchSnapshot()
+})
diff --git a/packages/common/src/static/demarchesTypes.ts b/packages/common/src/static/demarchesTypes.ts
index e745c6d38cde5b92128307ff119d23bdf88228f4..b566d78bb9fa5d6609a50007ca9c619238d05881 100644
--- a/packages/common/src/static/demarchesTypes.ts
+++ b/packages/common/src/static/demarchesTypes.ts
@@ -284,18 +284,12 @@ export const isDemarcheTypeOctroi = (demarcheTypeId: DemarcheTypeId): boolean =>
   return demarchesTypesOctroi.includes(demarcheTypeId)
 }
 
-const demarchesTypesWithPhasesAndWithoutDateFin: DemarcheTypeId[] = [
-  DEMARCHES_TYPES_IDS.Prolongation,
-  DEMARCHES_TYPES_IDS.Prolongation1,
-  DEMARCHES_TYPES_IDS.Prolongation2,
-  DEMARCHES_TYPES_IDS.ProlongationExceptionnelle,
-]
 export const isDemarcheTypeWithPhase = (demarcheTypeId: DemarcheTypeId): boolean => {
   if (isDemarcheTypeOctroi(demarcheTypeId)) {
     return true
   }
 
-  return demarchesTypesWithPhasesAndWithoutDateFin.includes(demarcheTypeId)
+  return isDemarcheTypeProlongations(demarcheTypeId)
 }
 
 export const sortedDemarchesTypes = Object.values(DemarchesTypes).sort((a, b) => a.nom.localeCompare(b.nom))
@@ -304,6 +298,10 @@ export const isTravaux = (demarcheTypeId: DemarcheTypeId): boolean => {
   return DemarchesTypes[demarcheTypeId].travaux
 }
 
+export const isDemarcheTypeProlongations = (demarcheType: DemarcheTypeId): boolean => {
+  return [DEMARCHES_TYPES_IDS.Prolongation, DEMARCHES_TYPES_IDS.Prolongation1, DEMARCHES_TYPES_IDS.Prolongation2, DEMARCHES_TYPES_IDS.ProlongationExceptionnelle].includes(demarcheType)
+}
+
 /**
  *  La démarche a un impact potentiel sur le titre (statut, visibilité administrations…)
  */
diff --git a/packages/common/src/static/etapesTypes.ts b/packages/common/src/static/etapesTypes.ts
index f8ba7066b65f7e6409998384c3a8608f7ea755ca..9de0fd2f3c1c4fa0cb972f32ac5181838568cf95 100644
--- a/packages/common/src/static/etapesTypes.ts
+++ b/packages/common/src/static/etapesTypes.ts
@@ -4,13 +4,13 @@ import { Definition } from '../definition'
 import { EtapeBrouillon } from '../etape'
 
 // prettier-ignore
-const IDS = ['abd', 'aca','aco','and','anf','def','dex','dim', 'dpu',  'dux','ihi', 'mfr','mod','mom','rca','rcb','rcd','rcm','rco','rcs','rie','rif','rim','rpu','sco','acg','apd','ape','apo','app','apu','asl','cac','cim','cod','css','dae','dec','des','ede','edm','epc','epu','esb','mca','mcb','mcd','mcm','mco','mcp','mcr','mcs','mdp','mec','men','meo','mie','mif','mim','mna','mnb','mnc','mnd','mni','mno','mns','mnv','ncl','npp','pfc','pfd','ppu','pqr','rcg','rde','rpe','sas','sca','scg','scl','spe','spo','spp','vfc','vfd','wab','wae','wao','war','wau','wce','wco','wda','wdc','wdd','wde','wdm','wfa','wfd','wfo','wfr','wmm','wmr','wmt','woe','wpa','wpb','wpc','wpo','wpp','wps','wrc','wrd','wre','wrt','wse','wtp', 'asc', 'adc'] as const
+const IDS = ['abd', 'aca','aco','and','anf','def','dex','dim', 'dpu',  'dux','ihi', 'mfr','mod','mom','rca','rcb','rcd','rcm','rco','rcs','rie','rif','rim','rpu','sco','acg','apd','ape','apo','app','apu','asl','cac','cim','cod','css','dae','dec','des','ede','edm','epc','epu','esb','mca','mcb','mcd', 'mci','mcm','mco','mcp','mcr','mcs','mdp','mec','men','meo','mie','mif','mim','mna','mnb','mnc','mnd','mni','mno','mns','mnv','ncl','npp','pfc','pfd','ppu','pqr','rcg','rde','rpe','sas','sca','scg','scl','spe','spo','spp','vfc','vfd','wab','wae','wao','war','wau','wce','wco','wda','wdc','wdd','wde','wdm','wfa','wfd','wfo','wfr','wmm','wmr','wmt','woe','wpa','wpb','wpc','wpo','wpp','wps','wrc','wrd','wre','wrt','wse','wtp', 'asc', 'adc'] as const
 
 // prettier-ignore
 const FONDAMENTALES_IDS = ['abd', 'aca','aco','and','anf','def','dex','dim', 'dpu','dux','ihi', 'mfr','mod','mom','rca','rcb','rcd','rcm','rco','rcs','rie','rif','rim','rpu','sco'] as const satisfies Readonly<EtapeTypeIdFondamentaleArray>
 
 // prettier-ignore
-const NON_FONDAMENTALES_IDS = ['acg','apd','ape','apo','app','apu','asl','cac','cim','cod','css','dae','dec','des','ede','edm','epc','epu','esb','mca','mcb','mcd','mcm','mco','mcp','mcr','mcs','mdp','mec','men','meo','mie','mif','mim','mna','mnb','mnc','mnd','mni','mno','mns','mnv','ncl','npp','pfc','pfd','ppu','pqr','rcg','rde','rpe','sas','sca','scg','scl','spe','spo','spp','vfc','vfd','wab','wae','wao','war','wau','wce','wco','wda','wdc','wdd','wde','wdm','wfa','wfd','wfo','wfr','wmm','wmr','wmt','woe','wpa','wpb','wpc','wpo','wpp','wps','wrc','wrd','wre','wrt','wse','wtp', 'asc', 'adc'] as const satisfies Readonly<EtapeTypeIdNonFondamentale[]>
+const NON_FONDAMENTALES_IDS = ['acg','apd','ape','apo','app','apu','asl','cac','cim','cod','css','dae','dec','des','ede','edm','epc','epu','esb','mca','mcb','mcd','mci', 'mcm','mco','mcp','mcr', 'mcs','mdp','mec','men','meo','mie','mif','mim','mna','mnb','mnc','mnd','mni','mno','mns','mnv','ncl','npp','pfc','pfd','ppu','pqr','rcg','rde','rpe','sas','sca','scg','scl','spe','spo','spp','vfc','vfd','wab','wae','wao','war','wau','wce','wco','wda','wdc','wdd','wde','wdm','wfa','wfd','wfo','wfr','wmm','wmr','wmt','woe','wpa','wpb','wpc','wpo','wpp','wps','wrc','wrd','wre','wrt','wse','wtp', 'asc', 'adc'] as const satisfies Readonly<EtapeTypeIdNonFondamentale[]>
 
 // Ceci est un test :)
 ;[...FONDAMENTALES_IDS, ...NON_FONDAMENTALES_IDS] as const satisfies typeof IDS
@@ -135,6 +135,7 @@ export const ETAPES_TYPES = {
   transmissionDuProjetDePrescriptionsAuDemandeur: 'wtp',
   avisDesServicesEtCommissionsConsultatives: 'asc',
   avisDesCollectivites: 'adc',
+  declarationDIrrecevabilite: 'mci',
 } as const satisfies Record<string, EtapeTypeId>
 
 export const etapeTypeIdValidator = z.enum(IDS)
@@ -1358,6 +1359,16 @@ export const EtapesTypes = {
     public_lecture: true,
     entreprises_lecture: true,
   },
+  mci: {
+    id: 'mci',
+    nom: "Déclaration d'irrecevabilité",
+    description: '',
+    fondamentale: false,
+    unique: false,
+    date_fin: null,
+    public_lecture: true,
+    entreprises_lecture: true,
+  },
 } as const satisfies { [key in EtapeTypeId]: EtapeType<key> }
 
 type IsFondamentale<T> = T extends EtapeTypeId ? ((typeof EtapesTypes)[T] extends { fondamentale: true } ? T : never) : never
diff --git a/packages/common/src/static/etapesTypesEtapesStatuts.ts b/packages/common/src/static/etapesTypesEtapesStatuts.ts
index 1e9fd3a33f1f4eea2cc14ec5e26b68f3c61e9035..1d582252f8e53f40ed3963a0adb377947a177707 100644
--- a/packages/common/src/static/etapesTypesEtapesStatuts.ts
+++ b/packages/common/src/static/etapesTypesEtapesStatuts.ts
@@ -136,6 +136,9 @@ export const EtapesTypesEtapesStatuts = {
     FAVORABLE: { etapeTypeId: 'mcr', etapeStatutId: 'fav' },
     DEFAVORABLE: { etapeTypeId: 'mcr', etapeStatutId: 'def' },
   },
+  declarationDIrrecevabilite: {
+    FAIT: { etapeTypeId: 'mci', etapeStatutId: 'fai' },
+  },
   demandeDeComplements_SaisineDeLaCARM_: { FAIT: { etapeTypeId: 'mcs', etapeStatutId: 'fai' } },
   depotDeLaDemande: { FAIT: { etapeTypeId: 'mdp', etapeStatutId: 'fai' } },
   avisDeDemandeConcurrente: { FAIT: { etapeTypeId: 'mec', etapeStatutId: 'fai' } },
diff --git a/packages/common/vitest.config.ts b/packages/common/vitest.config.ts
index cb8723adec27035b9b26f8cd40a727489f0839c4..7c44a32d7986c73fbef0caafb40647756924dae2 100644
--- a/packages/common/vitest.config.ts
+++ b/packages/common/vitest.config.ts
@@ -10,10 +10,10 @@ export default defineConfig({
       thresholds: {
         // the endgame is to put thresholds at 100 and never touch it again :)
         autoUpdate: true,
-        branches: 89.96,
-        functions: 79.52,
-        lines: 96.14,
-        statements: 96.14,
+        branches: 90.09,
+        functions: 79.92,
+        lines: 96.4,
+        statements: 96.4,
         perFile: false,
       },
     },