docs: Add JWT secret rotation and security considerations

- Add JWT to available rotation components
- Document security limitations and manual steps
- Add component table with service restart requirements
- Include verification and best practices documentation

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Rodrigo Rodriguez 2026-02-19 19:42:15 +00:00
parent 6d48dbba1b
commit cb84ad2b56
64 changed files with 688 additions and 139 deletions

View file

@ -55,7 +55,7 @@ On first run, botserver automatically:
- Installs required components (PostgreSQL, S3 storage, Cache, LLM)
- Sets up database with migrations
- Downloads AI models
- Starts HTTP server at `http://127.0.0.1:8080`
- Starts HTTP server at `http://127.0.0.1:9000`
### Run the Desktop App

View file

@ -35,7 +35,7 @@ By the end of this chapter, you will:
./botserver
```
Open `http://localhost:8080`. Start chatting. That's it.
Open `http://localhost:9000`. Start chatting. That's it.
Everything installs automatically on first run—PostgreSQL, storage, cache, and your first bot.
@ -55,7 +55,7 @@ Everything installs automatically on first run—PostgreSQL, storage, cache, and
<p>Just three steps:</p>
<p>1⃣ Download <code>botserver</code></p>
<p>2⃣ Run <code>./botserver</code></p>
<p>3⃣ Open your browser to localhost:8080</p>
<p>3⃣ Open your browser to localhost:9000</p>
<p>The bootstrap process handles everything else automatically!</p>
<div class="wa-time">09:00</div>
</div>

View file

@ -4,7 +4,7 @@ After botserver starts, you can immediately start chatting with your bot. No pro
## Just Start Talking
Open your browser to `http://localhost:8080` and start chatting:
Open your browser to `http://localhost:9000` and start chatting:
```
You: Hi!

View file

@ -120,7 +120,7 @@ psql $DATABASE_URL -c "SELECT version();"
curl http://localhost:8081/v1/models
# Open UI
open http://localhost:8080
open http://localhost:9000
```
## Bot Deployment

View file

@ -10,7 +10,7 @@ botserver certificates include `127.0.0.1` as a Subject Alternative Name (SAN),
| Component | Description | IP:Port |
|-----------|-------------|---------|
| api | Main botserver API | `127.0.0.1:8443` (HTTPS) / `127.0.0.1:8080` (HTTP) |
| api | Main botserver API | `127.0.0.1:8443` (HTTPS) / `127.0.0.1:9000` (HTTP) |
| tables | PostgreSQL database | `127.0.0.1:5432` |
| drive | Object storage (S3-compatible) | `127.0.0.1:9000` |
| cache | Redis cache | `127.0.0.1:6379` |

View file

@ -105,7 +105,7 @@ Installation begins by downloading and running the botserver binary. The bootstr
Bot deployment uses object storage buckets. Each bot receives its own bucket for file storage. Bots are deployed to the drive rather than the work folder, which is reserved for internal operations as documented in the gbapp chapter.
After startup, access the UI interface at `http://localhost:8080` to interact with your bots and monitor their operation.
After startup, access the UI interface at `http://localhost:9000` to interact with your bots and monitor their operation.
## Use Cases

View file

@ -28,13 +28,13 @@ Installing Cache...
Creating bots from templates...
default.gbai deployed
announcements.gbai deployed
botserver ready at http://localhost:8080
botserver ready at http://localhost:9000
```
### 3. Open Browser
```
http://localhost:8080
http://localhost:9000
```
Start chatting with your bot!

View file

@ -14,7 +14,7 @@ A session is a persistent conversation container that tracks everything about an
### UI Interface
When a user opens `http://localhost:8080`, the browser receives a session token in the form of a UUID. This token is stored in localStorage for persistence across page loads. The session itself is created in PostgreSQL for durability and cached for fast access during active conversations.
When a user opens `http://localhost:9000`, the browser receives a session token in the form of a UUID. This token is stored in localStorage for persistence across page loads. The session itself is created in PostgreSQL for durability and cached for fast access during active conversations.
### API Access
@ -22,12 +22,12 @@ Programmatic access to sessions uses the REST API. A POST request to `/api/sessi
```bash
# Get new session
curl -X POST http://localhost:8080/api/session
curl -X POST http://localhost:9000/api/session
# Returns: {"session_id": "uuid-here", "token": "secret-token"}
# Use session
curl -H "Authorization: Bearer secret-token" \
http://localhost:8080/api/chat
http://localhost:9000/api/chat
```
### Anonymous vs Authenticated

View file

@ -158,7 +158,7 @@ greeting,Welcome to support!
```bash
cp -r my-bot.gbai/ templates/
./botserver restart
# Visit http://localhost:8080/my-bot
# Visit http://localhost:9000/my-bot
```
### Production Server

View file

@ -674,7 +674,7 @@ idleTimeout = 60 ' Return to welcome screen after inactivity
lastActivity = NOW
' Initialize display
' (Runs in browser kiosk mode at http://localhost:8088/embedded/)
' (Runs in browser kiosk mode at http://localhost:9000/embedded/)
TALK welcomeMessage

View file

@ -122,7 +122,7 @@ Select based on your needs:
```bash
# Templates are auto-deployed during bootstrap
# Access at: http://localhost:8080/template-name
# Access at: http://localhost:9000/template-name
```
### 3. Customize Configuration

View file

@ -19,10 +19,10 @@ General Bots UI system built with HTMX and server-side rendering.
## Quick Access
```
http://localhost:8080 → Main interface
http://localhost:8080/chat → Chat app
http://localhost:8080/drive → File manager
http://localhost:8080/console → Terminal mode
http://localhost:9000 → Main interface
http://localhost:9000/chat → Chat app
http://localhost:9000/drive → File manager
http://localhost:9000/console → Terminal mode
```
## Suite Applications

View file

@ -96,7 +96,7 @@ Bot responses support full Markdown rendering:
### WebSocket Connection
```
ws://your-server:8080/ws
ws://your-server:9000/ws
```
**Message Types:**

View file

@ -102,7 +102,7 @@ Default template for browser access:
```bash
./botserver
# Browse to http://localhost:8080
# Browse to http://localhost:9000
# Loads Suite interface
```

View file

@ -90,7 +90,7 @@ Console mode supports any terminal with basic text output capabilities. UTF-8 su
## Tips
Console mode operates in read-only fashion and does not accept bot commands. For interactive bot testing, use the web interface available at http://localhost:8080. The display refreshes automatically every few seconds to show current status. Output is buffered for performance to avoid slowing down the server during high activity periods.
Console mode operates in read-only fashion and does not accept bot commands. For interactive bot testing, use the web interface available at http://localhost:9000. The display refreshes automatically every few seconds to show current status. Output is buffered for performance to avoid slowing down the server during high activity periods.
## Troubleshooting

View file

@ -130,7 +130,7 @@ This means:
The widget connects via WebSocket for real-time updates:
```
ws://localhost:8080/ws/dev
ws://localhost:9000/ws/dev
```
When connected:

View file

@ -63,7 +63,7 @@ Launch your preferred web browser by clicking its icon.
┌─────────────────────────────────────────────────────────────────────────┐
│ 🌐 Browser [─][□][×]│
├─────────────────────────────────────────────────────────────────────────┤
│ ← → ↻ │ https://your-company.bot:8080 │ ☆ │ │
│ ← → ↻ │ https://your-company.bot:9000 │ ☆ │ │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ Loading... │
@ -76,7 +76,7 @@ Launch your preferred web browser by clicking its icon.
Type your General Bots address in the address bar and press **Enter**.
💡 **Tip**: Your URL will look something like:
- `http://localhost:8080` (development)
- `http://localhost:9000` (development)
- `https://bots.yourcompany.com` (production)
- `https://app.pragmatismo.cloud` (cloud hosted)

