# Hosting Module - User Journeys

## Personas

| # | Persona | Role / Auth | Description |
|---|---------|-------------|-------------|
| 1 | **Platform Admin** | `admin` role | Manages the POC → live website pipeline, tracks client services, monitors renewals |
| 2 | **Prospect** | No auth (receives proposal link) | Views their POC website preview via a shared link |

!!! note "Admin-only module"
    The hosting module is primarily an admin-only module. The only non-admin page is the
    **POC Viewer** — a public preview page that shows the prospect's POC website with a
    HostWizard banner. Prospects do not have accounts until their proposal is accepted, at
    which point a Merchant account is created for them.

---

## Lifecycle Overview

The hosting module manages the complete POC → live website pipeline:

```mermaid
flowchart TD
    A[Prospect identified] --> B[Create Hosted Site]
    B --> C[Status: DRAFT]
    C --> D[Build POC website via CMS]
    D --> E[Mark POC Ready]
    E --> F[Status: POC_READY]
    F --> G[Send Proposal to prospect]
    G --> H[Status: PROPOSAL_SENT]
    H --> I{Prospect accepts?}
    I -->|Yes| J[Accept Proposal]
    J --> K[Status: ACCEPTED]
    K --> L[Merchant account created]
    L --> M[Go Live with domain]
    M --> N[Status: LIVE]
    I -->|No| O[Cancel]
    O --> P[Status: CANCELLED]
    N --> Q{Issues?}
    Q -->|Payment issues| R[Suspend]
    R --> S[Status: SUSPENDED]
    S --> T[Reactivate → LIVE]
    Q -->|Client leaves| O
```

### Status Transitions

| From | Allowed Targets |
|------|----------------|
| `draft` | `poc_ready`, `cancelled` |
| `poc_ready` | `proposal_sent`, `cancelled` |
| `proposal_sent` | `accepted`, `cancelled` |
| `accepted` | `live`, `cancelled` |
| `live` | `suspended`, `cancelled` |
| `suspended` | `live`, `cancelled` |
| `cancelled` | _(terminal)_ |

---

## Dev URLs (localhost:9999)

The dev server uses path-based platform routing: `http://localhost:9999/platforms/hosting/...`

### 1. Admin Pages

Login as: `admin@orion.lu` or `samir.boulahtit@gmail.com`

| Page | Dev URL |
|------|---------|
| Dashboard | `http://localhost:9999/platforms/hosting/admin/hosting` |
| Sites List | `http://localhost:9999/platforms/hosting/admin/hosting/sites` |
| New Site | `http://localhost:9999/platforms/hosting/admin/hosting/sites/new` |
| Site Detail | `http://localhost:9999/platforms/hosting/admin/hosting/sites/{site_id}` |
| Client Services | `http://localhost:9999/platforms/hosting/admin/hosting/clients` |

### 2. Public Pages

| Page | Dev URL |
|------|---------|
| POC Viewer | `http://localhost:9999/platforms/hosting/hosting/sites/{site_id}/preview` |

### 3. Admin API Endpoints

**Sites** (prefix: `/platforms/hosting/api/admin/hosting/`):

| Method | Endpoint | Dev URL |
|--------|----------|---------|
| GET | list sites | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites` |
| GET | site detail | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}` |
| POST | create site | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites` |
| POST | create from prospect | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/from-prospect/{prospect_id}` |
| PUT | update site | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}` |
| DELETE | delete site | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}` |

**Lifecycle** (prefix: `/platforms/hosting/api/admin/hosting/`):

| Method | Endpoint | Dev URL |
|--------|----------|---------|
| POST | mark POC ready | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/mark-poc-ready` |
| POST | send proposal | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/send-proposal` |
| POST | accept proposal | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/accept` |
| POST | go live | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/go-live` |
| POST | suspend | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/suspend` |
| POST | cancel | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/cancel` |

**Client Services** (prefix: `/platforms/hosting/api/admin/hosting/`):

| Method | Endpoint | Dev URL |
|--------|----------|---------|
| GET | list services | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services` |
| POST | create service | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services` |
| PUT | update service | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services/{id}` |
| DELETE | delete service | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services/{id}` |

**Stats** (prefix: `/platforms/hosting/api/admin/hosting/`):

| Method | Endpoint | Dev URL |
|--------|----------|---------|
| GET | dashboard stats | `http://localhost:9999/platforms/hosting/api/admin/hosting/stats/dashboard` |

---

## Production URLs (hostwizard.lu)

In production, the platform uses **domain-based routing**.

### Admin Pages & API

