Files
nuc/.artifacts/2026-02-16_22-30_openclaw-upgrade-protection.md
Alejandro Gutiérrez 1aa7ebcde3 Add AI gateway and WhatsApp integration artifacts (Feb 12-17)
OpenClaw setup, Arrio deployment, WhatsApp MCP server, DNS/Traefik
entries, communication style prompts (v1+v2), WhatsApp monitoring
system plan, and OpenClaw upgrade protection strategy.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 15:17:11 +01:00

227 lines
9.9 KiB
Markdown

# OpenClaw Upgrade Protection Strategy
**Date:** 2026-02-16 22:30
**Context:** Protecting our WhatsApp monitoring system when OpenClaw gets updated via `docker compose pull` or version bumps
## Risk Map
| Component | Location | Survives Update? | Risk |
|-----------|----------|-----------------|------|
| **handler.ts** (logger hook) | `~/.openclaw/hooks/whatsapp-logger/` | Yes — host volume mount | LOW: OpenClaw may change hook API |
| **handler.ts** (context hook) | `~/.openclaw/hooks/whatsapp-context/` | Yes — host volume mount | LOW: same |
| **wa-query.js** | `~/.openclaw/workspace/tools/` | Yes — host volume mount | NONE: pure Node.js, no OpenClaw deps |
| **TOOLS.md** | `~/.openclaw/workspace/TOOLS.md` | Yes — host volume mount | NONE: documentation only |
| **sidecar.py** | `~/.openclaw/whatsapp-monitor/` | Yes — runs on host, not in container | NONE: completely independent |
| **PostgreSQL** | Coolify-managed container `akwgskos0woc4w0coc8ssks4` | Yes — separate container + volume | NONE: independent of OpenClaw |
| **contacts.json** | `~/.openclaw/whatsapp-monitor/` | Yes — host filesystem | NONE |
| **JSONL files** | `~/.openclaw/whatsapp-monitor/` | Yes — host filesystem | NONE |
| **openclaw.json** | `~/.openclaw/openclaw.json` | Yes — host volume | MEDIUM: OpenClaw may add/remove keys on update |
| **wa-policy.py** | `~/openclaw/wa-policy.py` | Yes — host filesystem | LOW: may need openclaw.json schema update |
| **Cron jobs** | Stored in OpenClaw gateway internal DB | **MAYBE NOT** — depends on data persistence | HIGH: may be wiped on container recreation |
| **systemd service** | `/etc/systemd/system/whatsapp-monitor.service` | Yes — system-level | NONE |
| **Hook type imports** | `PluginHookMessageReceivedEvent` | Depends on API stability | HIGH: type may be renamed/restructured |
## What Can Break
### 1. Hook API Changes (HIGH risk)
OpenClaw hooks import types from `openclaw/plugins`. If a new version:
- Renames `PluginHookMessageReceivedEvent` → something else
- Changes the event shape (e.g., `event.from``event.sender.id`)
- Changes hook resolution (different events, different return types)
**Mitigation:**
```typescript
// Defensive handler.ts — no type import dependency
export default function handler(event: any) {
// Extract fields with fallbacks
const from = event.from || event.sender?.id || event.sender || "unknown";
const content = event.content || event.body || event.message?.text || "";
const channel = event.channelId || event.channel || "unknown";
const senderName = event.metadata?.senderName || event.senderName || event.pushName || "";
// ...
}
```
### 2. Cron Jobs Lost on Recreate (HIGH risk)
OpenClaw stores cron jobs in its internal state. If the container is recreated (not just restarted), crons may vanish.
**Mitigation:**
- Keep a cron recreation script on the host
- Run it after every `docker compose up -d` or update
### 3. openclaw.json Schema Changes (MEDIUM risk)
A new version might:
- Reject unknown keys we added
- Restructure `hooks.internal.entries`
- Change `channels.whatsapp` shape
**Mitigation:**
- Keep a backup of our config additions separately
- After update, run `openclaw doctor --fix` then re-apply our keys
### 4. Workspace Tool Execution (LOW risk)
OpenClaw might change how workspace tools are discovered or executed. Currently `exec` runs commands in the workspace dir.
**Mitigation:**
- wa-query.js is self-contained Node.js — worst case, it's called by absolute path
- The sidecar + index.json work regardless (host-side)
## Protection Artifacts
### Backup Script: `~/.openclaw/whatsapp-monitor/backup-config.sh`
Run before any OpenClaw update:
```bash
#!/bin/bash
# Backup all WhatsApp monitoring config before OpenClaw update
BACKUP_DIR="$HOME/.openclaw/whatsapp-monitor/backups/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$BACKUP_DIR"
# Hooks
cp -r ~/.openclaw/hooks/whatsapp-logger/ "$BACKUP_DIR/hook-logger/"
cp -r ~/.openclaw/hooks/whatsapp-context/ "$BACKUP_DIR/hook-context/"
# Config
cp ~/.openclaw/openclaw.json "$BACKUP_DIR/openclaw.json"
cp ~/.openclaw/whatsapp-monitor/contacts.json "$BACKUP_DIR/contacts.json"
# Workspace tools
cp ~/.openclaw/workspace/tools/wa-query.js "$BACKUP_DIR/wa-query.js"
cp ~/.openclaw/workspace/TOOLS.md "$BACKUP_DIR/TOOLS.md"
# Policy
cp ~/openclaw/wa-policy.py "$BACKUP_DIR/wa-policy.py"
# Cron snapshot
docker exec openclaw-openclaw-gateway-1 node dist/index.js cron list \
--token 3547c3f2b7b4a33eb077cf804bcca446057f81ba1578b2045dbb3aa4e04346ee \
--url ws://127.0.0.1:18789 2>/dev/null > "$BACKUP_DIR/cron-jobs.txt"
echo "Backed up to $BACKUP_DIR"
ls -la "$BACKUP_DIR"
```
### Restore Script: `~/.openclaw/whatsapp-monitor/restore-after-update.sh`
Run after any OpenClaw update:
```bash
#!/bin/bash
# Restore WhatsApp monitoring after OpenClaw update
TOKEN="3547c3f2b7b4a33eb077cf804bcca446057f81ba1578b2045dbb3aa4e04346ee"
URL="ws://127.0.0.1:18789"
echo "=== Verifying hooks ==="
ls -la ~/.openclaw/hooks/whatsapp-logger/handler.ts
ls -la ~/.openclaw/hooks/whatsapp-context/handler.ts
echo "=== Verifying workspace tools ==="
ls -la ~/.openclaw/workspace/tools/wa-query.js
echo "=== Re-registering hooks in config ==="
python3 -c "
import json
with open('$HOME/.openclaw/openclaw.json') as f:
config = json.load(f)
hooks = config.setdefault('hooks', {}).setdefault('internal', {})
hooks['enabled'] = True
entries = hooks.setdefault('entries', {})
entries['WhatsApp Message Logger'] = {'enabled': True}
entries['WhatsApp Context Injector'] = {'enabled': True}
with open('$HOME/.openclaw/openclaw.json', 'w') as f:
json.dump(config, f, indent=2)
print('Hooks re-registered in config')
"
echo "=== Re-creating cron jobs ==="
docker exec openclaw-openclaw-gateway-1 node dist/index.js cron add \
--name "WhatsApp Morning Digest" \
--schedule "cron 0 9 * * * @ UTC" \
--prompt 'Run node tools/wa-query.js summary 12 and node tools/wa-query.js unread. Create a digest. Send to +34678000075 via openclaw message send --channel whatsapp. Then mark-read all.' \
--target isolated --agent main \
--token "$TOKEN" --url "$URL" 2>/dev/null && echo "Morning digest cron added"
docker exec openclaw-openclaw-gateway-1 node dist/index.js cron add \
--name "WhatsApp Evening Digest" \
--schedule "cron 0 21 * * * @ UTC" \
--prompt 'Run node tools/wa-query.js summary 12 and node tools/wa-query.js unread. Create a digest. Send to +34678000075 via openclaw message send --channel whatsapp. Then mark-read all.' \
--target isolated --agent main \
--token "$TOKEN" --url "$URL" 2>/dev/null && echo "Evening digest cron added"
echo "=== Verifying sidecar ==="
systemctl status whatsapp-monitor.service --no-pager | head -5
echo "=== Verifying PostgreSQL ==="
docker exec akwgskos0woc4w0coc8ssks4 psql -U openclaw -d whatsapp_monitor -c "SELECT count(*) as messages FROM messages; SELECT count(*) as contacts FROM contacts;"
echo "=== Restarting gateway ==="
cd ~/openclaw && docker compose restart openclaw-gateway
echo "=== Done ==="
```
## Pre-Update Checklist
Before running `docker compose pull` or updating OpenClaw:
1. **[ ]** Run backup script: `bash ~/.openclaw/whatsapp-monitor/backup-config.sh`
2. **[ ]** Note current cron job count: `docker exec openclaw-openclaw-gateway-1 node dist/index.js cron list --token TOKEN --url URL | grep -c WhatsApp`
3. **[ ]** Stop sidecar (optional, prevents stale writes): `sudo systemctl stop whatsapp-monitor`
4. **[ ]** Pull/update OpenClaw: `cd ~/openclaw && docker compose pull && docker compose up -d`
5. **[ ]** Wait for gateway to start: `docker logs -f openclaw-openclaw-gateway-1`
6. **[ ]** Run restore script: `bash ~/.openclaw/whatsapp-monitor/restore-after-update.sh`
7. **[ ]** Re-start sidecar: `sudo systemctl start whatsapp-monitor`
8. **[ ]** Verify everything: check hooks, crons, sidecar status, PG connection
## Why PostgreSQL Protects Us
| SQLite (old) | PostgreSQL (new) |
|---|---|
| File inside `~/.openclaw/whatsapp-monitor/` — could be corrupted by concurrent access | Separate container, proper ACID transactions |
| Gone if someone deletes the directory | Lives in Coolify-managed Docker volume — survives everything |
| Not queryable from CloudBeaver | Visible in CloudBeaver at `127.0.0.1:5450` |
| No backups | Can add Coolify backup schedule |
| Single writer (file locking) | Concurrent readers + writers |
## PostgreSQL Connection Details
| Property | Value |
|----------|-------|
| **Container** | `akwgskos0woc4w0coc8ssks4` |
| **Image** | `postgres:16-alpine` |
| **Host port** | `5450` |
| **User** | `openclaw` |
| **Password** | `OpenClaw2026!` |
| **Database** | `whatsapp_monitor` |
| **Coolify UUID** | `akwgskos0woc4w0coc8ssks4` |
| **Internal URL** | `postgres://openclaw:OpenClaw2026%21@akwgskos0woc4w0coc8ssks4:5432/whatsapp_monitor` |
| **Host URL** | `postgres://openclaw:OpenClaw2026!@127.0.0.1:5450/whatsapp_monitor` |
## Architecture After Migration
```
WhatsApp message → OpenClaw gateway (container)
├── Hook: whatsapp-logger/handler.ts
│ └── writes JSONL to ~/.openclaw/whatsapp-monitor/
├── Hook: whatsapp-context/handler.ts
│ └── reads index.json → injects into agent context
└── wa-query.js (reads JSONL + contacts.json)
└── for quick queries inside the agent
NUC Host:
sidecar.py (systemd) ─── reads JSONL ──→ PostgreSQL (Coolify container :5450)
│ │
└── writes ──→ index.json (summary for hooks + agent)
CloudBeaver can query it
```
## Related
- Plan: `.artifacts/2026-02-16_22-00_whatsapp-monitoring-system-plan.md`
- WhatsApp MCP: `.artifacts/2026-02-12_22-50_whatsapp-mcp-setup.md`
- OpenClaw setup: `.artifacts/2026-02-12_02-30_openclaw-setup.md`