View file

@ -21,7 +21,7 @@ The dashboard displays botserver at the center orchestrating all interactions, w
The monitoring dashboard is the **default homepage** when accessing Suite:
```/dev/null/monitoring-url.txt#L1
http://localhost:8080/monitoring
http://localhost:9000/monitoring
```
Or from within Suite:

View file

@ -71,7 +71,7 @@ Automatic dark mode activates based on system preference:
Connection handling is simplified for reliability:
```javascript
const ws = new WebSocket('ws://localhost:8080/ws');
const ws = new WebSocket('ws://localhost:9000/ws');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
@ -98,7 +98,7 @@ function sendMessage() {
The single.gbui template is perfect for embedding in existing websites:
```html
<iframe src="http://localhost:8080/ui/suite/single.gbui"
<iframe src="http://localhost:9000/ui/suite/single.gbui"
width="400"
height="600">
</iframe>

View file

@ -23,7 +23,7 @@ General Bots Suite is your all-in-one workspace that combines communication, pro
### Opening the Suite
1. **Open your web browser** (Chrome, Firefox, Safari, or Edge)
2. **Go to your General Bots address** (example: `http://your-company.bot:8080`)
2. **Go to your General Bots address** (example: `http://your-company.bot:9000`)
3. **The Suite loads automatically** - you'll see the workspace in seconds
### Your First Look

View file