| Page / Endpoint | Production URL |
|-----------------|----------------|
| Dashboard | `https://hostwizard.lu/admin/hosting` |
| Sites | `https://hostwizard.lu/admin/hosting/sites` |
| New Site | `https://hostwizard.lu/admin/hosting/sites/new` |
| Site Detail | `https://hostwizard.lu/admin/hosting/sites/{id}` |
| Client Services | `https://hostwizard.lu/admin/hosting/clients` |
| API - Sites | `GET https://hostwizard.lu/api/admin/hosting/sites` |
| API - Stats | `GET https://hostwizard.lu/api/admin/hosting/stats/dashboard` |

### Public Pages

| Page | Production URL |
|------|----------------|
| POC Viewer | `https://hostwizard.lu/hosting/sites/{site_id}/preview` |

---

## Data Model

### Hosted Site

```
HostedSite
├── id (PK)
├── store_id (FK → stores.id, unique)        # The CMS-powered website
├── prospect_id (FK → prospects.id, nullable) # Origin prospect
├── status: draft | poc_ready | proposal_sent | accepted | live | suspended | cancelled
├── business_name (str)
├── contact_name, contact_email, contact_phone
├── proposal_sent_at, proposal_accepted_at, went_live_at (datetime)
├── proposal_notes (text)
├── live_domain (str, unique)
├── internal_notes (text)
├── created_at, updated_at
└── Relationships: store, prospect, client_services
```

### Client Service

```
ClientService
├── id (PK)
├── hosted_site_id (FK → hosted_sites.id, CASCADE)
├── service_type: domain | email | ssl | hosting | website_maintenance
├── name (str)                        # e.g., "acme.lu domain", "5 mailboxes"
├── status: pending | active | suspended | expired | cancelled
├── billing_period: monthly | annual | one_time
├── price_cents (int), currency (str, default EUR)
├── addon_product_id (FK, nullable)   # Link to billing product
├── domain_name, registrar            # Domain-specific
├── mailbox_count                     # Email-specific
├── expires_at, period_start, period_end, auto_renew
├── notes (text)
└── created_at, updated_at
```

---

## User Journeys

### Journey 1: Create Hosted Site from Prospect

**Persona:** Platform Admin
**Goal:** Convert a qualified prospect into a hosted site with a POC website

**Prerequisite:** A prospect exists in the prospecting module (see [Prospecting Journeys](../prospecting/user-journeys.md))

```mermaid
flowchart TD
    A[View prospect in prospecting module] --> B[Click 'Create Hosted Site from Prospect']
    B --> C[HostedSite created with status DRAFT]
    C --> D[Store auto-created on hosting platform]
    D --> E[Contact info pre-filled from prospect]
    E --> F[Navigate to site detail]
    F --> G[Build POC website via CMS editor]
```

**Steps:**

1. Create hosted site from prospect:
    - API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/from-prospect/{prospect_id}`
    - API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/from-prospect/{prospect_id}`
2. This automatically:
    - Creates a Store on the hosting platform
    - Creates a HostedSite record linked to the Store and Prospect
    - Pre-fills business_name, contact_name, contact_email, contact_phone from prospect data
3. View the new site:
    - Dev: `http://localhost:9999/platforms/hosting/admin/hosting/sites/{site_id}`
    - Prod: `https://hostwizard.lu/admin/hosting/sites/{site_id}`
4. Click the Store link to open the CMS editor and build the POC website

---

### Journey 2: Create Hosted Site Manually

**Persona:** Platform Admin
**Goal:** Create a hosted site without an existing prospect (e.g., direct referral)

```mermaid
flowchart TD
    A[Navigate to New Site page] --> B[Fill in business details]
    B --> C[Submit form]
    C --> D[HostedSite + Store created]
    D --> E[Navigate to site detail]
    E --> F[Build POC website]
```

**Steps:**

1. Navigate to New Site form:
    - Dev: `http://localhost:9999/platforms/hosting/admin/hosting/sites/new`
    - Prod: `https://hostwizard.lu/admin/hosting/sites/new`
2. Create the site:
    - API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites`
    - API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites`
    - Body: `{ "business_name": "Boulangerie du Parc", "contact_name": "Jean Müller", "contact_email": "jean@boulangerie-parc.lu", "contact_phone": "+352 26 123 456" }`
3. A Store is auto-created with subdomain `boulangerie-du-parc` on the hosting platform

---

### Journey 3: POC → Proposal Flow

**Persona:** Platform Admin
**Goal:** Build a POC website, mark it ready, and send a proposal to the prospect

```mermaid
flowchart TD
    A[Site is DRAFT] --> B[Build POC website via CMS]
    B --> C[Mark POC Ready]
    C --> D[Site is POC_READY]
    D --> E[Preview the POC site]
    E --> F[Send Proposal with notes]
    F --> G[Site is PROPOSAL_SENT]
    G --> H[Share preview link with prospect]
```

**Steps:**

