# Deployment Notes

Two active environments share one Convex deployment (`dev:befitting-dalmatian-161`).
Each runs its own web server, Flue agents process, and `.env` file.

## Environments

| | Local Mac Dev | Cheaptricks Staging |
| --- | --- | --- |
| SSH alias | (local) | `cheaptricks` |
| Repo path | `/Users/puter/Workspace/zopu/code` | `/workspace/code` |
| Tailscale IPv4 | `100.101.157.28` | `100.122.185.111` |
| Web URL | `http://100.101.157.28:5173` | `https://zopu.cheaptricks.puter.wtf` |
| Flue URL (internal) | `http://100.101.157.28:3585` | `http://127.0.0.1:3585` |
| Flue URL (browser-facing) | `http://100.101.157.28:3585` | `https://zopu.cheaptricks.puter.wtf/api` |
| Caddy | none (direct Tailscale) | `zopu.cheaptricks.puter.wtf` HTTPS termination |
| Bun | installed directly | symlink at `/workspace/.bun` |
| Process manager | manual `bun run dev:tailscale:*` | `nohup` into `/tmp/zopu-*.log` |

## Shared Convex deployment

Deployment name: `dev:befitting-dalmatian-161`
Convex URL: `https://befitting-dalmatian-161.convex.cloud`
Convex Site URL: `https://befitting-dalmatian-161.convex.site`

Convex env vars are deployment-scoped, not per-machine. Authenticate from any
machine with `npx convex dev` inside `packages/backend`.

Key Convex env var:

```
SITE_URL = <the origin Better Auth should trust>
```

This controls `trustedOrigins` in the Better Auth config
(`packages/backend/convex/auth.ts`). It must match the URL the browser
actually visits, or sign-in fails silently with a CORS rejection.

When switching between environments:

```bash
cd packages/backend

# For local Mac testing:
npx convex env set SITE_URL 'http://100.101.157.28:5173'

# For Cheaptricks staging:
npx convex env set SITE_URL 'https://zopu.cheaptricks.puter.wtf'
```

## Local Mac Dev `.env`

```env
CONVEX_DEPLOYMENT=dev:befitting-dalmatian-161
CONVEX_URL=https://befitting-dalmatian-161.convex.cloud
CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site
SITE_URL=http://100.101.157.28:5173
NATIVE_APP_URL=code://

VITE_CONVEX_URL=https://befitting-dalmatian-161.convex.cloud
VITE_CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site
VITE_FLUE_URL=http://100.101.157.28:3585

DAEMON_ID=local-macbook
DAEMON_NAME=Local MacBook
DAEMON_VERSION=0.0.0
DAEMON_HEARTBEAT_MS=15000
DAEMON_COMMAND_LEASE_MS=60000

FLUE_DB_TOKEN=<from secrets manager>

AGENT_MODEL_PROVIDER=xiaomi
AGENT_MODEL_NAME=mimo-v2.5
AGENT_MODEL_API=openai-completions
AGENT_MODEL_BASE_URL=<cheaptricks gateway base url>
AGENT_MODEL_API_KEY=<cheaptricks api key>
AGENT_MODEL_CONTEXT_WINDOW=1048576
AGENT_MODEL_MAX_TOKENS=131072

GITEA_URL=https://git.openputer.com
GITEA_TOKEN=<gitea personal access token>
```

### Start local dev

```bash
bun run dev:tailscale:agents -- --port 3585 &
bun run dev:tailscale:web &
```

Both bind `0.0.0.0` so they are reachable over Tailscale from a phone.

Before testing locally, flip the Convex `SITE_URL`:

```bash
cd packages/backend && npx convex env set SITE_URL 'http://100.101.157.28:5173'
```

## Cheaptricks Staging `.env`

Located at `/workspace/code/.env` on the `cheaptricks` host.

