Mortgage Application Creation

Summary

An authenticated Acheteur or Pro (agent) initiates a new mortgage application by calling POST /mortgage/applications. Both paths create a MortgageApplication record in draft status. When a Pro creates the application on behalf of a buyer, the system also creates a placeholder Acheteur record with a synthetic email — real buyer information is filled in during wizard step 1. An optional propertyId links the application to a specific listing.

State Diagram

stateDiagram-v2
    state "Authentification" as Authenticating
    state "Parcours acheteur" as AcheteurFlow
    state "Parcours pro" as ProFlow
    state "Dossier brouillon créé" as DraftCreated
    state "Acheteur provisoire créé" as PlaceholderCreated
    [*] --> Authenticating
    Authenticating --> AcheteurFlow: callerRole == acheteur
    Authenticating --> ProFlow: callerRole == pro
    AcheteurFlow --> DraftCreated: use acheteurId from JWT
    ProFlow --> PlaceholderCreated: create placeholder Acheteur
    PlaceholderCreated --> DraftCreated: create MortgageApplication with proId
    DraftCreated --> [*]: 201 returned with application

Steps

1. Authentication (Actor: system)

The dualAuth preHandler is applied to all /mortgage/* routes. It tries Acheteur JWT first (ACHETEUR_JWT_SECRET), then Pro JWT (PRO_JWT_SECRET). Both are 15-minute HS256 access tokens. If both fail, a 401 is returned. On success, request.callerRole is set to either "acheteur" or "pro".

Triggers: Any request to /mortgage/applications Outcome: request.callerRole, request.acheteurId or request.proId are populated

2. Resolve Acheteur Identity (Actor: system)

  • If callerRole === "acheteur": acheteurId is taken directly from the JWT.
  • If callerRole === "pro": a placeholder Acheteur record is created with email: pending-{timestamp}@placeholder.sealion and empty name fields. proId is extracted from the JWT.

Triggers: Successful authentication Outcome: A valid acheteurId exists in the database

3. Create Draft Application (Actor: system)

prisma.mortgageApplication.create() is called with:

  • acheteurId (real or placeholder)
  • proId (Pro flow only, otherwise null)
  • propertyId (from request body, optional)
  • status: "draft"

Triggers: Resolved identity Outcome: MortgageApplication row in DB, HTTP 201 response

Error States

  • Missing or invalid JWT → 401, both auth strategies failed
  • propertyId provided but no validation performed at creation time (FK checked at DB level)