# TeXise SaaS — MySQL, Administrator and Trusted API Setup

## What `texise.service` is

`texise.service` is the loopback-only trusted backend used by Apache for `/api/*` and by TeXise for accounts/sessions, Google OAuth callbacks, project metadata, licenses and AI quota, CMS/support, scholarly-provider gateways, AI Review server fallback and collaboration signaling. It is **not** the LaTeX compiler. Manuscript files and compilation remain browser-local.

The HTTP API listens on `127.0.0.1:3100`; collaboration signaling listens on `127.0.0.1:3101` by default.

## Existing production database: `texise_db`

Provision the database with a dedicated least-privilege application account. The examples below use `texise_app`. Generate a password containing only hex characters so it is safe to place in the systemd EnvironmentFile:

```bash
DB_PASS="$(openssl rand -hex 32)"
printf '%s\n' "$DB_PASS"
```

Using MySQL (use `mariadb` instead when that is the local administrator client):

```sql
CREATE DATABASE IF NOT EXISTS texise_db
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

CREATE USER IF NOT EXISTS 'texise_app'@'localhost' IDENTIFIED BY 'REPLACE_WITH_DB_PASS';
CREATE USER IF NOT EXISTS 'texise_app'@'127.0.0.1' IDENTIFIED BY 'REPLACE_WITH_DB_PASS';
ALTER USER 'texise_app'@'localhost' IDENTIFIED BY 'REPLACE_WITH_DB_PASS';
ALTER USER 'texise_app'@'127.0.0.1' IDENTIFIED BY 'REPLACE_WITH_DB_PASS';

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, REFERENCES
  ON texise_db.* TO 'texise_app'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, REFERENCES
  ON texise_db.* TO 'texise_app'@'127.0.0.1';
FLUSH PRIVILEGES;
```

TeXise does not require `DROP`, global `CREATE DATABASE`, or MySQL root privileges during normal operation. Leave `TEXISE_MYSQL_CREATE_DATABASE=0` when `texise_db` already exists.

Verify the application account before running the TeXise upgrade:

```bash
mysql -h 127.0.0.1 -P 3306 -u texise_app -p -D texise_db -e 'SELECT 1 AS ok;'
```

## `/etc/texise/texise.env`

Set the real production database name rather than the historical example default:

```ini
TEXISE_SAAS_ENABLED=1
MYSQL_HOST=127.0.0.1
MYSQL_PORT=3306
MYSQL_DATABASE=texise_db
MYSQL_USER=texise_app
MYSQL_PASSWORD=REPLACE_WITH_DB_PASS
TEXISE_MYSQL_CREATE_DATABASE=0
SESSION_SECRET=REPLACE_WITH_AT_LEAST_32_RANDOM_CHARACTERS
TEXISE_SESSION_DAYS=30
```

Generate a session secret when one is not already present:

```bash
openssl rand -hex 48
```

The installer also generates `SESSION_SECRET` automatically when SaaS is requested and the preserved value is missing/short.

## Administrator bootstrap

There is no manual SQL insert for the first admin. During the SaaS preflight TeXise runs idempotent migrations and then ensures this account exists:

- email: `admin@texise.com`
- initial password: `admin`
- role: `admin`
- status: `active`
- `force_password_change=1`

Open `/admin/login`, sign in once with `admin@texise.com` / `admin`, then TeXise requires a replacement password of at least 12 characters.

If `admin@texise.com` already exists as a normal user, TeXise refuses to silently elevate that row and the preflight fails with `BOOTSTRAP_ADMIN_EMAIL_CONFLICT`.

## Operations commands

The installer places `/usr/local/bin/texise-saas`:

```bash
texise-saas preflight
texise-saas status
texise-saas logs
```

`preflight` uses the same `/etc/texise/texise.env` as the service, connects to the configured database, applies idempotent migrations and verifies the bootstrap administrator. It can therefore diagnose the account layer even if port 3100 is currently unavailable.

## Deployment ordering

For SaaS-enabled installs/upgrades the trusted runtime is now handled in this order:

1. stage server source;
2. install pinned server runtime dependencies;
3. run MySQL/migration/admin preflight as `texise:texise` with the real systemd environment file;
4. abort with the actionable database error if preflight fails;
5. only after a successful preflight replace the active runtime;
6. restart `texise.service`;
7. check `127.0.0.1:3100/api/health`;
8. on a health failure automatically print the latest `texise.service` journal.

This prevents a wrong `MYSQL_DATABASE`, password, grant or migration from being reported only as an opaque `curl: (7)` failure.
