# Litoral Regas VPN Orchestrator

A dark-themed Tauri desktop technician app for provisioning Litoral_Regas OpenWrt WireGuard production routers.

## Production baseline

The app is structured around the validated router baseline:

- OpenWrt 23.05 only
- ZBT-WE826 16M target firmware
- fw4/nftables only
- no `opkg upgrade`
- LAN subnet: `198.51.100.0/24`
- Router LAN IP: `198.51.100.1`
- Controller IP: `198.51.100.10`
- PLC IP: `198.51.100.50`
- Overlay route: `198.19.0.0/16`
- Router password: `litoralr`
- Hostname format: `Litoral_Regas_XXX`
- LuCI over WireGuard
- VPN firewall zone and DNAT rules:
  - router WG IP `:5900` -> `198.51.100.10:5900`
  - router WG IP `:20248` -> `198.51.100.10:20249`
  - router WG IP `:8000` -> `198.51.100.10:8000`
  - router WG IP `:81` -> `198.51.100.50:81`

## Install

```bash
npm install
npm install lucide-react recharts clsx tailwind-merge
npm install -D tailwindcss postcss autoprefixer
```

## Development

```bash
npm run tauri:dev
```

Equivalent bootstrap command sequence:

```bash
npm create tauri-app@latest lr-openwrt-tool
# choose React, TypeScript, npm
cd lr-openwrt-tool
npm install
npm run tauri:dev
```

## Build

```bash
npm run tauri:build
```

## Backend assumptions

Development defaults are stored in app settings, not hardcoded as production secrets:

- Base URL: `http://localhost:8080`
- Header: `X-API-Key: dev-api-key`

Implemented API client calls:

- `GET /api/vpn/available-ip`
- `GET /api/vpn/used-ips`
- `POST /api/vpn/peers`
- `GET /api/vps/health`
- `POST /api/vps/wireguard/rollback-last-backup`

## Provisioning flow

The provisioning wizard models the technician workflow as a state machine:

1. `IDLE`
2. `DETECT_ROUTER`
3. `UPLOAD_FIRMWARE`
4. `FLASHING`
5. `WAITING_FOR_REBOOT`
6. `WAITING_FOR_RECONNECT`
7. `UPLOAD_PROVISIONING_BUNDLE`
8. `RUN_PROVISIONING`
9. `CAPTURE_PUBLIC_KEY`
10. `REGISTER_PEER`
11. `VERIFY`
12. `COMPLETE`
13. `ERROR`

New router flow:

1. Detect router at `192.168.1.1`.
2. Request next available VPN IP from the backend.
3. Generate `router.env` using the production baseline.
4. Upload firmware, flash router, and wait for SSH at `198.51.100.1`.
5. Upload `router.env` and `provision.sh`.
6. Run provisioning.
7. Capture WireGuard public key.
8. Register peer with `POST /api/vpn/peers`.
9. Verify final router state.

Reprovision flow keeps the selected existing VPN IP and replaces the public key through the same `POST /api/vpn/peers` endpoint.

## Current Tauri command status

The following commands are implemented as mock placeholders with production-ready signatures:

- `detect_router(ip)`
- `upload_firmware(ip, firmwarePath)`
- `flash_router(ip, remoteFirmwarePath)`
- `wait_for_ssh(ip)`
- `upload_provisioning_bundle(ip, envContent, scriptContent)`
- `run_provisioning(ip)`
- `capture_wireguard_public_key(ip)`
- `verify_router(ip)`

Future work should replace the mock bodies with real SSH/SCP/sysupgrade logic and explicitly call `remove_known_host` before reconnect attempts for `192.168.1.1` and `198.51.100.1`.