@ -59,7 +59,7 @@ The Suite interface provides multi-application integration with seamless navigat
The Suite interface is best suited for enterprise deployments requiring full functionality, power users working with multiple services simultaneously, desktop application distribution via Tauri builds, and multi-service integrations where context switching between modules matters.
You can access the Suite interface via web at `http://localhost:8080/suite` or as a native desktop application using the `botui` Tauri app (see [BotUI Desktop](../botui/README.md)).
You can access the Suite interface via web at `http://localhost:9000/suite` or as a native desktop application using the `botui` Tauri app (see [BotUI Desktop](../botui/README.md)).
## Minimal Interface
@ -69,7 +69,7 @@ This lightweight interface provides core chat and basic interactions only, fast
The Minimal interface excels for mobile web access, embedded chatbots in external websites, low-bandwidth environments, quick access terminals and kiosks, and scenarios where simplicity matters more than features.
Access the Minimal interface at the root URL `http://localhost:8080` where it is served by default, explicitly at `http://localhost:8080/minimal`, or embedded via iframe or WebView in your own applications.
Access the Minimal interface at the root URL `http://localhost:9000` where it is served by default, explicitly at `http://localhost:9000/minimal`, or embedded via iframe or WebView in your own applications.
## Configuration
@ -211,11 +211,11 @@ ls -la ui/suite/
ls -la ui/minimal/
# Test interfaces
curl http://localhost:8080/
curl http://localhost:8080/suite/
curl http://localhost:9000/
curl http://localhost:9000/suite/
# Check static file serving
curl http://localhost:8080/js/htmx-app.js
curl http://localhost:9000/js/htmx-app.js
```
## Customization

View file

@ -4,18 +4,38 @@ Saves data to a database table using upsert (insert or update) semantics.
## Syntax
### Form 1: Save with object (classic)
```basic
SAVE "table", id, data
```
### Form 2: Save with variables (direct)
```basic
SAVE "table", id, field1, field2, field3, ...
```
The variable names are used as column names automatically.
## Parameters
### Form 1 (with object)
| Parameter | Type | Description |
|-----------|------|-------------|
| table | String | The name of the database table |
| id | String/Number | The unique identifier for the record |
| data | Object | A map/object containing field names and values |
### Form 2 (with variables)
| Parameter | Type | Description |
|-----------|------|-------------|
| table | String | The name of the database table |
| id | String/Number | The unique identifier for the record |
| field1, field2, ... | Any | Variable references (names become column names) |
## Description
`SAVE` performs an upsert operation:
@ -24,9 +44,55 @@ SAVE "table", id, data
The `id` parameter maps to the `id` column in the table.
### Form 1 vs Form 2
**Form 1** (with object) is useful when you need custom column names or complex data structures:
```basic
data = #{
"customer_name": "João Silva",
"email": "joao@example.com"
}
SAVE "customers", "CUST-001", data
```
**Form 2** (with variables) is simpler - variable names become column names:
```basic
customerName = "João Silva"
email = "joao@example.com"
phone = "+5511999887766"
SAVE "customers", "CUST-001", customerName, email, phone
' Creates columns: customerName, email, phone
```
This eliminates the need for WITH blocks when variable names match your desired column names.
### Perfect for TOOL Functions
**This is especially useful for TOOL functions** where variables are automatically filled by user input and can be saved directly without needing WITH blocks:
```basic
' TOOL function parameters - automatically filled by LLM
PARAM nome AS STRING LIKE "João Silva" DESCRIPTION "Nome completo"
PARAM email AS EMAIL LIKE "joao@example.com" DESCRIPTION "Email"
PARAM telefone AS STRING LIKE "(21) 98888-8888" DESCRIPTION "Telefone"
' Generate unique ID
customerId = "CUST-" + FORMAT(NOW(), "yyyyMMddHHmmss")
' Save directly - variable names become column names automatically!
' No need for WITH block - just pass the variables directly
SAVE "customers", customerId, nome, email, telefone
RETURN customerId
```
In TOOL functions, the parameters (variables like `nome`, `email`, `telefone`) are automatically extracted from user input by the LLM. The direct SAVE syntax allows you to persist these variables immediately without manual object construction.
## Examples
### Basic Save with Object
### Basic Save with Object (Form 1)
```basic
' Create data object using Rhai map syntax
@ -40,32 +106,73 @@ data = #{
SAVE "customers", "CUST-001", data
```
### Save Order Data
### Save with Variables - No WITH Block Needed (Form 2)
```basic
' Variable names become column names automatically
casamentoId = "CAS-20250117-1234"
protocolo = "CAS123456"
nomeNoivo = "Carlos Eduardo"
nomeNoiva = "Juliana Cristina"
telefoneNoivo = "(21) 98888-8888"
telefoneNoiva = "(21) 97777-7777"
emailNoivo = "carlos@example.com"
emailNoiva = "juliana@example.com"
tipoCasamento = "RELIGIOSO_COM_EFEITO_CIVIL"
dataPreferencial = "2026-12-15"
horarioPreferencial = "16:00"
' Save directly without WITH block
SAVE "casamentos", casamentoId, protocolo, nomeNoivo, nomeNoiva, telefoneNoivo, telefoneNoiva, emailNoivo, emailNoiva, tipoCasamento, dataPreferencial, horarioPreferencial
```
### Save Order Data (Direct Syntax - No Object)
```basic
order_id = "ORD-" + FORMAT(NOW(), "YYYYMMDDHHmmss")
customer_id = "CUST-001"
customer_name = "João Silva"
total = 150.50
status = "pending"
order_data = #{
"customer_id": customer_id,
"customer_name": customer_name,
"total": total,
"status": "pending",
"created_at": NOW()
}
SAVE "orders", order_id, order_data
' Save directly - variable names become columns
SAVE "orders", order_id, customer_id, customer_name, total, status
TALK "Order " + order_id + " saved successfully!"
```
### Save Event Registration
```basic
' Event registration form data
eventId = "EVT-" + FORMAT(NOW(), "YYYYMMDDHHmmss")
nome = "Maria Santos"
email = "maria@example.com"
telefone = "(11) 91234-5678"
dataEvento = "2025-03-15"
quantidadePessoas = 3
observacoes = "Precisa de cadeira de rodas"
' Direct save - no WITH block needed
SAVE "eventos", eventId, nome, email, telefone, dataEvento, quantidadePessoas, observacoes
TALK "Inscrição confirmada! ID: " + eventId
```
### Update Existing Record
```basic
' If order exists, this updates it; otherwise creates it
order_id = "ORD-20250117-0001"
status = "shipped"
shipped_at = NOW()
tracking_number = "TRACK123456"
' Use object for updates to specific columns
update_data = #{
"status": "shipped",
"shipped_at": NOW(),
"tracking_number": tracking
"status": status,
"shipped_at": shipped_at,
"tracking_number": tracking_number
}
SAVE "orders", order_id, update_data
@ -79,15 +186,10 @@ WEBHOOK "new-customer"
customer_id = "CUST-" + FORMAT(NOW(), "YYYYMMDDHHmmss")
phone = body.phone
name = body.name
source = "webhook"
customer_data = #{
"name": name,
"phone": phone,
"source": "webhook",
"created_at": NOW()
}
SAVE "customers", customer_id, customer_data
' Direct save with variables
SAVE "customers", customer_id, phone, name, source
' Notify via WhatsApp
TALK TO "whatsapp:" + phone, "Welcome " + name + "! Your account has been created."
@ -121,12 +223,11 @@ WEBHOOK "create-order"
' Save order
order_id = body.order_id
order_data = #{
"customer_id": body.customer_id,
"total": body.total,
"status": "pending"
}
SAVE "orders", order_id, order_data
customer_id = body.customer_id
total = body.total
status = "pending"
SAVE "orders", order_id, customer_id, total, status
' Save each line item
FOR EACH item IN body.items
@ -146,6 +247,27 @@ TALK TO "whatsapp:" + body.customer_phone, "Order #" + order_id + " confirmed!"
result_status = "ok"
```
### Comparison: WITH Block vs Direct Syntax
**Old way (WITH block):**
```basic
WITH casamento
id = casamentoId
protocolo = protocolo
noivo = nomeNoivo
noiva = nomeNoiva
END WITH
SAVE "casamentos", casamento
```
**New way (direct):**
```basic
' Variable names become column names automatically
SAVE "casamentos", casamentoId, protocolo, nomeNoivo, nomeNoiva
```
The direct syntax is cleaner and avoids the intermediate object creation. Use it when your variable names match your desired column names.
## Return Value
Returns an object with:

View file

@ -4,11 +4,27 @@ Send email messages.
## Syntax
### Single Line
```basic
SEND MAIL to, subject, body
SEND MAIL to, subject, body USING "account@example.com"
```
### Multi-Line Block with Variable Substitution
```basic
BEGIN MAIL recipient
Subject: Email subject here
Dear ${customerName},
Your order ${orderId} is ready.
Thank you!
END MAIL
```
## Parameters
| Parameter | Type | Description |
@ -17,6 +33,7 @@ SEND MAIL to, subject, body USING "account@example.com"
| `subject` | String | Email subject line |
| `body` | String | Email body (plain text or HTML) |
| `account` | String | (Optional) Connected account to send through |
| `${variable}` | Expression | Variable substitution within MAIL blocks |
## Description
@ -25,6 +42,190 @@ The `SEND MAIL` keyword sends emails using either:
1. **Default SMTP** - Configuration from `config.csv`
2. **Connected Account** - Send through Gmail, Outlook, etc. configured in Sources app
## BEGIN MAIL / END MAIL Blocks
The `BEGIN MAIL / END MAIL` block syntax allows you to write elegant multi-line emails with automatic variable substitution using `${variable}` syntax.
### Syntax
```basic
BEGIN MAIL recipient
Subject: Email subject ${variable}
Dear ${customerName},
Your order ${orderId} has been shipped.
Tracking: ${trackingNumber}
Best regards,
The Team
END MAIL
```
### How It Works
1. **First line after `BEGIN MAIL`**: Should contain the email recipient
2. **Line starting with `Subject:`**: Email subject line (supports `${variable}`)
3. **Blank line after subject**: Separates subject from body
4. **Body lines**: Email content with automatic `${variable}` substitution
5. **Each line** is converted to string concatenation with proper newline handling
**Input:**
```basic
nome = "João"
pedido = "12345"
BEGIN MAIL "cliente@example.com"
Subject: Confirmação do Pedido ${pedido}
Olá ${nome},
Seu pedido foi confirmado!
Atenciosamente,
Equipe de Vendas
END MAIL
```
**Converted to:**
```basic
SEND MAIL "cliente@example.com", "Confirmação do Pedido 12345", "Olá " + nome + ",\n\nSeu pedido foi confirmado!\n\nAtenciosamente,\nEquipe de Vendas"
```
### Variable Substitution Rules
- `${variableName}` - Replaced with the variable value
- `${FUNCTION(args)}` - Function calls are evaluated and substituted
- Plain text without `${}` is treated as a string literal
- Special characters like `$` (not followed by `{`) are preserved
- Newlines are preserved as `\n` in the final email body
### Examples
#### Simple Email
```basic
email = "customer@example.com"
nome = "Maria"
BEGIN MAIL email
Subject: Bem-vindo ao nosso serviço!
Olá ${nome},
Obrigado por se cadastrar!
Atenciosamente,
Equipe
END MAIL
```
#### With Function Calls
```basic
BEGIN MAIL "cliente@empresa.com"
Subject: Pedido ${pedidoId} - Confirmação
Prezado ${nomeCliente},
Confirmamos seu pedido #${pedidoId} no valor de ${FORMAT(total, "currency")}.
Entrega prevista para: ${FORMAT(dataEntrega, "dd/MM/yyyy")}
Atenciosamente,
Departamento de Vendas
END MAIL
```
#### HTML Email
```basic
BEGIN MAIL "cliente@exemplo.com"
Subject: Seu pedido foi enviado!
<h1>Confirmação de Pedido</h1>
<p>Olá ${nome},</p>
<p>Seu pedido <strong>${pedidoId}</strong> foi enviado com sucesso!</p>
<p>Valor: <em>${FORMAT(valor, "currency")}</em></p>
<p>Atenciosamente,<br>Loja Virtual</p>
END MAIL
```
### Real-World Example: Wedding Confirmation
```basic
PARAM nomeNoivo AS STRING LIKE "Carlos" DESCRIPTION "Nome do noivo"
PARAM nomeNoiva AS STRING LIKE "Ana" DESCRIPTION "Nome da noiva"
PARAM emailNoivo AS EMAIL LIKE "noivo@example.com" DESCRIPTION "Email do noivo"
PARAM emailNoiva AS EMAIL LIKE "noiva@example.com" DESCRIPTION "Email da noiva"
PARAM protocolo AS STRING LIKE "CAS123456" DESCRIPTION "Protocolo"
casamentoId = "CAS-" + FORMAT(NOW(), "yyyyMMddHHmmss")
tipoTexto = "Religioso Simples"
BEGIN MAIL emailNoivo
Subject: Confirmação de Casamento - Protocolo ${protocolo}
Queridos ${nomeNoivo} e ${nomeNoiva},
Parabéns pelo compromisso de amor que estão assumindo! Recebemos a solicitação de casamento no Santuário Cristo Redentor.
DADOS DA SOLICITAÇÃO:
Protocolo: ${protocolo}
ID: ${casamentoId}
Noivo: ${nomeNoivo}
Noiva: ${nomeNoiva}
Tipo: ${tipoTexto}
Nossa equipe verificará a disponibilidade e enviará todas as instruções necessárias em breve.
Que Deus abençoe a união de vocês!
Atenciosamente,
Secretaria do Santuário Cristo Redentor
Tel: (21) 4101-0770 | WhatsApp: (21) 99566-5883
END MAIL
```
### Multiple Recipients
Send the same email to multiple people:
```basic
BEGIN MAIL "team1@company.com"
Subject: Meeting Reminder
Team meeting tomorrow at 3 PM.
END MAIL
BEGIN MAIL "team2@company.com"
Subject: Meeting Reminder
Team meeting tomorrow at 3 PM.
END MAIL
```
Or use comma-separated recipients:
```basic
recipients = "john@company.com, jane@company.com, bob@company.com"
SEND MAIL recipients, "Meeting Update", "Meeting rescheduled to 4 PM"
```
### Advantages
1. **Cleaner Syntax** - No more repetitive string concatenation for email body
2. **Easier to Read** - Multi-line emails are natural to write and maintain
3. **Template-Like** - Write emails like templates with `${variable}` placeholders
4. **Automatic Newlines** - Blank lines in the block become `\n` in the email
5. **Perfect for TOOL Functions** - Variables are automatically filled by user input
## Examples
## Configuration
Default SMTP in `config.csv`:

View file

@ -4,18 +4,31 @@ Sends a message to the current conversation or to a specific recipient on any su
## Syntax
### Single Message
```basic
TALK message
TALK TO recipient, message
```
### Multi-Line Block with Variable Substitution
```basic
BEGIN TALK
Line 1 with ${variable}
Line 2 with ${anotherVariable}
Plain text line
END TALK
```
## Parameters
| Parameter | Type | Description |
|-----------|------|-------------|
| message | String | The message to send |
| recipient | String | Channel and address in format `channel:address` |
| ${variable} | Expression | Variable substitution within TALK blocks |
## Description
@ -23,6 +36,151 @@ TALK TO recipient, message
- **TALK message** - Sends to the current conversation (web chat, WhatsApp, etc.)
- **TALK TO recipient, message** - Sends to a specific recipient on any channel
- **BEGIN TALK / END TALK** - Multi-line block with automatic variable substitution
## BEGIN TALK / END TALK Blocks
The `BEGIN TALK / END TALK` block syntax allows you to write multiple messages with automatic variable substitution using `${variable}` syntax.
### Syntax
```basic
BEGIN TALK
Hello ${name}!
Your order ${orderId} is confirmed.
Total: ${FORMAT(total, "currency")}
Thank you for your purchase!
END TALK
```
Each line within the block becomes a separate `TALK` statement. The `${variable}` syntax is automatically converted to string concatenation.
### How It Works
**Input:**
```basic
nomeNoivo = "Carlos"
protocolo = "CAS123456"
BEGIN TALK
Solicitacao de Casamento enviada com sucesso!
PROTOCOLO: ${protocolo}
Noivo: ${nomeNoivo}
END TALK
```
**Converted to:**
```basic
TALK "Solicitacao de Casamento enviada com sucesso!"
TALK "PROTOCOLO: " + protocolo
TALK "Noivo: " + nomeNoivo
```
### Variable Substitution Rules
- `${variableName}` - Replaced with the variable value using string concatenation
- `${FUNCTION(args)}` - Function calls are evaluated and substituted
- Plain text without `${}` is treated as a string literal
- Special characters like `$` (not followed by `{`) are preserved as-is
### Examples
#### Simple Substitution
```basic
nome = "João"
idade = 30
BEGIN TALK
Olá ${nome}!
Você tem ${idade} anos.
END TALK
```
**Equivalent to:**
```basic
TALK "Olá " + nome + "!"
TALK "Você tem " + idade + " anos."
```
#### With Function Calls
```basic
total = 299.90
numero = 42
BEGIN TALK
Seu pedido: ${numero}
Total: ${FORMAT(total, "currency")}
Obrigado pela preferência!
END TALK
```
#### Mixed Content
```basic
nome = "Maria"
codigo = "PROMO2024"
desconto = 20
BEGIN TALK
🎉 Oferta Especial para ${nome}!
Use o código: ${codigo}
Desconto de ${desconto}%
Aproveite!
END TALK
```
### Real-World Example: Wedding Confirmation
```basic
PARAM nomeNoivo AS STRING LIKE "Carlos" DESCRIPTION "Nome do noivo"
PARAM nomeNoiva AS STRING LIKE "Ana" DESCRIPTION "Nome da noiva"
PARAM protocolo AS STRING LIKE "CAS123456" DESCRIPTION "Protocolo"
PARAM dataCasamento AS DATE LIKE "2026-12-15" DESCRIPTION "Data do casamento"
casamentoId = "CAS-" + FORMAT(NOW(), "yyyyMMddHHmmss")
dataDisplay = FORMAT(dataCasamento, "dd/MM/yyyy")
BEGIN TALK
✅ Solicitação de Casamento enviada com sucesso!
Protocolo: ${protocolo}
ID: ${casamentoId}
Noivo: ${nomeNoivo}
Noiva: ${nomeNoiva}
Data: ${dataDisplay}
Status: Aguardando verificação de disponibilidade
Contato: (21) 4101-0770
END TALK
```
This is much cleaner than writing individual TALK statements with manual concatenation:
**Old way:**
```basic
TALK "Solicitacao de Casamento enviada com sucesso!"
TALK "Protocolo: " + protocolo
TALK "ID: " + casamentoId
TALK "Noivo: " + nomeNoivo
TALK "Noiva: " + nomeNoiva
TALK "Data: " + dataDisplay
TALK "Status: Aguardando verificacao de disponibilidade"
TALK "Contato: (21) 4101-0770"
```
### Advantages
1. **Cleaner Syntax** - No more repetitive `TALK` statements and `+` concatenations
2. **Easier to Read** - Multi-line messages are more natural to write
3. **Less Error-Prone** - Automatic substitution reduces typos in variable names
4. **Template-Like** - Write messages like templates with `${variable}` placeholders
5. **Perfect for TOOL Functions** - Variables are automatically filled by user input
## TALK - Current Conversation
## TALK - Current Conversation

View file

@ -21,7 +21,7 @@ This script works identically whether the user is:
## Supported Channels
### Web (Default)
The primary channel. Users access via browser at `http://localhost:8080`.
The primary channel. Users access via browser at `http://localhost:9000`.
### WhatsApp Business
Requires WhatsApp Business API configuration. Messages are automatically formatted for WhatsApp's constraints.

View file

@ -292,7 +292,7 @@ bot.example.com {
# WebSocket (sticky sessions)
handle /ws* {
reverse_proxy botserver-1:8080 botserver-2:8080 {
reverse_proxy botserver-1:9000 botserver-2:9000 {
lb_policy cookie
health_uri /api/health
health_interval 10s
@ -301,7 +301,7 @@ bot.example.com {
# API (round robin)
handle /api/* {
reverse_proxy botserver-1:8080 botserver-2:8080 {
reverse_proxy botserver-1:9000 botserver-2:9000 {
lb_policy round_robin
fail_duration 30s
}
@ -400,7 +400,7 @@ VAULT_ADDR=https://localhost:8200
VAULT_TOKEN=hvs.your-token-here
# Directory for user auth (Zitadel)
DIRECTORY_URL=https://localhost:8080
DIRECTORY_URL=https://localhost:9000
DIRECTORY_CLIENT_ID=your-client-id
DIRECTORY_CLIENT_SECRET=your-client-secret

View file

@ -87,7 +87,7 @@ scale-rule-queue-action,up
for i in {2..5}; do
lxc launch images:debian/12 botserver-$i
lxc config device add botserver-$i port-$((8080+i)) proxy \
listen=tcp:0.0.0.0:$((8080+i)) connect=tcp:127.0.0.1:8080
listen=tcp:0.0.0.0:$((8080+i)) connect=tcp:127.0.0.1:9000
done
```
@ -207,7 +207,7 @@ update_load_balancer() {
upstreams=""
for container in $(lxc list -c n --format csv | grep "^botserver-"); do
ip=$(lxc list $container -c 4 --format csv | cut -d' ' -f1)
upstreams="$upstreams\n to $ip:8080"
upstreams="$upstreams\n to $ip:9000"
done
# Update Caddy config
@ -268,12 +268,12 @@ bot.example.com {
# Health check endpoint (no load balancing)
handle /api/health {
reverse_proxy localhost:8080
reverse_proxy localhost:9000
}
# WebSocket connections (sticky sessions)
handle /ws* {
reverse_proxy botserver-1:8080 botserver-2:8080 botserver-3:8080 {
reverse_proxy botserver-1:9000 botserver-2:9000 botserver-3:9000 {
lb_policy cookie
lb_try_duration 5s
health_uri /api/health
@ -284,7 +284,7 @@ bot.example.com {
# API requests (round robin)
handle /api/* {
reverse_proxy botserver-1:8080 botserver-2:8080 botserver-3:8080 {
reverse_proxy botserver-1:9000 botserver-2:9000 botserver-3:9000 {
lb_policy round_robin
lb_try_duration 5s
health_uri /api/health
@ -295,7 +295,7 @@ bot.example.com {
# Static files (any instance)
handle {
reverse_proxy botserver-1:8080 botserver-2:8080 botserver-3:8080 {
reverse_proxy botserver-1:9000 botserver-2:9000 botserver-3:9000 {
lb_policy first
}
}
@ -353,7 +353,7 @@ bot.example.com {
window 1m
}
}
reverse_proxy botserver:8080
reverse_proxy botserver:9000
}
}
```

View file

@ -162,7 +162,7 @@ Use the Vault CLI or API:
```bash
# Directory (Zitadel) - includes URL, no longer in .env
vault kv put gbo/directory \
url=https://localhost:8080 \
url=https://localhost:9000 \
project_id=your-project-id \
client_id=your-client-id \
client_secret=your-client-secret
@ -506,7 +506,7 @@ If you're currently using environment variables:
```bash
# .env - TOO MANY SECRETS!
DATABASE_URL=postgres://user:password@localhost/db
DIRECTORY_URL=https://localhost:8080
DIRECTORY_URL=https://localhost:9000
DIRECTORY_CLIENT_ID=your-client-id
DIRECTORY_CLIENT_SECRET=your-client-secret
REDIS_PASSWORD=redis-secret
@ -528,7 +528,7 @@ VAULT_TOKEN=hvs.xxxxx
```bash
# EVERYTHING in Vault
vault kv put gbo/directory \
url=https://localhost:8080 \
url=https://localhost:9000 \
project_id=12345 \
client_id=xxx \
client_secret=xxx
@ -579,7 +579,7 @@ fi
# Store everything in Vault
vault kv put gbo/directory \
url="${DIRECTORY_URL:-https://localhost:8080}" \
url="${DIRECTORY_URL:-https://localhost:9000}" \
project_id="${DIRECTORY_PROJECT_ID:-}" \
client_id="${ZITADEL_CLIENT_ID:-}" \
client_secret="${ZITADEL_CLIENT_SECRET:-}"

View file

@ -9,7 +9,7 @@ This API is on the development roadmap. The endpoints documented below represent
## Base URL
```
http://localhost:8080/api/v1/admin
http://localhost:9000/api/v1/admin
```
## Authentication

View file

@ -9,7 +9,7 @@ This API is on the development roadmap. The endpoints documented below represent
## Base URL
```
http://localhost:8080/api/v1/ai
http://localhost:9000/api/v1/ai
```
## Authentication

View file

@ -9,7 +9,7 @@ This API is on the development roadmap. The endpoints documented below represent
## Base URL
```
http://localhost:8080/api/v1/analytics
http://localhost:9000/api/v1/analytics
```
## Authentication

View file

@ -9,7 +9,7 @@ This API is on the development roadmap. The endpoints documented below represent
## Base URL
```
http://localhost:8080/api/v1/backup
http://localhost:9000/api/v1/backup
```
## Authentication

View file

@ -9,7 +9,7 @@ This API is on the development roadmap. The endpoints documented below represent
## Base URL
```
http://localhost:8080/api/v1/compliance
http://localhost:9000/api/v1/compliance
```
## Authentication

View file

@ -14,7 +14,7 @@ The Document Processing API enables:
## Base URL
```
http://localhost:8080/api/v1/documents
http://localhost:9000/api/v1/documents
```
## Authentication
@ -47,7 +47,7 @@ curl -X POST \
-H "Authorization: Bearer token123" \
-F "file=@document.pdf" \
-F 'process_options={"extract_text":true,"extract_metadata":true}' \
http://localhost:8080/api/v1/documents/upload
http://localhost:9000/api/v1/documents/upload
```
**Response:**
@ -532,7 +532,7 @@ import requests
# Upload and process document
with open('document.pdf', 'rb') as f:
response = requests.post(
'http://localhost:8080/api/v1/documents/upload',
'http://localhost:9000/api/v1/documents/upload',
headers={'Authorization': 'Bearer token123'},
files={'file': f},
data={'process_options': '{"extract_text": true}'}
@ -542,7 +542,7 @@ document_id = response.json()['document_id']
# Get extracted text
text_response = requests.get(
f'http://localhost:8080/api/v1/documents/{document_id}/text',
f'http://localhost:9000/api/v1/documents/{document_id}/text',
headers={'Authorization': 'Bearer token123'}
)

View file

@ -22,7 +22,7 @@ async function authenticate() {
**cURL:**
```bash
# Session validation
curl -X GET http://localhost:8080/auth/validate \
curl -X GET http://localhost:9000/auth/validate \
-H "Authorization: Bearer YOUR_SESSION_TOKEN"
```
@ -55,7 +55,7 @@ async function createGroup() {
import requests
def create_group():
url = "http://localhost:8080/api/groups/create"
url = "http://localhost:9000/api/groups/create"
headers = {
"Authorization": "Bearer YOUR_TOKEN",
"Content-Type": "application/json"
@ -96,7 +96,7 @@ async function addMember(groupId, userId) {
**cURL:**
```bash
curl -X GET http://localhost:8080/api/admin/system/status \
curl -X GET http://localhost:9000/api/admin/system/status \
-H "Authorization: Bearer ADMIN_TOKEN"
```
@ -113,7 +113,7 @@ import (
func getSystemStatus(token string) {
client := &http.Client{}
req, _ := http.NewRequest("GET",
"http://localhost:8080/api/admin/system/status", nil)
"http://localhost:9000/api/admin/system/status", nil)
req.Header.Add("Authorization", "Bearer " + token)
resp, err := client.Do(req)
@ -164,7 +164,7 @@ class BotChat {
}
connect() {
this.ws = new WebSocket('ws://localhost:8080/ws');
this.ws = new WebSocket('ws://localhost:9000/ws');
this.ws.onopen = () => {
console.log('Connected to bot');
@ -370,7 +370,7 @@ function handleConversationCompleted(conversationData) {
1. Import the API collection (when available)
2. Set environment variables for:
- `base_url`: http://localhost:8080
- `base_url`: http://localhost:9000
- `token`: Your session token
3. Run requests individually or as collection

View file

@ -15,7 +15,7 @@ The Group Membership API enables:
## Base URL
```
http://localhost:8080/api/v1/groups
http://localhost:9000/api/v1/groups
```
## Authentication

View file

@ -9,7 +9,7 @@ This API is on the development roadmap. The endpoints documented below represent
## Base URL
```
http://localhost:8080/api/v1/ml
http://localhost:9000/api/v1/ml
```
## Authentication

View file

@ -9,7 +9,7 @@ This API is on the development roadmap. The endpoints documented below represent
## Base URL
```
http://localhost:8080/api/v1/monitoring
http://localhost:9000/api/v1/monitoring
```
## Authentication

View file

@ -14,7 +14,7 @@ The Notifications API enables:
## Base URL
```
http://localhost:8080/api/v1/notifications
http://localhost:9000/api/v1/notifications
```
## Authentication
@ -446,7 +446,7 @@ curl -X POST \
"title": "Hello",
"message": "This is a test notification"
}' \
http://localhost:8080/api/v1/notifications/send
http://localhost:9000/api/v1/notifications/send
```
### Schedule Broadcast
@ -463,7 +463,7 @@ curl -X POST \
},
"schedule": "2024-01-20T02:00:00Z"
}' \
http://localhost:8080/api/v1/notifications/broadcast
http://localhost:9000/api/v1/notifications/broadcast
```
## Best Practices

View file

@ -9,7 +9,7 @@ This API is on the development roadmap. The endpoints documented below represent
## Base URL
```
http://localhost:8080/api/v1/reports
http://localhost:9000/api/v1/reports
```
## Authentication

View file

@ -9,7 +9,7 @@ This API is on the development roadmap. The endpoints documented below represent
## Base URL
```
http://localhost:8080/api/v1/security
http://localhost:9000/api/v1/security
```
## Authentication

View file

@ -14,7 +14,7 @@ The Storage API allows you to:
## Base URL
```
http://localhost:8080/api/v1/storage
http://localhost:9000/api/v1/storage
```
## Authentication
@ -268,7 +268,7 @@ curl -X PUT \
-H "Authorization: Bearer token123" \
-H "Content-Type: application/pdf" \
--data-binary @document.pdf \
http://localhost:8080/api/v1/storage/buckets/mybot.gbai/objects/docs/manual.pdf
http://localhost:9000/api/v1/storage/buckets/mybot.gbai/objects/docs/manual.pdf
```
### Download File
@ -276,7 +276,7 @@ curl -X PUT \
```bash
curl -X GET \
-H "Authorization: Bearer token123" \
http://localhost:8080/api/v1/storage/buckets/mybot.gbai/objects/docs/manual.pdf \
http://localhost:9000/api/v1/storage/buckets/mybot.gbai/objects/docs/manual.pdf \
-o downloaded.pdf
```
@ -285,7 +285,7 @@ curl -X GET \
```bash
curl -X GET \
-H "Authorization: Bearer token123" \
"http://localhost:8080/api/v1/storage/buckets/mybot.gbai/objects?prefix=docs/"
"http://localhost:9000/api/v1/storage/buckets/mybot.gbai/objects?prefix=docs/"
```
## Storage Organization

View file

@ -15,7 +15,7 @@ The Tasks API enables:
## Base URL
```
http://localhost:8080/api/v1/tasks
http://localhost:9000/api/v1/tasks
```
## Authentication

View file

@ -15,7 +15,7 @@ The User Security API enables:
## Base URL
```
http://localhost:8080/api/v1/security
http://localhost:9000/api/v1/security
```
## Authentication

View file

@ -359,7 +359,7 @@ Register new user (if self-registration enabled).
For full user management, access Zitadel admin console:
1. **Access Console**: `http://localhost:8080` (or your Zitadel URL)
1. **Access Console**: `http://localhost:9000` (or your Zitadel URL)
2. **Create Users**: Organization → Users → Add
3. **Manage Roles**: Users → Select User → Authorizations
4. **Reset Passwords**: Users → Select User → Actions → Reset Password

View file

@ -159,7 +159,7 @@ Run General Bots on your own infrastructure with single binary deployment, conta
./botserver
```
Access at `http://localhost:8080` and start building.
Access at `http://localhost:9000` and start building.
## Summary

View file

@ -85,7 +85,7 @@ app.example.com {
| ⚠️ | Password Rotation | Directory | HIPAA | Configure 90-day rotation policy |
| 📝 | Access Reviews | Directory | All | Quarterly manual review of user permissions |
**Configuration**: Directory Admin Console (`http://localhost:8080`)
**Configuration**: Directory Admin Console (`http://localhost:9000`)
**Key Settings**:
- Password min length: 12 characters
@ -206,7 +206,7 @@ directory = "oidc"
[directory."oidc"]
type = "oidc"
issuer = "http://localhost:8080"
issuer = "http://localhost:9000"
```
**DNS Records**:

View file

@ -180,7 +180,7 @@ cargo test --all
RUSTFLAGS="-Z sanitizer=address" cargo +nightly test
# Verify rate limiting
curl -X POST http://localhost:8080/api/test \
curl -X POST http://localhost:9000/api/test \
-H "Content-Type: application/json" \
--data '{}' \
--parallel --parallel-max 1000

View file

@ -123,7 +123,7 @@ Document WebSocket protocols with connection details, message formats for both d
### Connection
```
ws://localhost:8080/ws
ws://localhost:9000/ws
```
### Message Format

View file

@ -67,7 +67,7 @@ return {
'botserver/nvim-botserver',
config = function()
require('botserver').setup({
server_url = 'http://localhost:8080',
server_url = 'http://localhost:9000',
default_bot = 'edu'
})
end

View file

@ -313,7 +313,7 @@ cargo test --all-features
3. **Port Already in Use**
- Change SERVER_PORT in .env
- Kill existing process: `lsof -i :8080`
- Kill existing process: `lsof -i :9000`
4. **Compilation Errors**
- Update Rust: `rustup update`

View file

@ -229,7 +229,7 @@ cd botserver
Open in your browser:
```
http://mybot.local:8088
http://mybot.local:9000
```
## Common Beginner Mistakes

View file

@ -83,7 +83,7 @@ wget https://huggingface.co/TheBloke/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/
--threads 4
# Verify
curl http://localhost:8080/v1/models
curl http://localhost:9000/v1/models
```
### Systemd Service
@ -127,7 +127,7 @@ sudo systemctl start llama-server
```env
# Use local llama.cpp
LLM_PROVIDER=llamacpp
LLM_API_URL=http://127.0.0.1:8080
LLM_API_URL=http://127.0.0.1:9000
LLM_MODEL=tinyllama
# Memory limits
@ -263,7 +263,7 @@ llama.cpp exposes an OpenAI-compatible API:
### Chat Completion
```bash
curl http://localhost:8080/v1/chat/completions \
curl http://localhost:9000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "tinyllama",
@ -277,7 +277,7 @@ curl http://localhost:8080/v1/chat/completions \
### Streaming
```bash
curl http://localhost:8080/v1/chat/completions \
curl http://localhost:9000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "tinyllama",
@ -289,8 +289,8 @@ curl http://localhost:8080/v1/chat/completions \
### Health Check
```bash
curl http://localhost:8080/health
curl http://localhost:8080/v1/models
curl http://localhost:9000/health
curl http://localhost:9000/v1/models
```
## Monitoring

View file

@ -231,7 +231,7 @@ BotDevice can work offline with local LLM:
1. Install botserver on the device (see [Local LLM](./local-llm.md))
2. Configure to use localhost:
```javascript
window.BOTSERVER_URL = "http://127.0.0.1:8088";
window.BOTSERVER_URL = "http://127.0.0.1:9000";
```
3. Run llama.cpp with small model (TinyLlama on 4GB+ devices)

View file

@ -22,9 +22,9 @@ cd botserver
```
That's it! After ~10-15 minutes:
- botserver runs on port 8088
- llama.cpp runs on port 8080 with TinyLlama
- Embedded UI available at `http://your-device:8088/embedded/`
- botserver runs on port 9000
- llama.cpp runs on port 8081 with TinyLlama
- Embedded UI available at `http://your-device:9000/embedded/`
## Step-by-Step Guide
@ -87,17 +87,17 @@ ssh pi@raspberrypi.local 'sudo systemctl status botserver'
ssh pi@raspberrypi.local 'sudo systemctl status llama-server'
# Test botserver
curl http://raspberrypi.local:8088/health
curl http://raspberrypi.local:9000/health
# Test llama.cpp
curl http://raspberrypi.local:8080/v1/models
curl http://raspberrypi.local:9000/v1/models
```
### Step 5: Access the Interface
Open in your browser:
```
http://raspberrypi.local:8088/embedded/
http://raspberrypi.local:9000/embedded/
```
Or set up kiosk mode (auto-starts on boot):
@ -142,11 +142,11 @@ Key settings:
```env
# Server
HOST=0.0.0.0
PORT=8088
PORT=9000
# Local LLM
LLM_PROVIDER=llamacpp
LLM_API_URL=http://127.0.0.1:8080
LLM_API_URL=http://127.0.0.1:8081
LLM_MODEL=tinyllama
# Memory limits for small devices

View file

@ -100,7 +100,7 @@ lxc config set botserver limits.memory 4GB
lxc config set botserver limits.cpu 2
# Forward ports
lxc config device add botserver http proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:8080
lxc config device add botserver http proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:9000
lxc config device add botserver https proxy listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:8443
# Set environment for Vault
@ -118,7 +118,7 @@ services:
botserver:
image: generalbots/botserver:latest
ports:
- "8080:8080"
- "8080:9000"
environment:
- VAULT_ADDR=http://vault:8200
volumes:

View file

@ -404,6 +404,7 @@ botserver rotate-secret <component>
| `email` | SMTP password |
| `directory` | Zitadel client secret |
| `encryption` | Master encryption key (⚠️ dangerous) |
| `jwt` | JWT signing secret (⚠️ invalidates refresh tokens) |
**Examples:**
@ -496,6 +497,73 @@ botserver version --all
---
## Security Considerations
### Current Limitations
⚠️ **Manual Service Updates Required**
After rotating credentials, you MUST manually update each service:
- **Database (tables):** Run the provided SQL command to update PostgreSQL user password
- **Drive (MinIO):** Run the provided `mc admin` commands to update S3 credentials
- **Cache (Redis):** Run the provided `redis-cli` command to update password
- **Directory (Zitadel):** Update client secret via admin console
⚠️ **Service Restart Required**
After rotating **JWT secret**, you MUST restart botserver:
```bash
botserver restart
```
All users will need to re-login (refresh tokens invalidated). Access tokens (15-minute expiry) will expire naturally.
⚠️ **No Automatic Rollback**
If verification fails, you must manually restore from backups:
```bash
# Database: Re-run SQL with old password
# JWT: Restore .env.backup.<timestamp>
# Other: Use backup values shown in rotation output
```
### Available Components for Rotation
| Component | Credential Type | Manual Update Required | Service Restart |
|-----------|----------------|------------------------|-----------------|
| `tables` | PostgreSQL password | ✅ Run SQL command | ❌ No |
| `drive` | MinIO S3 credentials | ✅ Run mc commands | ❌ No |
| `cache` | Redis/Valkey password | ✅ Run redis-cli | ❌ No |
| `email` | SMTP password | ✅ Update mail server | ❌ No |
| `directory` | Zitadel client secret | ✅ Update via console | ❌ No |
| `encryption` | Master encryption key | ⚠️ Re-encrypt all data | ❌ No |
| `jwt` | JWT signing secret | ❌ No | ✅ **Yes** |
### Best Practices
1. **Test in staging first** - Never rotate in production without testing
2. **Schedule during low traffic** - Rotate JWT outside peak hours
3. **Have rollback plan ready** - Save backup paths shown during rotation
4. **Monitor logs** - Check for authentication failures after rotation:
```bash
tail -f /var/log/botserver/app.log | grep -i "authentication\\|jwt\\|token"
```
5. **Rotate regularly** - Every 90 days for production, per security compliance
6. **After JWT rotation** - Verify all services are healthy before declaring success
### Verification
The `rotate-secret` command includes automatic verification where possible:
- **Database:** Tests PostgreSQL connection with new credentials
- **JWT:** Checks health endpoint (requires service to be running)
- **Other:** Displays manual verification instructions
If verification fails:
1. Check the error message for specific failure details
2. Restore from backup if needed
3. Re-run rotation after fixing the issue
---
## Complete Setup Example
Here's a complete workflow to set up Vault and migrate secrets.

View file

@ -63,7 +63,7 @@ ss -tlnp | grep LISTEN
1. **Port already in use**
```bash
# Find what's using the port
lsof -i :8080
lsof -i :9000
lsof -i :5432
# Kill conflicting process

View file

@ -14,7 +14,7 @@ The Security Protection module provides comprehensive host-level security throug
▼ HTMX/API calls
┌─────────────────────────────────────────────────────────────┐
│ botserver (port 8088) │
│ botserver (port 9000) │
│ /api/security/protection/* │
└─────────────────────────────────────────────────────────────┘

View file

@ -79,7 +79,7 @@
<text x="80" y="20" text-anchor="middle" font-size="11" font-weight="600" class="white-text">botserver</text>
<text x="80" y="55" text-anchor="middle" font-size="10" class="main-text">(Rust)</text>
<text x="80" y="72" text-anchor="middle" font-size="10" font-weight="500" class="main-text">Port 8088</text>
<text x="80" y="72" text-anchor="middle" font-size="10" font-weight="500" class="main-text">Port 9000</text>
<text x="80" y="95" text-anchor="middle" font-size="9" class="mono-text">ARM64 Binary</text>
</g>

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

View file

@ -90,7 +90,7 @@
<text x="85" y="52" text-anchor="middle" font-size="10" class="main-text">Rust Runtime</text>
<text x="85" y="68" text-anchor="middle" font-size="9" class="mono-text">Session Manager</text>
<text x="85" y="84" text-anchor="middle" font-size="9" class="mono-text">Port 8088</text>
<text x="85" y="84" text-anchor="middle" font-size="9" class="mono-text">Port 9000</text>
</g>
<!-- Arrow 2 -->

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View file

@ -46,7 +46,7 @@
<g transform="translate(320, 80)">
<rect width="240" height="280" rx="10" fill="#E8F5E9" stroke="#388E3C" stroke-width="2"/>
<text x="120" y="30" text-anchor="middle" class="box-label">botserver (Rust)</text>
<text x="120" y="50" text-anchor="middle" class="small-text">Port 8088</text>
<text x="120" y="50" text-anchor="middle" class="small-text">Port 9000</text>
<rect x="20" y="70" width="200" height="40" rx="4" fill="#C8E6C9" stroke="#388E3C"/>
<text x="120" y="95" text-anchor="middle" class="small-text">BASIC Interpreter</text>
<rect x="20" y="120" width="200" height="40" rx="4" fill="#C8E6C9" stroke="#388E3C"/>

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View file

@ -299,7 +299,7 @@ Or continue reading for the full journey:
<div class="wa-bubble">
<p>Great! Just run:</p>
<p><code>./botserver</code></p>
<p>Then open http://localhost:8080</p>
<p>Then open http://localhost:9000</p>
<p>That's it! 🚀</p>
<div class="wa-time">09:00</div>
</div>

View file

@ -250,7 +250,7 @@ chmod +x botserver
### 2. Open Browser
```
http://localhost:8080
http://localhost:9000
```
### 3. Start Chatting