1. Build the POC website using the Store's CMS editor (linked from site detail page)
2. When the POC is ready, mark it:
    - API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/mark-poc-ready`
    - API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/mark-poc-ready`
3. Preview the POC site (public link, no auth needed):
    - Dev: `http://localhost:9999/platforms/hosting/hosting/sites/{id}/preview`
    - Prod: `https://hostwizard.lu/hosting/sites/{id}/preview`
4. Send proposal to the prospect:
    - API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/send-proposal`
    - API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/send-proposal`
    - Body: `{ "notes": "Custom website with 5 pages, domain registration included" }`
5. Share the preview link with the prospect via email

!!! info "POC Viewer"
    The POC Viewer page renders the Store's storefront in an iframe with a teal
    HostWizard banner at the top. It only works for sites with status `poc_ready`
    or `proposal_sent`. Once the site goes live, the preview is disabled.

---

### Journey 4: Accept Proposal & Create Merchant

**Persona:** Platform Admin
**Goal:** When a prospect accepts, create their merchant account and subscription

```mermaid
flowchart TD
    A[Prospect accepts proposal] --> B{Existing merchant?}
    B -->|Yes| C[Link to existing merchant]
    B -->|No| D[Auto-create merchant + owner account]
    C --> E[Accept Proposal]
    D --> E
    E --> F[Site is ACCEPTED]
    F --> G[Store reassigned to merchant]
    G --> H[Subscription created on hosting platform]
    H --> I[Prospect marked as CONVERTED]
```

**Steps:**

1. Accept the proposal (auto-creates merchant if no merchant_id provided):
    - API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/accept`
    - API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/accept`
    - Body: `{}` (auto-create merchant) or `{ "merchant_id": 5 }` (link to existing)
2. This automatically:
    - Creates a new Merchant from contact info (name, email, phone)
    - Creates a store owner account with a temporary password
    - Reassigns the Store from the system merchant to the new merchant
    - Creates a MerchantSubscription on the hosting platform (essential tier)
    - Marks the linked prospect as CONVERTED (if prospect_id is set)
3. View the updated site detail:
    - Dev: `http://localhost:9999/platforms/hosting/admin/hosting/sites/{id}`
    - Prod: `https://hostwizard.lu/admin/hosting/sites/{id}`

!!! warning "Merchant account credentials"
    When accepting without an existing `merchant_id`, a new merchant owner account is
    created with a temporary password. The admin should communicate these credentials
    to the client so they can log in and self-edit their website via the CMS.

---

### Journey 5: Go Live with Custom Domain

**Persona:** Platform Admin
**Goal:** Assign a production domain to the website and make it live

```mermaid
flowchart TD
    A[Site is ACCEPTED] --> B[Configure DNS for client domain]
    B --> C[Go Live with domain]
    C --> D[Site is LIVE]
    D --> E[StoreDomain created]
    E --> F[Website accessible at client domain]
```

**Steps:**

1. Ensure DNS is configured for the client's domain (A/AAAA records pointing to the server)
2. Go live:
    - API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/go-live`
    - API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/go-live`
    - Body: `{ "domain": "boulangerie-parc.lu" }`
3. This automatically:
    - Sets `went_live_at` timestamp
    - Creates a StoreDomain record (primary) for the domain
    - Sets `live_domain` on the hosted site
4. The website is now accessible at `https://boulangerie-parc.lu`

---

### Journey 6: Add Client Services

**Persona:** Platform Admin
**Goal:** Track operational services (domains, email, SSL, hosting) for a client

```mermaid
flowchart TD
    A[Open site detail] --> B[Go to Services tab]
    B --> C[Add domain service]
    C --> D[Add email service]
    D --> E[Add SSL service]
    E --> F[Add hosting service]
    F --> G[Services tracked with expiry dates]
```

**Steps:**

1. Navigate to site detail, Services tab:
    - Dev: `http://localhost:9999/platforms/hosting/admin/hosting/sites/{site_id}`
    - Prod: `https://hostwizard.lu/admin/hosting/sites/{site_id}`
2. Add a domain service:
    - API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services`
    - API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{site_id}/services`
    - Body: `{ "service_type": "domain", "name": "boulangerie-parc.lu domain", "domain_name": "boulangerie-parc.lu", "registrar": "Namecheap", "billing_period": "annual", "price_cents": 1500, "expires_at": "2027-03-01T00:00:00", "auto_renew": true }`
3. Add an email service:
    - Body: `{ "service_type": "email", "name": "5 mailboxes", "mailbox_count": 5, "billing_period": "monthly", "price_cents": 999 }`
4. Add an SSL service:
    - Body: `{ "service_type": "ssl", "name": "SSL certificate", "billing_period": "annual", "price_cents": 0, "expires_at": "2027-03-01T00:00:00" }`
