Files
pulse/Claude.md

1372 lines
31 KiB
Markdown
Raw Normal View History

2026-01-07 19:57:16 -05:00
# PULSE - Pipelined Unified Logic & Server Engine
## Project Overview
PULSE is a distributed workflow orchestration platform designed for managing and executing complex multi-step operations across server clusters. It provides a centralized web-based control center for defining, managing, and executing workflows that can span multiple servers, require human interaction, and perform complex automation tasks at scale.
### Core Objectives
- Orchestrate operations across distributed infrastructure
- Enable interactive workflows with user prompts and conditional logic
- Provide high availability through redundant worker nodes
- Offer real-time monitoring and execution tracking
- Support both simple command execution and complex multi-step workflows
## Architecture
### System Components
#### 1. PULSE Server (Web Server)
**Location:** `10.10.10.65` (LXC Container ID: 122)
**Directory:** `/opt/pulse-server`
The central orchestration hub that:
- Hosts the web interface for workflow management
- Manages workflow definitions and execution state
- Coordinates task distribution to worker nodes
- Handles user interactions via Authelia SSO
- Provides real-time status updates via WebSocket
- Stores all data in MariaDB database
**Technology Stack:**
- Node.js 20.x
- Express.js (web framework)
- WebSocket (ws package) for real-time communication
- MySQL2 (database driver for MariaDB)
- Bcryptjs (password hashing, legacy)
- Jsonwebtoken (JWT tokens, legacy)
- Crypto (Node.js built-in for UUIDs)
**Key Files:**
- `server.js` - Main server application
- `public/index.html` - Web dashboard UI
- `.env` - Environment configuration (NOT in git)
- `package.json` - Dependencies
- `.gitignore` - Excludes secrets and node_modules
#### 2. PULSE Worker Nodes
**Example:** `10.10.10.151` (LXC Container ID: 153, hostname: pulse-worker-01)
**Directory:** `/opt/pulse-worker`
Lightweight execution agents that:
- Connect to PULSE server via HTTP and WebSocket
- Execute commands, scripts, and workflows on target infrastructure
- Report execution status and results back to server
- Send heartbeat with system metrics every 30 seconds
- Support multiple concurrent workflow executions
- Auto-reconnect on connection loss
**Technology Stack:**
- Node.js 20.x
- Axios (HTTP client)
- WebSocket (ws package)
- Child_process (command execution)
- OS module (system metrics)
**Key Files:**
- `worker.js` - Main worker agent
- `.env` - Worker configuration (NOT in git)
- `package.json` - Dependencies
#### 3. MariaDB Database
**Location:** `10.10.10.50:3306`
**Database:** `pulse`
**User:** `pulse_user` (access from 10.10.10.65 only)
**Password:** `ZE6BuNtBG6P&g*gDpZRY`
**Tables:**
```sql
-- Users table (SSO managed)
CREATE TABLE users (
id VARCHAR(36) PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
display_name VARCHAR(255),
email VARCHAR(255),
groups TEXT,
last_login TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Worker nodes
CREATE TABLE workers (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL,
status VARCHAR(50) NOT NULL,
last_heartbeat TIMESTAMP NULL,
api_key VARCHAR(255),
metadata JSON,
INDEX idx_status (status),
INDEX idx_heartbeat (last_heartbeat)
);
-- Workflow definitions
CREATE TABLE workflows (
id VARCHAR(36) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
definition JSON NOT NULL,
created_by VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_name (name)
);
-- Workflow executions
CREATE TABLE executions (
id VARCHAR(36) PRIMARY KEY,
workflow_id VARCHAR(36) NOT NULL,
status VARCHAR(50) NOT NULL,
started_by VARCHAR(255),
started_at TIMESTAMP NULL,
completed_at TIMESTAMP NULL,
logs JSON,
FOREIGN KEY (workflow_id) REFERENCES workflows(id) ON DELETE CASCADE,
INDEX idx_workflow (workflow_id),
INDEX idx_status (status),
INDEX idx_started (started_at)
);
```
#### 4. Authentication System
**LLDAP Server:** `10.10.10.39:3890`
**Authelia Server:** `10.10.10.39:9091`
**Auth Domain:** `auth.lotusguild.org`
**Authentication Flow:**
1. User accesses `https://pulse.lotusguild.org`
2. Nginx Proxy Manager forwards auth check to Authelia
3. If not authenticated, redirect to `auth.lotusguild.org`
4. User logs in via LLDAP (admin/employee groups)
5. Authelia sets headers and redirects back to PULSE
6. PULSE trusts headers: `Remote-User`, `Remote-Name`, `Remote-Email`, `Remote-Groups`
7. User session is auto-created/updated in database
**Allowed Groups:**
- `admin` - Full access including delete operations
- `employee` - Standard access, can execute workflows
#### 5. Deployment Pipeline
**Git Repository:** `https://code.lotusguild.org/LotusGuild/pulse`
**Webhook Endpoint:** `http://10.10.10.65:9000/hooks/pulse-deploy`
**Webhook Secret:** `c0dd85e473d0efdd3653b77bb38408b14015e7e020e59ad7d446b6c1fab1940d`
**Deployment Flow:**
1. Developer pushes code to Gitea
2. Gitea triggers webhook with SHA256 signature
3. Webhook service validates signature
4. Deployment script `/usr/local/bin/pulse_deploy.sh` runs
5. Script backs up `.env`, pulls latest code, restores `.env`
6. Installs dependencies with `npm install --production`
7. Restarts PULSE service via systemd
8. Verifies service is running
**Deployment Script Location:** `/usr/local/bin/pulse_deploy.sh`
**Webhook Config:** `/etc/webhook/hooks.json`
**Webhook Service:** `systemd` service on port 9000
## API Endpoints
### Authentication (SSO via Authelia)
All API endpoints require SSO authentication via Authelia headers.
### User Management
- `GET /api/user` - Get current user info (SSO headers)
### Workers
- `GET /api/workers` - List all workers
- `POST /api/workers/heartbeat` - Worker heartbeat (requires `X-API-Key` header)
- `DELETE /api/workers/:id` - Delete worker (admin only)
- `POST /api/workers/:id/command` - Send direct command to worker
### Workflows
- `GET /api/workflows` - List all workflows
- `POST /api/workflows` - Create new workflow
- `DELETE /api/workflows/:id` - Delete workflow (admin only)
### Executions
- `GET /api/executions` - List all executions (recent 50)
- `POST /api/executions` - Start workflow execution
- `GET /api/executions/:id` - Get execution details with logs
- `POST /api/executions/:id/respond` - Respond to workflow prompt
### Health
- `GET /health` - Health check (no auth required)
## Workflow Definition Format
Workflows are defined in JSON format with the following structure:
```json
{
"steps": [
{
"name": "Step Name",
"type": "execute|prompt|wait",
"targets": ["all", "worker-name", "worker-group"],
"command": "shell command to execute",
"condition": "JavaScript expression",
"timeout": 300000,
"message": "Prompt message for user",
"options": ["Yes", "No", "Cancel"],
"duration": 5000
}
]
}
```
### Step Types
#### 1. Execute Step
Executes a shell command on target workers.
```json
{
"name": "Update packages",
"type": "execute",
"targets": ["all"],
"command": "apt update && apt upgrade -y",
"timeout": 600000
}
```
**Fields:**
- `name` - Step description
- `type` - Must be "execute"
- `targets` - Array of worker names or ["all"]
- `command` - Shell command to execute
- `timeout` - Timeout in milliseconds (default: 300000)
- `condition` - Optional JavaScript condition to evaluate
#### 2. Prompt Step
Pauses workflow and prompts user for input.
```json
{
"name": "User confirmation",
"type": "prompt",
"message": "Proceed with system reboot?",
"options": ["Yes", "No", "Cancel"]
}
```
**Fields:**
- `name` - Step description
- `type` - Must be "prompt"
- `message` - Message to display to user
- `options` - Array of options for user to choose from
The user's response is stored in `promptResponse` variable for use in conditions.
#### 3. Wait Step
Delays execution for a specified duration.
```json
{
"name": "Wait for services",
"type": "wait",
"duration": 10000
}
```
**Fields:**
- `name` - Step description
- `type` - Must be "wait"
- `duration` - Delay in milliseconds
### Conditions
Steps can have optional conditions that determine if they should execute:
```json
{
"name": "Reboot servers",
"type": "execute",
"command": "reboot",
"condition": "promptResponse === 'Yes'"
}
```
Conditions are JavaScript expressions evaluated in the workflow context. Available variables:
- `promptResponse` - The most recent user prompt response
- `state` - The full execution state object
### Example Workflows
#### Simple Command Execution
```json
{
"steps": [
{
"name": "Check disk space",
"type": "execute",
"targets": ["all"],
"command": "df -h"
}
]
}
```
#### Interactive System Update
```json
{
"steps": [
{
"name": "Update package list",
"type": "execute",
"targets": ["all"],
"command": "apt update"
},
{
"name": "User approval",
"type": "prompt",
"message": "Packages updated. Proceed with upgrade?",
"options": ["Yes", "No"]
},
{
"name": "Upgrade packages",
"type": "execute",
"targets": ["all"],
"command": "apt upgrade -y",
"condition": "promptResponse === 'Yes'"
},
{
"name": "Reboot confirmation",
"type": "prompt",
"message": "Upgrade complete. Reboot servers?",
"options": ["Yes", "No"]
},
{
"name": "Reboot servers",
"type": "execute",
"targets": ["all"],
"command": "reboot",
"condition": "promptResponse === 'Yes'"
}
]
}
```
#### Backup with Verification
```json
{
"steps": [
{
"name": "Create backup",
"type": "execute",
"targets": ["all"],
"command": "tar -czf /tmp/backup-$(date +%Y%m%d).tar.gz /opt/pulse-worker"
},
{
"name": "Wait for backup",
"type": "wait",
"duration": 5000
},
{
"name": "Verify backup",
"type": "execute",
"targets": ["all"],
"command": "tar -tzf /tmp/backup-*.tar.gz > /dev/null && echo 'OK' || echo 'FAILED'"
},
{
"name": "Cleanup decision",
"type": "prompt",
"message": "Backup complete. Delete old backups?",
"options": ["Yes", "No"]
},
{
"name": "Cleanup old backups",
"type": "execute",
"targets": ["all"],
"command": "find /tmp -name 'backup-*.tar.gz' -mtime +7 -delete",
"condition": "promptResponse === 'Yes'"
}
]
}
```
## WebSocket Protocol
### Client → Server Messages
#### Worker Connection
```json
{
"type": "worker_connect",
"worker_id": "uuid",
"worker_name": "pulse-worker-01"
}
```
#### Command Result
```json
{
"type": "command_result",
"execution_id": "uuid",
"worker_id": "uuid",
"success": true,
"stdout": "command output",
"stderr": "",
"duration": 1234,
"timestamp": "2025-11-30T12:00:00Z"
}
```
#### Workflow Result
```json
{
"type": "workflow_result",
"execution_id": "uuid",
"worker_id": "uuid",
"success": true,
"message": "Workflow completed",
"timestamp": "2025-11-30T12:00:00Z"
}
```
#### Pong Response
```json
{
"type": "pong",
"worker_id": "uuid"
}
```
### Server → Client Messages
#### Execute Command
```json
{
"type": "execute_command",
"execution_id": "uuid",
"step_index": 0,
"command": "uptime",
"timeout": 300000,
"worker_id": "uuid"
}
```
#### Execute Workflow
```json
{
"type": "execute_workflow",
"execution_id": "uuid",
"workflow": {
"name": "Workflow Name",
"steps": [...]
}
}
```
#### Ping
```json
{
"type": "ping"
}
```
#### Broadcast Messages
```json
{
"type": "worker_update",
"worker_id": "uuid",
"status": "online"
}
```
```json
{
"type": "workflow_created",
"workflow_id": "uuid"
}
```
```json
{
"type": "execution_started",
"execution_id": "uuid",
"workflow_id": "uuid"
}
```
```json
{
"type": "execution_prompt",
"execution_id": "uuid",
"prompt": {
"message": "Proceed?",
"options": ["Yes", "No"],
"step": 2
}
}
```
```json
{
"type": "execution_status",
"execution_id": "uuid",
"status": "completed"
}
```
## Environment Variables
### PULSE Server (.env)
```bash
# Server Configuration
PORT=8080
HOST=0.0.0.0
SECRET_KEY=change-this-to-a-secure-random-string
# MariaDB Configuration
DB_HOST=10.10.10.50
DB_PORT=3306
DB_NAME=pulse
DB_USER=pulse_user
DB_PASSWORD=ZE6BuNtBG6P&g*gDpZRY
# Worker API Key (for worker authentication)
WORKER_API_KEY=5709f45547622803ad0af4726e43aea3aa3f412b25ca5df0c5a0da7929579c53
NODE_ENV=production
```
### PULSE Worker (.env)
```bash
# PULSE Server Configuration
PULSE_SERVER=http://10.10.10.65:8080
PULSE_WS=ws://10.10.10.65:8080
# Worker Configuration
WORKER_NAME=pulse-worker-01
WORKER_API_KEY=5709f45547622803ad0af4726e43aea3aa3f412b25ca5df0c5a0da7929579c53
# Heartbeat interval (seconds)
HEARTBEAT_INTERVAL=30
# Max concurrent tasks
MAX_CONCURRENT_TASKS=5
```
## Infrastructure Details
### LXC Container Specifications
#### PULSE Server (ID: 122)
- **OS:** Debian 13 (Trixie)
- **Hostname:** pulse-web-server
- **IP:** 10.10.10.65
- **Storage:** 8GB on Ceph pool (appPool)
- **RAM:** 4096 MiB
- **CPU:** 4 cores
- **Container Type:** Unprivileged
- **Features:** Standard (no nesting, no FUSE)
- **Network:** vmbr0 bridge, DHCP (static assignment via router)
#### PULSE Worker (ID: 153)
- **OS:** Debian 13 (Trixie)
- **Hostname:** pulse-worker-01
- **IP:** 10.10.10.151 (originally 10.10.10.189, changed via DHCP)
- **Storage:** 8GB on Ceph pool (appPool)
- **RAM:** 512 MiB
- **CPU:** 1 core
- **Container Type:** Unprivileged
- **Features:** Standard
- **Network:** vmbr0 bridge, DHCP
### Proxmox Cluster
- **Ceph Storage:** High availability distributed storage
- **Backend:** Ceph RBD
- **Pools:** appPool (containers), mediafs (templates)
- **Replication:** Data replicated across cluster nodes
### Nginx Proxy Manager Configuration
**Domain:** `pulse.lotusguild.org`
**Proxy Host Settings:**
- Scheme: http
- Forward Hostname/IP: 10.10.10.65
- Forward Port: 8080
- Cache Assets: Yes
- Block Common Exploits: Yes
- Websockets Support: Yes
- Force SSL: Yes
- HTTP/2 Support: Yes
**Custom Nginx Configuration:**
```nginx
include /snippets/authelia-location.conf;
location / {
add_header Strict-Transport-Security $hsts_header always;
# Authelia auth check
auth_request /authelia;
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
# Pass auth headers to backend
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-Email $email;
# Redirect to login on 401
error_page 401 =302 https://auth.lotusguild.org/?rd=$scheme://$http_host$request_uri;
# Websockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
# Standard proxy headers
include /etc/nginx/conf.d/include/proxy.conf;
}
```
### Authelia Configuration
**Location:** Authelia server `/etc/authelia/configuration.yml`
**PULSE Access Rule:**
```yaml
access_control:
rules:
# ... other rules ...
# PULSE Workflow Orchestration
- domain: pulse.lotusguild.org
policy: one_factor
subject:
- group:admin
- group:employee
```
**LDAP Backend:**
- Server: `ldap://10.10.10.39:3890`
- User: `uid=autheliaapplication,ou=people,dc=example,dc=com`
- Base DN: `dc=example,dc=com`
- Users DN: `ou=people`
- Groups DN: `ou=groups`
### Gitea Webhook Configuration
**Gitea Server Configuration:**
```ini
[webhook]
ALLOWED_HOST_LIST = 10.10.10.0/24
```
**Repository Webhook:**
- URL: `http://10.10.10.65:9000/hooks/pulse-deploy`
- Method: POST
- Content Type: application/json
- Secret: `c0dd85e473d0efdd3653b77bb38408b14015e7e020e59ad7d446b6c1fab1940d`
- Trigger: Push events on main branch
- Active: Yes
## Systemd Services
### PULSE Server
**Service File:** `/etc/systemd/system/pulse.service`
```ini
[Unit]
Description=PULSE Workflow Orchestration Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/pulse-server
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
**Commands:**
```bash
systemctl daemon-reload
systemctl enable pulse
systemctl start pulse
systemctl status pulse
journalctl -u pulse -f
```
### PULSE Worker
**Service File:** `/etc/systemd/system/pulse-worker.service`
```ini
[Unit]
Description=PULSE Worker Agent
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/pulse-worker
ExecStart=/usr/bin/node worker.js
Restart=always
RestartSec=10
LimitNOFILE=65536
[Install]
WantedBy=multi-user.target
```
**Commands:**
```bash
systemctl daemon-reload
systemctl enable pulse-worker
systemctl start pulse-worker
systemctl status pulse-worker
journalctl -u pulse-worker -f
```
### Webhook Service
**Service File:** `/etc/systemd/system/webhook.service`
```ini
[Unit]
Description=Webhook Listener for Auto Deploy
After=network.target
[Service]
ExecStart=/usr/bin/webhook -hooks /etc/webhook/hooks.json -port 9000 -verbose
Restart=always
User=root
[Install]
WantedBy=multi-user.target
```
**Webhook Configuration:** `/etc/webhook/hooks.json`
```json
[
{
"id": "pulse-deploy",
"execute-command": "/usr/local/bin/pulse_deploy.sh",
"command-working-directory": "/opt/pulse-server",
"response-message": "Deploying PULSE server...",
"trigger-rule": {
"match": {
"type": "payload-hash-sha256",
"secret": "c0dd85e473d0efdd3653b77bb38408b14015e7e020e59ad7d446b6c1fab1940d",
"parameter": {
"source": "header",
"name": "X-Gitea-Signature"
}
}
}
}
]
```
**Commands:**
```bash
systemctl daemon-reload
systemctl enable webhook
systemctl start webhook
systemctl status webhook
journalctl -u webhook -f
```
## Development Workflow
### Making Changes to PULSE Server
1. **SSH into server or work locally:**
```bash
ssh root@10.10.10.65
cd /opt/pulse-server
```
2. **Make changes to code:**
```bash
nano server.js
# or
nano public/index.html
```
3. **Test changes locally:**
```bash
systemctl restart pulse
systemctl status pulse
journalctl -u pulse -f
```
4. **Commit and push:**
```bash
git add .
git commit -m "Description of changes"
git push
```
5. **Automatic deployment happens:**
- Gitea webhook triggers
- Deployment script runs
- Service restarts automatically
- Check logs: `journalctl -u webhook -f`
### Making Changes to PULSE Worker
1. **SSH into worker:**
```bash
ssh root@10.10.10.151
cd /opt/pulse-worker
```
2. **Make changes:**
```bash
nano worker.js
```
3. **Restart service:**
```bash
systemctl restart pulse-worker
systemctl status pulse-worker
journalctl -u pulse-worker -f
```
4. **If adding to git (future):**
- Workers could be deployed from a separate repo
- Or use same repo with different directory
### Adding Dependencies
**Server:**
```bash
cd /opt/pulse-server
npm install <package-name>
git add package.json package-lock.json
git commit -m "Add dependency: <package-name>"
git push
```
**Worker:**
```bash
cd /opt/pulse-worker
npm install <package-name>
# Manual restart required (not in git yet)
systemctl restart pulse-worker
```
## Troubleshooting
### Server Won't Start
1. **Check logs:**
```bash
journalctl -u pulse -xeu
```
2. **Common issues:**
- Database connection failed: Check MariaDB is running and credentials
- Port 8080 already in use: Check for other processes
- Missing .env file: Restore from backup or recreate
3. **Test manually:**
```bash
cd /opt/pulse-server
node server.js
```
### Worker Won't Connect
1. **Check logs:**
```bash
journalctl -u pulse-worker -f
```
2. **Common issues:**
- Wrong server URL in .env: Should be `http://10.10.10.65:8080`
- Wrong API key: Must match server's WORKER_API_KEY
- Network issue: Check firewall and connectivity
3. **Test connection manually:**
```bash
curl http://10.10.10.65:8080/health
```
4. **Test heartbeat:**
```bash
cd /opt/pulse-worker
node -e "
const axios = require('axios');
const crypto = require('crypto');
axios.post('http://10.10.10.65:8080/api/workers/heartbeat', {
worker_id: crypto.randomUUID(),
name: 'test',
metadata: {}
}, {
headers: {'X-API-Key': '5709f45547622803ad0af4726e43aea3aa3f412b25ca5df0c5a0da7929579c53'}
}).then(() => console.log('OK')).catch(err => console.error(err.message));
"
```
### Authentication Issues
1. **Can't access web interface:**
- Check Authelia is running
- Verify you're in admin or employee group in LLDAP
- Check Nginx Proxy Manager configuration
- Try accessing directly: `http://10.10.10.65:8080/health`
2. **Check auth headers:**
```bash
curl -H "Remote-User: testuser" \
-H "Remote-Groups: admin" \
http://10.10.10.65:8080/api/user
```
### Database Issues
1. **Can't connect to database:**
```bash
# From server
cd /opt/pulse-server
node -e "
const mysql = require('mysql2/promise');
(async () => {
try {
const pool = mysql.createPool({
host: '10.10.10.50',
user: 'pulse_user',
password: 'ZE6BuNtBG6P&g*gDpZRY',
database: 'pulse'
});
await pool.query('SELECT 1');
console.log('✓ Database connection OK');
await pool.end();
} catch (err) {
console.error('✗ Database error:', err.message);
}
})();
"
```
2. **Inspect database:**
```bash
# Install mysql client first
apt install default-mysql-client
mysql -h 10.10.10.50 -u pulse_user -p'ZE6BuNtBG6P&g*gDpZRY' pulse
# Run queries
SHOW TABLES;
SELECT * FROM workers;
SELECT * FROM workflows;
SELECT * FROM executions ORDER BY started_at DESC LIMIT 10;
```
### Deployment Issues
1. **Webhook not triggering:**
- Check webhook service: `systemctl status webhook`
- Check Gitea webhook configuration
- Verify secret matches in both places
- Check webhook logs: `journalctl -u webhook -f`
2. **Deployment fails:**
- Check deployment script: `/usr/local/bin/pulse_deploy.sh`
- Check git connectivity from server
- Verify .env file is preserved
3. **Manual deployment:**
```bash
/usr/local/bin/pulse_deploy.sh
```
## Security Considerations
### Secrets Management
**NEVER commit these to git:**
- `.env` files (both server and worker)
- Database passwords
- API keys
- Webhook secrets
- SSH keys
**Protected by .gitignore:**
```
.env
.env.local
.env.*.local
*.db
*.sqlite
*.backup
node_modules/
```
### Network Security
- **Worker API Key:** All worker heartbeats require valid API key
- **SSO Authentication:** All web access requires Authelia login
- **Group Authorization:** Only admin/employee groups can access
- **Database Access:** Restricted to 10.10.10.65 only
- **Internal Network:** All communication on private 10.10.10.0/24
### Access Control
**Admin users can:**
- Create/delete workflows
- Execute workflows
- Delete workers
- View all executions
**Employee users can:**
- Execute workflows
- View workflows
- View workers
- View executions
### Recommended Practices
1. **Rotate secrets regularly:**
- Worker API key every 90 days
- Webhook secret every 90 days
- Database passwords every 180 days
2. **Monitor access:**
- Review Authelia logs for suspicious activity
- Check worker connections regularly
- Monitor execution logs for anomalies
3. **Backup strategy:**
- Database: Regular mysqldump backups
- .env files: Secure backup location
- Workflow definitions: Stored in database (backed up with DB)
4. **LXC container security:**
- Unprivileged containers
- Regular OS updates via apt
- Minimal installed packages
- No SSH access (console access only via Proxmox)
## Monitoring and Maintenance
### Health Checks
**Server health:**
```bash
curl http://10.10.10.65:8080/health
```
**Expected response:**
```json
{
"status": "ok",
"timestamp": "2025-11-30T12:00:00.000Z",
"database": "connected",
"auth": "authelia-sso"
}
```
### Log Monitoring
**Real-time logs:**
```bash
# Server
journalctl -u pulse -f
# Worker
journalctl -u pulse-worker -f
# Webhook
journalctl -u webhook -f
```
**Log analysis:**
```bash
# Last 100 lines
journalctl -u pulse -n 100
# Since specific time
journalctl -u pulse --since "1 hour ago"
# Errors only
journalctl -u pulse -p err
```
### Resource Monitoring
**Worker metrics:**
- Dashboard shows CPU, memory, load average
- Heartbeat includes system metrics
- Check worker status every 30 seconds
### Performance Tuning
**Server optimization:**
- Node.js runs single-threaded by default
- Consider PM2 for clustering if needed
- WebSocket connections scale to ~10k per process
- Database connection pool: 10 connections
**Worker optimization:**
- Workers limit concurrent tasks (default: 5)
- Adjust MAX_CONCURRENT_TASKS based on worker resources
- Monitor CPU and memory usage
- Consider worker groups for task distribution
### Maintenance Tasks
**Weekly:**
- Review worker health and remove dead workers
- Check execution logs for failures
- Monitor database growth
**Monthly:**
- Review and clean old execution logs
- Check for outdated workflow definitions
- Update dependencies (security patches)
- Review Authelia access logs
**Quarterly:**
- Rotate secrets (API keys, webhook secrets)
- Review and optimize workflows
- Backup database
- Test disaster recovery procedures
## Future Enhancements
### Planned Features
1. **Workflow Scheduler:**
- Cron-like scheduling for workflows
- Recurring execution support
- Time-based triggers
2. **Advanced Worker Management:**
- Worker groups and tags
- Resource-based task assignment
- Worker health monitoring
- Auto-scaling capabilities
3. **Enhanced Execution Engine:**
- Parallel step execution
- Step dependencies and DAGs
- Retry logic with backoff
- Execution templates
4. **Notification System:**
- Email notifications on completion/failure
- Slack/Discord webhooks
- Custom notification handlers
5. **Audit and Compliance:**
- Detailed audit logs
- Execution history retention policies
- Compliance reporting
6. **UI Enhancements:**
- Visual workflow builder (drag-and-drop)
- Real-time execution viewer
- Execution comparison and diff
- Mobile-responsive design improvements
7. **API Improvements:**
- GraphQL API
- REST API versioning
- API rate limiting
- API documentation (Swagger/OpenAPI)
8. **Advanced Workflows:**
- Conditional workflows (if/else)
- Loops and iterations
- Error handling and rollback
- Workflow composition (call workflows from workflows)
9. **Security Enhancements:**
- Workflow approval system
- Execution authorization per workflow
- Secret management integration (Vault)
- Command whitelisting
10. **Monitoring & Observability:**
- Prometheus metrics export
- Grafana dashboards
- Distributed tracing
- Performance profiling
### Scaling Considerations
**Horizontal Scaling:**
- Multiple PULSE servers behind load balancer
- Redis for shared state and WebSocket pub/sub
- Database read replicas
- Worker auto-scaling based on queue depth
**Vertical Scaling:**
- Increase server resources (CPU/RAM)
- Optimize database queries and indexes
- Implement caching layer
- Worker resource allocation tuning
### Migration Path
**To Kubernetes:**
- Containerize PULSE server and workers
- Use Helm charts for deployment
- Implement StatefulSets for database
- ConfigMaps for configuration
- Secrets for sensitive data
**To High Availability:**
- Active-active PULSE servers
- PostgreSQL with replication
- Redis cluster for session storage
- Load balancer with health checks
- Shared storage for artifacts
## Contributing
### Development Setup
1. **Clone repository:**
```bash
git clone https://code.lotusguild.org/LotusGuild/pulse.git
cd pulse
```
2. **Install dependencies:**
```bash
npm install
```
3. **Create .env file:**
```bash
cp .env.example .env
# Edit .env with your configuration
```
4. **Run locally:**
```bash
node server.js
```
5. **Access dashboard:**
```
http://localhost:8080
```
### Code Style
- **JavaScript:** ES6+ syntax
- **Indentation:** 2 spaces
- **Quotes:** Single quotes preferred
- **Semicolons:** Required
- **Naming:** camelCase for variables, PascalCase for classes
### Testing
**Manual testing checklist:**
- [ ] Worker connects and sends heartbeat
- [ ] Workflow creation succeeds
- [ ] Workflow execution starts
- [ ] Commands execute on workers
- [ ] User prompts display correctly
- [ ] WebSocket real-time updates work
- [ ] Authentication via Authelia works
- [ ] Worker deletion works (admin only)
- [ ] Database queries are efficient
### Pull Request Process
1. Create feature branch: `git checkout -b feature/my-feature`
2. Make changes and commit: `git commit -m "Add feature"`
3. Push to Gitea: `git push origin feature/my-feature`
4. Create pull request in Gitea
5. Wait for review and approval
6. Merge to main branch
7. Automatic deployment via webhook
## Support and Resources
### Documentation
- **Main README:** `/opt/pulse-server/README.md`
- **This Guide:** `Claude.md`
- **Authelia Docs:** https://www.authelia.com/docs/
- **LLDAP Docs:** https://github.com/lldap/lldap
### Logging Locations
- **PULSE Server:** `journalctl -u pulse`
- **PULSE Worker:** `journalctl -u pulse-worker`
- **Webhook:** `journalctl -u webhook`
- **Nginx:** `/var/log/nginx/`
- **Authelia:** Check Authelia container logs
### Common Commands Reference
```bash
# Server Management
systemctl status pulse
systemctl restart pulse
systemctl stop pulse
systemctl start pulse
journalctl -u pulse -f
# Worker Management
systemctl status pulse-worker
systemctl restart pulse-worker
journalctl -u pulse-worker -f
# Deployment
/usr/local/bin/pulse_deploy.sh
journalctl -u webhook -f
git status
git log --oneline -10
# Database
mysql -h 10.10.10.50 -u pulse_user -p'ZE6BuNtBG6P&g*gDpZRY' pulse
# Health Checks
curl http://10.10.10.65:8080/health
curl https://pulse.lotusguild.org/health
# Container Management (from Proxmox host)
pct list
pct status 122
pct status 153
pct enter 122
pct enter 153
```
## Glossary
- **PULSE:** Pipelined Unified Logic & Server Engine - the name of this orchestration platform
- **Worker:** An agent node that executes commands and workflows
- **Workflow:** A defined sequence of steps to accomplish a task
- **Execution:** An instance of a workflow being run
- **Step:** A single action within a workflow (execute, prompt, wait)
- **Heartbeat:** Periodic status update from worker to server
- **LXC:** Linux Container - lightweight virtualization
- **Ceph:** Distributed storage system
- **Authelia:** SSO authentication server
- **LLDAP:** Lightweight LDAP server for user management
- **Gitea:** Self-hosted Git service
- **Webhook:** HTTP callback triggered by events (like git push)
- **SSO:** Single Sign-On - authentication system
- **MariaDB:** MySQL-compatible database server
## Version History
- **v1.0.0** (2025-11-30) - Initial release
- Basic workflow orchestration
- Worker management
- Authelia SSO integration
- Web dashboard
- Git deployment pipeline
- Interactive workflows with prompts
- Command execution on workers
---
**Last Updated:** November 30, 2025
**Project Status:** Active Development
**License:** Internal - Lotus Guild
**Maintainer:** Jared (jared@lotusguild.org)</parameter>