```env
CONVEX_DEPLOYMENT=dev:befitting-dalmatian-161
CONVEX_URL=https://befitting-dalmatian-161.convex.cloud
CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site
SITE_URL=https://zopu.cheaptricks.puter.wtf
NATIVE_APP_URL=code://

VITE_CONVEX_URL=https://befitting-dalmatian-161.convex.cloud
VITE_CONVEX_SITE_URL=https://befitting-dalmatian-161.convex.site
VITE_FLUE_URL=https://zopu.cheaptricks.puter.wtf/api

VITE_ZOPU_SERVER_URL=https://zopu.cheaptricks.puter.wtf/api
PORT=3590

DAEMON_ID=local-macbook
DAEMON_NAME=Local MacBook
DAEMON_VERSION=0.0.0
DAEMON_HEARTBEAT_MS=15000
DAEMON_COMMAND_LEASE_MS=60000

FLUE_DB_TOKEN=<from secrets manager>

AGENT_MODEL_PROVIDER=xiaomi
AGENT_MODEL_NAME=mimo-v2.5
AGENT_MODEL_API=openai-completions
AGENT_MODEL_BASE_URL=https://ai.cheaptricks.puter.wtf/v1
AGENT_MODEL_API_KEY=<cheaptricks api key>
AGENT_MODEL_CONTEXT_WINDOW=1048576
AGENT_MODEL_MAX_TOKENS=131072

GITEA_URL=https://git.openputer.com
GITEA_TOKEN=<gitea personal access token>
```

### Caddy config

File: `/etc/caddy/Caddyfile` on `cheaptricks`

```
zopu.cheaptricks.puter.wtf {
    bind 135.181.82.179 2a01:4f9:c013:4a64::1
    encode zstd gzip

    handle_path /api/* {
        reverse_proxy 127.0.0.1:3585
    }

    reverse_proxy 127.0.0.1:5173
}
```

`/api/*` routes to the Flue agents process (port 3585).
Everything else routes to the web dev server (port 5173).

Reload after changes:

```bash
sudo systemctl reload caddy
```

### Vite allowedHosts

`apps/web/vite.config.ts` must include `server: { allowedHosts: true }` or
Vite rejects requests arriving through the Caddy domain.

### Start staging dev

```bash
ssh cheaptricks
export PATH=$PATH:/workspace/.bun/bin
cd /workspace/code

# Pull latest
git pull origin feat/web-integrarion
bun install

# Start both processes with nohup so they survive SSH disconnect
nohup bun run dev:tailscale:agents -- --port 3585 > /tmp/zopu-agents.log 2>&1 &
nohup bun run dev:tailscale:web > /tmp/zopu-web.log 2>&1 &
```

Before testing on staging, flip the Convex `SITE_URL`:

```bash
cd packages/backend && npx convex env set SITE_URL 'https://zopu.cheaptricks.puter.wtf'
```

### Verify staging

```bash
curl -sS -o /dev/null -w '%{http_code}\n' https://zopu.cheaptricks.puter.wtf/
# expect: 200

curl -sS -D - -o /dev/null \
  'https://befitting-dalmatian-161.convex.site/api/auth/get-session' \
  -H 'Origin: https://zopu.cheaptricks.puter.wtf' | grep access-control-allow-origin
# expect: access-control-allow-origin: https://zopu.cheaptricks.puter.wtf
```

## Model configuration

Both environments use the same model via the Cheaptricks AI gateway:

- Provider identity: `xiaomi` (Flue catalog maps this to MiMo multimodal metadata)
- Model: `mimo-v2.5`
- API protocol: `openai-completions`
- Context window: `1048576`
- Max output tokens: `131072`
- Multimodal: text + image input

The `AGENT_MODEL_BASE_URL` differs:
- Local Mac: uses the external gateway URL
- Cheaptricks: uses `https://ai.cheaptricks.puter.wtf/v1` (local to the box)

## Known gotchas

1. **Convex SITE_URL is single-valued.** Only one origin can be trusted at a
   time. Switch it when moving between local and staging, or sign-in breaks
   silently with a CORS error in the browser console.

2. **Vite blocks unknown hosts by default.** Caddy domain must be allowed
   via `server.allowedHosts` in `apps/web/vite.config.ts`.

3. **Flue port changed from 3583 to 3585.** The old Caddy config pointed at
   3583/13100. Current ports are 3585 (Flue) and 5173 (web).

4. **`.env` is gitignored.** Each machine maintains its own copy. The repo
   ships `.env.example` as the template.

5. **Convex CLI auth is per-machine.** Run `npx convex dev` once inside
   `packages/backend` on each new machine to authenticate the CLI.