5. View all services for a site:
    - API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services`
    - API Prod: `GET https://hostwizard.lu/api/admin/hosting/sites/{site_id}/services`

---

### Journey 7: Dashboard & Renewal Monitoring

**Persona:** Platform Admin
**Goal:** Monitor business KPIs and upcoming service renewals

```mermaid
flowchart TD
    A[Navigate to Dashboard] --> B[View KPIs]
    B --> C[Total sites, live sites, POC sites]
    C --> D[Monthly revenue]
    D --> E[Active services count]
    E --> F[Upcoming renewals in 30 days]
    F --> G[Navigate to Client Services]
    G --> H[Filter by expiring soon]
    H --> I[Renew or update services]
```

**Steps:**

1. Navigate to Dashboard:
    - Dev: `http://localhost:9999/platforms/hosting/admin/hosting`
    - Prod: `https://hostwizard.lu/admin/hosting`
2. View dashboard stats:
    - API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/hosting/stats/dashboard`
    - API Prod: `GET https://hostwizard.lu/api/admin/hosting/stats/dashboard`
    - Returns: `total_sites`, `live_sites`, `poc_sites`, `sites_by_status`, `active_services`, `monthly_revenue_cents`, `upcoming_renewals`, `services_by_type`
3. Navigate to Client Services for detailed view:
    - Dev: `http://localhost:9999/platforms/hosting/admin/hosting/clients`
    - Prod: `https://hostwizard.lu/admin/hosting/clients`
4. Filter by type (domain, email, ssl, hosting) or status
5. Toggle "Expiring Soon" to see services expiring within 30 days

---

### Journey 8: Suspend & Reactivate

**Persona:** Platform Admin
**Goal:** Handle suspension (e.g., unpaid invoices) and reactivation

**Steps:**

1. Suspend a site:
    - API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/suspend`
    - API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/suspend`
2. Site status changes to `suspended`
3. Once payment is resolved, reactivate by transitioning back to live:
    - The `suspended → live` transition is allowed
4. To permanently close a site:
    - API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/cancel`
    - API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/cancel`
5. `cancelled` is a terminal state — no further transitions allowed

---

### Journey 9: Complete Pipeline (Prospect → Live Site)

**Persona:** Platform Admin
**Goal:** Walk the complete pipeline from prospect to live website

This journey combines the prospecting and hosting modules end-to-end:

```mermaid
flowchart TD
    A[Import domain / capture lead] --> B[Enrich & score prospect]
    B --> C[Create hosted site from prospect]
    C --> D[Build POC website via CMS]
    D --> E[Mark POC ready]
    E --> F[Send proposal + share preview link]
    F --> G{Prospect accepts?}
    G -->|Yes| H[Accept → Merchant created]
    H --> I[Add client services]
    I --> J[Go live with domain]
    J --> K[Website live at client domain]
    K --> L[Monitor renewals & services]
    G -->|No| M[Cancel or follow up later]
```

**Steps:**

1. **Prospecting phase** (see [Prospecting Journeys](../prospecting/user-journeys.md)):
    - Import domain or capture lead offline
    - Run enrichment pipeline
    - Score and qualify the prospect
2. **Create hosted site**: `POST /api/admin/hosting/sites/from-prospect/{prospect_id}`
3. **Build POC**: Edit the auto-created Store via CMS
4. **Mark POC ready**: `POST /api/admin/hosting/sites/{id}/mark-poc-ready`
5. **Send proposal**: `POST /api/admin/hosting/sites/{id}/send-proposal`
6. **Share preview**: Send `https://hostwizard.lu/hosting/sites/{id}/preview` to prospect
7. **Accept proposal**: `POST /api/admin/hosting/sites/{id}/accept`
8. **Add services**: `POST /api/admin/hosting/sites/{id}/services` (domain, email, SSL, hosting)
9. **Go live**: `POST /api/admin/hosting/sites/{id}/go-live` with domain
10. **Monitor**: Dashboard at `https://hostwizard.lu/admin/hosting`

---

## Recommended Test Order

1. **Journey 2** - Create a site manually first (simplest path, no prospect dependency)
2. **Journey 3** - Walk the POC → proposal flow
3. **Journey 4** - Accept proposal and verify merchant creation
4. **Journey 5** - Go live with a test domain
5. **Journey 6** - Add client services
6. **Journey 7** - Check dashboard stats
7. **Journey 1** - Test the prospect → hosted site conversion (requires prospecting data)
8. **Journey 8** - Test suspend/reactivate/cancel
9. **Journey 9** - Walk the complete end-to-end pipeline

!!! tip "Test Journey 2 before Journey 1"
    Journey 2 (manual creation) doesn't require any prospecting data and is the fastest
    way to verify the hosting module works. Journey 1 (from prospect) requires running
    the prospecting module first.
