# Operations

Day-to-day commands for running project-bifrost.

## Managing invites

All commands run on the VPS as the `fenja` user.

```bash
# Add someone
sudo -u fenja node /opt/fenja/bin/invite.js add someone@example.com

# Remove someone (doesn't kill their active session — see below)
sudo -u fenja node /opt/fenja/bin/invite.js remove someone@example.com

# List everyone
sudo -u fenja node /opt/fenja/bin/invite.js list
```

Removing an invite stops a user from requesting *new* codes, but doesn't invalidate their existing session cookie (valid 30 days). To kick them out immediately, also run:

```bash
sudo sqlite3 /opt/fenja/data/fenja.sqlite \
  "DELETE FROM sessions WHERE email = 'someone@example.com';"
```

## Service control

```bash
sudo systemctl status fenja          # is it running?
sudo systemctl restart fenja         # restart (after config/code changes)
sudo journalctl -u fenja -f          # live log tail
sudo journalctl -u fenja -n 100      # last 100 lines
```

## Deploying code changes

From your laptop, in WSL, inside the project folder:

```bash
# Push to staging on VPS
rsync -avz --delete \
  --exclude node_modules --exclude data --exclude .env --exclude .git \
  ./ user@project-bifrost.fenja.ai:/tmp/fenja-upload/

# Then on the VPS:
ssh user@project-bifrost.fenja.ai
sudo rsync -a --delete /tmp/fenja-upload/ /opt/fenja/
sudo chown -R fenja:fenja /opt/fenja
rm -rf /tmp/fenja-upload

# If package.json changed:
cd /opt/fenja
sudo -u fenja npm ci --omit=dev

# Restart
sudo systemctl restart fenja
sudo journalctl -u fenja -n 20
```

Confirm `[mail] SMTP relay reachable` and `[bifrost] listening` appear in the logs.

## Editing secrets (SMTP, pepper)

Secrets live in `/etc/fenja/env`, not in the repo.

```bash
sudo nano /etc/fenja/env
sudo systemctl restart fenja
```

**Never change `CODE_PEPPER` after go-live** — it invalidates every pending code. Not catastrophic (users re-request within 10 min), but avoid unless rotating for security.

## Backups

Nightly cron at `/etc/cron.d/fenja-backup` snapshots the SQLite file to `/opt/fenja/data/backup-YYYY-MM-DD.sqlite`, keeping 14 days.

Manual snapshot:

```bash
sudo -u fenja sqlite3 /opt/fenja/data/fenja.sqlite \
  ".backup /opt/fenja/data/backup-manual-$(date +%F).sqlite"
```

Pull a backup to your laptop:

```bash
scp user@project-bifrost.fenja.ai:/opt/fenja/data/backup-YYYY-MM-DD.sqlite .
```

## Quick health checks

```powershell
# From your laptop
curl.exe -I https://project-bifrost.fenja.ai/              # expect 200
curl.exe -I https://project-bifrost.fenja.ai/timeline.js   # expect 302 → /
```

If either fails, check Nginx (`sudo systemctl status nginx`) and Node (`sudo systemctl status fenja`).

## Troubleshooting

| Symptom | First thing to check |
|---|---|
| Users don't get codes | `journalctl -u fenja -n 50` for SMTP errors |
| Codes arrive in spam | SPF/DKIM/DMARC records on the sending domain |
| 502 Bad Gateway | Node crashed — `systemctl status fenja` then `journalctl` |
| 504 Gateway Timeout | Node running but hung — `systemctl restart fenja` |
| Nginx config change broke something | `sudo nginx -t` will tell you exactly what |
| Can't log in with the right code | Clock drift between your machine and the VPS, or pepper mismatch |

## File locations

```
/opt/fenja/                 code (owned by fenja:fenja)
/opt/fenja/data/            SQLite + nightly backups
/etc/fenja/env              secrets (root:fenja, 640)
/etc/systemd/system/fenja.service
/etc/nginx/sites-available/project-bifrost
/etc/nginx/sites-enabled/project-bifrost  (symlink)
/etc/letsencrypt/live/project-bifrost.fenja.ai/  TLS certs
/etc/cron.d/fenja-backup
```
