# ProspectCRM — Setup Guide

**Architecture:** one shared codebase, one deployment — but each tenant gets
its own dedicated database. A single small "system" database holds the
tenant registry (`tenants` table: subdomain, custom domain, which database
they live in, status). All other tables (`users`, `leads`,
`lead_activities`, `campaigns`, `messages`) live inside each tenant's own
database, with no `tenant_id` column needed — the database itself is the
isolation boundary.

This still needs `composer install` on your actual server (this sandbox
can't reach packagist, so `vendor/` and the framework `system/` folder
aren't included).

## 1. One deployment, not one per tenant

Deploy this codebase **once**, at a single path, e.g.
`/home/prosptadm/prospectcrm`. Do NOT create a separate folder per tenant
(e.g. `/home/prosptadm/trucklgst`) — every tenant is served by this same
codebase; only the database differs.

## 2. Three hosts, two document roots

| Host | Document root | Purpose |
|---|---|---|
| `prospectcrm.app` / `www` | `public_html/` | Marketing/landing page — a **separate** site, not this codebase |
| `admin.prospectcrm.app` | `prospectcrm/public` | Tenant management backend (system DB) |
| `*.prospectcrm.app` (any tenant) | `prospectcrm/public` | The CRM app itself, tenant-resolved |

`admin.*` and every tenant subdomain point at the **same** CI4
`public/` folder — `TenantFilter` recognizes the `admin` subdomain and
skips tenant resolution for it, routing instead to `Admin\Tenants` (see
`app/Controllers/Admin/Tenants.php`), which operates on the system DB
directly. Only the bare/marketing domain is a genuinely separate site.

## 3. DNS

- `prospectcrm.app` (A record) -> server IP, docroot `public_html/`
- `admin.prospectcrm.app` -> same IP, docroot `prospectcrm/public`
- `*.prospectcrm.app` (wildcard) -> same IP, docroot `prospectcrm/public`
  (covers every tenant automatically; explicit subdomains like `admin`
  take precedence over the wildcard)
- Wildcard SSL cert (`*.prospectcrm.app`) via Let's Encrypt DNS-01
  (HTTP-01 doesn't cover wildcards) — this also covers `admin.*`

## 4. Server setup

```bash
cd /home/prosptadm/prospectcrm
composer install --no-dev --optimize-autoloader
nano .env   # fill in real DB host/user/password — leave app.baseURL as
            # the placeholder value (it doesn't need to match any
            # particular host; all redirects in this app use the
            # to_path() helper, which bypasses baseURL and stays on
            # whatever host the request came in on)
```

The DB user in `.env` needs `CREATE DATABASE` privilege — tenant
provisioning creates a new database per tenant at runtime.

## 5. Database setup

**System database** (one time, holds the tenant registry):

```bash
php spark migrate
```

This creates just the `tenants` table (in the database named in `.env`).

**Per-tenant database** (once per new tenant):

```bash
php spark tenant:create trucklgst "Truck Logistics Co"
```

This will:
1. Create a new database (e.g. `prospectcrm_trucklgst`)
2. Apply the CRM schema to it (`app/Database/TenantSchema/schema.sql`)
3. Register the tenant in the system `tenants` table

Once that's run, `trucklgst.prospectcrm.app` is live — `TenantFilter`
resolves it to the new database automatically.

## 6. What's scaffolded vs. what's still to build

**Included:**
- System DB migration (`tenants` table)
- Per-tenant schema (`app/Database/TenantSchema/schema.sql`) — users,
  leads, lead_activities, campaigns, messages
- `TenantContext` + `TenantFilter` — resolves tenant from subdomain/custom
  domain, connects to that tenant's own database for the rest of the
  request; skips resolution entirely for the `admin` subdomain
- `TenantProvisioner` + `php spark tenant:create` — one-command tenant
  onboarding
- `BaseModel` — every tenant-scoped model automatically queries the
  correct tenant database
- Models: `TenantModel` (system DB), `UserModel`, `LeadModel`,
  `LeadActivityModel`, `CampaignModel`, `MessageModel` (all tenant DB)
- Route stubs for leads, campaigns, and inbound provider webhooks
- `Admin\Tenants` controller (JSON stub) + hostname-scoped routes for
  `admin.prospectcrm.app` — list/create/view tenants
- Admin auth — `admin_users` table (system DB), `Admin\Auth` login/logout
  (bare HTML form, no styling), `AdminAuthFilter` protecting all
  `admin.prospectcrm.app` routes except `/login`. Bootstrap your first
  admin account with `php spark admin:create` (no public signup by design)

**Not yet built** (next steps):
- Controllers' actual logic for `Leads::*`, `Campaigns::*`, `Webhooks::*`
- Tenant-side auth/login (checks that tenant's own `users` table)
- Email/SMS provider integration (e.g. SES/Postmark + Twilio)
- Views/UI for both the admin backend and the tenant app
- The `public_html/` marketing site itself (not part of this codebase)
