Files
tajniak81 d6956395c8 Rebrand CommGate to gsmnode and adopt new design system
Rename the whole project from CommGate to gsmnode and re-skin every
surface onto the new signal-green + ink design system (Space Grotesk /
IBM Plex Sans / JetBrains Mono, flat surfaces, two-arrow routing mark,
lowercase gsm+node wordmark).

- Web App + API panel: rewrite token layer, gn-* utilities, data-gsm-theme,
  new logo/favicon assets; both builds verified.
- Phone App (Flutter): green theme, new mark/wordmark widgets, adaptive
  launcher icons; rename Android applicationId/package to app.gsmnode.phone;
  bump AGP to 8.6.0 and google_fonts to 8.1.0; debug APK build verified.
- API Server (Go): panel routes, User-Agent, health service id, branding.
- Home Assistant Plugin: rename integration domain sms_gateway to gsmnode
  (folder, DOMAIN, services, entity ids, classes); py_compile verified.
- Update all READMEs; add .gitignore (excludes Design/, build artifacts).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 08:53:14 +02:00

155 lines
5.4 KiB
Markdown

# gsmnode — API Server
Go service that is the **single trusted entry point** in front of PocketBase.
The Web App and Phone App talk only to this server; it performs all PocketBase
access as a superuser and enforces ownership in application logic.
```
Web App ─┐
├─► API Server (:8080) ─► PocketBase (10.2.1.10:8028)
Phone App ─┘
```
The server root (`GET /`) serves a gsmnode-branded **web panel**: a live health
readout plus a quick reference of both API audiences. Open
http://localhost:8080/ in a browser to check the server at a glance.
The panel is a **Vue 3 + Tailwind v4** app in [`panel/`](panel/), built into
`internal/api/dist` and embedded into the Go binary at compile time:
```powershell
cd panel
npm install
npm run build # outputs to ../internal/api/dist
cd ..; go build -o api-server.exe ./cmd/server # embeds the fresh dist
```
For panel development with hot reload (proxies `/api` to a running server on
`:8080`): `cd panel; npm run dev` → http://localhost:5174.
## Requirements
- Go 1.26+ (`go version`)
- A reachable PocketBase v0.23+ instance and its **superuser** credentials
- Node 18+ (only for the setup scripts)
## 1. Configure
```powershell
Copy-Item .env.example .env
# edit .env: set PB_ADMIN_EMAIL, PB_ADMIN_PASSWORD, and a strong JWT_SECRET
```
| Variable | Purpose | Default |
|---|---|---|
| `API_ADDR` | Listen address | `:8080` |
| `POCKETBASE_URL` | PocketBase base URL | `http://10.2.1.10:8028` |
| `PB_ADMIN_EMAIL` / `PB_ADMIN_PASSWORD` | PocketBase superuser login | — (required) |
| `JWT_SECRET` | Signs client JWTs | dev placeholder |
| `JWT_ACCESS_TTL` | Access-token lifetime | `24h` |
| `CORS_ALLOW_ORIGINS` | Comma list, or `*` | `*` |
## 2. Set up PocketBase collections
Creates/updates `devices`, `messages`, `inbox`, `webhooks` (the default `users`
auth collection is reused). Idempotent.
```powershell
$env:POCKETBASE_URL="http://10.2.1.10:8028"
$env:PB_ADMIN_EMAIL="admin@example.com"
$env:PB_ADMIN_PASSWORD="your-password"
node scripts/setup-pocketbase.mjs
```
Create a login user:
```powershell
node scripts/create-user.mjs user@example.com "user-password" "Display Name"
```
## 3. Run
```powershell
./scripts/Run-ApiServer.ps1
# or: go run ./cmd/server
```
Health check: `GET http://localhost:8080/api/health`.
## API
### Authentication scheme
- **Client API** (`/api/...`): `Authorization: Bearer <JWT>` from `/api/auth/login`.
Used by the Web App and integrators.
- **Mobile API** (`/api/mobile/...`): `Authorization: Bearer <device_token>`
returned by device registration. Used by the Phone App.
### Client / 3rd-party endpoints
| Method | Path | Description |
|---|---|---|
| `GET` | `/api/health` | Readiness probe (public) |
| `POST` | `/api/auth/login` | `{email, password}` → JWT + user |
| `POST` | `/api/auth/refresh` | New JWT (auth) |
| `GET` | `/api/auth/me` | Current user |
| `GET` | `/api/devices` | List your devices |
| `DELETE` | `/api/devices/{id}` | Remove a device |
| `POST` | `/api/messages` | Enqueue SMS `{phone_numbers[], text_message, device_id?, sim_number?, schedule_at?}` |
| `POST` | `/api/calls` | Enqueue a phone call `{phone_number, device_id?}` |
| `GET` | `/api/messages` | List messages (`?status=&device_id=&type=&page=&per_page=`) |
| `GET` | `/api/messages/{id}` | Message state |
| `GET` | `/api/inbox` | Received SMS |
| `GET` | `/api/webhooks` | List webhooks |
| `POST` | `/api/webhooks` | Register `{event, url, device_id?}` |
| `DELETE` | `/api/webhooks/{id}` | Delete webhook |
### Mobile / device endpoints
| Method | Path | Description |
|---|---|---|
| `POST` | `/api/mobile/v1/device` | Register device (auth: **user JWT**) → returns `auth_token` |
| `POST` | `/api/mobile/v1/ping` | Heartbeat (auth: device token) |
| `GET` | `/api/mobile/v1/messages` | Pull pending messages; marks them `Processed` |
| `PATCH` | `/api/mobile/v1/messages/{id}` | Report `{status, error?}` (`Sent`/`Delivered`/`Failed`) |
| `POST` | `/api/mobile/v1/inbox` | Report received SMS `{phone_number, message, received_at?}` |
### Message lifecycle
`Pending` → (device pulls) `Processed``Sent``Delivered`, or `Failed`.
Calls are stored as messages with `type: "call"` (SMS is `type: "sms"`) and flow
through the same pull/report pipeline. The device dials the number natively and
reports `Sent` (a call has no delivery report) or `Failed`.
### Webhook events
`sms:received`, `sms:sent`, `sms:delivered`, `sms:failed`. Delivered as
`POST {event, device_id, payload, created_at}` to the registered URL.
## Quick smoke test
```powershell
# log in
$login = curl -s -X POST http://localhost:8080/api/auth/login `
-H "Content-Type: application/json" `
-d '{"email":"user@example.com","password":"user-password"}' | ConvertFrom-Json
$token = $login.access_token
# register a device (as the phone app would)
curl -s -X POST http://localhost:8080/api/mobile/v1/device `
-H "Authorization: Bearer $token" -H "Content-Type: application/json" `
-d '{"device_id":"test-1","name":"Test Phone","platform":"android"}'
```
## Project layout
```
cmd/server/main.go entry point, wiring, graceful shutdown
internal/config env/.env configuration
internal/pb PocketBase REST client (superuser)
internal/auth JWT issue/verify, device token generation
internal/api router, middleware, handlers
scripts/ PocketBase setup + run helpers
```