@askexenow/exe-os 0.9.155 → 0.9.157
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deploy/compose/PROTECTED_FILES.md +34 -0
- package/deploy/compose/backup.sh +117 -0
- package/deploy/compose/branding.json +20 -0
- package/deploy/compose/docker-compose.yml +14 -0
- package/deploy/compose/restore.sh +73 -0
- package/deploy/compose/setup.sh +166 -0
- package/deploy/compose/status.sh +48 -0
- package/dist/bin/stack-update.js +27 -2
- package/package.json +1 -1
- package/release-notes.json +126 -126
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Protected Files — NEVER overwritten by stack-update
|
|
2
|
+
|
|
3
|
+
These files contain customer configuration. `exe-os stack-update` MUST NOT
|
|
4
|
+
touch them. If a file needs to change, the update should add a NEW file
|
|
5
|
+
and log a migration notice, not replace the existing one.
|
|
6
|
+
|
|
7
|
+
## Config files (bind-mounted, customer-owned after first setup)
|
|
8
|
+
- `.env` — all secrets, tokens, passwords (PATCHED, never replaced)
|
|
9
|
+
- `gateway.json` — WhatsApp adapter config, account names
|
|
10
|
+
- `branding.json` — customer brand colors, fonts, logo
|
|
11
|
+
- `cloudflared/config.yml` — tunnel ID, credentials, ingress routes
|
|
12
|
+
- `cloudflared/*.json` — tunnel credential files
|
|
13
|
+
|
|
14
|
+
## Data volumes (Docker managed, persist across updates)
|
|
15
|
+
- `postgres_data` — all database data (CRM, wiki, graph, raw, gateway)
|
|
16
|
+
- `gateway_data` — Baileys WhatsApp auth state (creds.json, sessions)
|
|
17
|
+
- `wiki_data` — uploaded documents, workspace storage
|
|
18
|
+
- `crm_data` — CRM local file storage
|
|
19
|
+
- `monitor_hub_data` — PocketBase data, alert history
|
|
20
|
+
- `monitor_agent_data` — agent metrics cache
|
|
21
|
+
- `redis_data` — CRM job queue, session cache
|
|
22
|
+
- `clickhouse_data` — CRM analytics
|
|
23
|
+
- `exe_os_data` — daemon state, SQLCipher memory DB
|
|
24
|
+
|
|
25
|
+
## What CAN be updated safely
|
|
26
|
+
- Docker images (pulled, not built locally)
|
|
27
|
+
- `init-db.sql` (only runs on FIRST postgres boot, not on restarts)
|
|
28
|
+
- `docker-compose.yml` (can be replaced — it references configs by path)
|
|
29
|
+
- Deploy scripts (setup.sh, backup.sh, status.sh)
|
|
30
|
+
|
|
31
|
+
## Golden rule
|
|
32
|
+
If `docker compose down && docker compose up -d` loses customer data
|
|
33
|
+
or config, the compose is WRONG. Volumes and bind mounts must survive
|
|
34
|
+
any container lifecycle operation EXCEPT `docker compose down -v`.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# exe-os stack backup — full data + config, portable to any destination.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ./backup.sh # Backup to /opt/exe-backups/
|
|
6
|
+
# ./backup.sh --output /tmp/backup # Backup to custom dir
|
|
7
|
+
# ./backup.sh --download # Create backup + print download command
|
|
8
|
+
# ./backup.sh --upload-r2 # Backup + upload to Cloudflare R2
|
|
9
|
+
# ./backup.sh --upload-s3 s3://bucket # Backup + upload to S3
|
|
10
|
+
#
|
|
11
|
+
set -euo pipefail
|
|
12
|
+
|
|
13
|
+
BACKUP_DIR="${BACKUP_DIR:-/opt/exe-backups}"
|
|
14
|
+
RETENTION_DAYS="${BACKUP_RETENTION_DAYS:-7}"
|
|
15
|
+
DATE=$(date +%Y%m%d-%H%M%S)
|
|
16
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
17
|
+
DOWNLOAD_MODE=false
|
|
18
|
+
UPLOAD_R2=false
|
|
19
|
+
UPLOAD_S3=""
|
|
20
|
+
|
|
21
|
+
while [[ $# -gt 0 ]]; do
|
|
22
|
+
case $1 in
|
|
23
|
+
--output) BACKUP_DIR="$2"; shift 2;;
|
|
24
|
+
--download) DOWNLOAD_MODE=true; shift;;
|
|
25
|
+
--upload-r2) UPLOAD_R2=true; shift;;
|
|
26
|
+
--upload-s3) UPLOAD_S3="$2"; shift 2;;
|
|
27
|
+
*) shift;;
|
|
28
|
+
esac
|
|
29
|
+
done
|
|
30
|
+
|
|
31
|
+
mkdir -p "$BACKUP_DIR"
|
|
32
|
+
ARCHIVE="$BACKUP_DIR/exe-backup-$DATE"
|
|
33
|
+
mkdir -p "$ARCHIVE"
|
|
34
|
+
|
|
35
|
+
echo "[backup] Starting exe-os full stack backup ($DATE)"
|
|
36
|
+
|
|
37
|
+
# 1. Postgres dump (all databases)
|
|
38
|
+
echo "[backup] Dumping postgres..."
|
|
39
|
+
docker exec exe-db pg_dumpall -U exe > "$ARCHIVE/postgres.sql" 2>/dev/null || echo "[backup] Postgres dump failed"
|
|
40
|
+
gzip "$ARCHIVE/postgres.sql" 2>/dev/null || true
|
|
41
|
+
|
|
42
|
+
# 2. Customer config files (.env, gateway.json, branding.json, cloudflared)
|
|
43
|
+
echo "[backup] Backing up config files..."
|
|
44
|
+
cp "$SCRIPT_DIR/.env" "$ARCHIVE/env.bak" 2>/dev/null || true
|
|
45
|
+
cp "$SCRIPT_DIR/gateway.json" "$ARCHIVE/gateway.json" 2>/dev/null || true
|
|
46
|
+
cp "$SCRIPT_DIR/branding.json" "$ARCHIVE/branding.json" 2>/dev/null || true
|
|
47
|
+
cp -r "$SCRIPT_DIR/cloudflared" "$ARCHIVE/cloudflared" 2>/dev/null || true
|
|
48
|
+
|
|
49
|
+
# 3. Gateway auth state (Baileys creds — critical for WhatsApp connection)
|
|
50
|
+
echo "[backup] Backing up gateway WhatsApp auth state..."
|
|
51
|
+
docker cp exe-gateway:/data/. "$ARCHIVE/gateway-data/" 2>/dev/null || echo "[backup] Gateway data skipped"
|
|
52
|
+
|
|
53
|
+
# 4. Wiki storage (uploaded documents)
|
|
54
|
+
echo "[backup] Backing up wiki storage..."
|
|
55
|
+
docker cp exe-wiki:/app/server/storage/. "$ARCHIVE/wiki-storage/" 2>/dev/null || echo "[backup] Wiki storage skipped"
|
|
56
|
+
|
|
57
|
+
# 5. exe-os daemon state (optional — SQLCipher DB is local-first, not critical for VPS)
|
|
58
|
+
echo "[backup] Backing up exe-os state..."
|
|
59
|
+
docker cp exe-os:/home/exed/.exe-os/. "$ARCHIVE/exe-os-data/" 2>/dev/null || echo "[backup] exe-os data skipped"
|
|
60
|
+
|
|
61
|
+
# 6. Create single archive
|
|
62
|
+
echo "[backup] Creating archive..."
|
|
63
|
+
TARFILE="$BACKUP_DIR/exe-backup-$DATE.tar.gz"
|
|
64
|
+
tar -czf "$TARFILE" -C "$BACKUP_DIR" "exe-backup-$DATE" 2>/dev/null
|
|
65
|
+
rm -rf "$ARCHIVE"
|
|
66
|
+
echo "[backup] Archive: $TARFILE ($(du -h "$TARFILE" | cut -f1))"
|
|
67
|
+
|
|
68
|
+
# 7. Retention — delete old backups
|
|
69
|
+
echo "[backup] Cleaning backups older than $RETENTION_DAYS days..."
|
|
70
|
+
find "$BACKUP_DIR" -name "exe-backup-*.tar.gz" -mtime "+$RETENTION_DAYS" -delete 2>/dev/null
|
|
71
|
+
|
|
72
|
+
# 8. Download instructions
|
|
73
|
+
if $DOWNLOAD_MODE; then
|
|
74
|
+
echo ""
|
|
75
|
+
echo "=== Download to your local machine ==="
|
|
76
|
+
echo "Run on your local machine:"
|
|
77
|
+
echo ""
|
|
78
|
+
HOSTNAME=$(hostname)
|
|
79
|
+
IP=$(curl -s ifconfig.me 2>/dev/null || echo "<VPS_IP>")
|
|
80
|
+
echo " scp root@$IP:$TARFILE ./exe-backup-$DATE.tar.gz"
|
|
81
|
+
echo ""
|
|
82
|
+
echo "Or via Tailscale:"
|
|
83
|
+
TS_IP=$(tailscale ip -4 2>/dev/null || echo "<TAILSCALE_IP>")
|
|
84
|
+
echo " scp root@$TS_IP:$TARFILE ./exe-backup-$DATE.tar.gz"
|
|
85
|
+
echo ""
|
|
86
|
+
echo "To restore on a new VPS:"
|
|
87
|
+
echo " tar -xzf exe-backup-$DATE.tar.gz"
|
|
88
|
+
echo " cp env.bak /opt/exe-stack/.env"
|
|
89
|
+
echo " cp gateway.json /opt/exe-stack/"
|
|
90
|
+
echo " cp branding.json /opt/exe-stack/"
|
|
91
|
+
echo " cp -r cloudflared/ /opt/exe-stack/"
|
|
92
|
+
echo " cat postgres.sql.gz | gunzip | docker exec -i exe-db psql -U exe"
|
|
93
|
+
echo " docker compose up -d"
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
# 9. Upload to R2 (Cloudflare)
|
|
97
|
+
if $UPLOAD_R2; then
|
|
98
|
+
echo "[backup] Uploading to Cloudflare R2..."
|
|
99
|
+
if command -v rclone >/dev/null 2>&1; then
|
|
100
|
+
rclone copy "$TARFILE" r2:exe-backups/ 2>&1 && echo "[backup] R2 upload complete" || echo "[backup] R2 upload failed"
|
|
101
|
+
elif command -v aws >/dev/null 2>&1; then
|
|
102
|
+
aws s3 cp "$TARFILE" "s3://exe-backups/$(basename "$TARFILE")" --endpoint-url "${R2_ENDPOINT:-}" 2>&1 || echo "[backup] R2 upload failed — configure R2_ENDPOINT"
|
|
103
|
+
else
|
|
104
|
+
echo "[backup] Install rclone or aws-cli for R2 upload"
|
|
105
|
+
fi
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# 10. Upload to S3
|
|
109
|
+
if [[ -n "$UPLOAD_S3" ]]; then
|
|
110
|
+
echo "[backup] Uploading to S3..."
|
|
111
|
+
aws s3 cp "$TARFILE" "$UPLOAD_S3/$(basename "$TARFILE")" 2>&1 && echo "[backup] S3 upload complete" || echo "[backup] S3 upload failed"
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
echo "[backup] Done."
|
|
115
|
+
echo ""
|
|
116
|
+
echo "Backups:"
|
|
117
|
+
ls -lh "$BACKUP_DIR"/exe-backup-*.tar.gz 2>/dev/null | tail -5
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Exe OS",
|
|
3
|
+
"logo": null,
|
|
4
|
+
"colors": {
|
|
5
|
+
"primary": "#F5D76E",
|
|
6
|
+
"background": "#0F0E1A",
|
|
7
|
+
"surface": "rgba(245, 215, 110, 0.08)",
|
|
8
|
+
"text": "#f8f5ea",
|
|
9
|
+
"muted": "rgba(248, 245, 234, 0.72)"
|
|
10
|
+
},
|
|
11
|
+
"fonts": {
|
|
12
|
+
"heading": "Epilogue",
|
|
13
|
+
"body": "Manrope",
|
|
14
|
+
"mono": "Space Grotesk"
|
|
15
|
+
},
|
|
16
|
+
"support": {
|
|
17
|
+
"email": "support@askexe.com",
|
|
18
|
+
"url": "https://askexe.com"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -126,6 +126,11 @@ services:
|
|
|
126
126
|
API_EXTERNAL_URL: ${GOTRUE_EXTERNAL_URL:-https://auth.askexe.com}
|
|
127
127
|
GOTRUE_DISABLE_SIGNUP: ${GOTRUE_DISABLE_SIGNUP:-false}
|
|
128
128
|
GOTRUE_MAILER_AUTOCONFIRM: ${GOTRUE_MAILER_AUTOCONFIRM:-true}
|
|
129
|
+
GOTRUE_SMTP_HOST: ${SMTP_HOST:-}
|
|
130
|
+
GOTRUE_SMTP_PORT: ${SMTP_PORT:-587}
|
|
131
|
+
GOTRUE_SMTP_USER: ${SMTP_USER:-}
|
|
132
|
+
GOTRUE_SMTP_PASS: ${SMTP_PASS:-}
|
|
133
|
+
GOTRUE_SMTP_ADMIN_EMAIL: ${SMTP_FROM:-noreply@askexe.com}
|
|
129
134
|
ports:
|
|
130
135
|
- "127.0.0.1:${GOTRUE_HOST_PORT:-9999}:9999"
|
|
131
136
|
networks:
|
|
@@ -173,9 +178,14 @@ services:
|
|
|
173
178
|
image: ${CRM_IMAGE_TAG:-ghcr.io/askexe/exe-crm:v0.9.2}
|
|
174
179
|
container_name: exe-crm
|
|
175
180
|
restart: unless-stopped
|
|
181
|
+
# Auto-migrate on boot: run database init before starting the app.
|
|
182
|
+
# Twenty CRM won't create tables automatically — this ensures they exist.
|
|
183
|
+
command: ["sh", "-c", "yarn database:init:prod 2>/dev/null || true && node dist/src/main"]
|
|
176
184
|
depends_on:
|
|
177
185
|
exe-db:
|
|
178
186
|
condition: service_healthy
|
|
187
|
+
gotrue:
|
|
188
|
+
condition: service_healthy
|
|
179
189
|
clickhouse:
|
|
180
190
|
condition: service_healthy
|
|
181
191
|
redis:
|
|
@@ -261,9 +271,13 @@ services:
|
|
|
261
271
|
image: ${WIKI_IMAGE_TAG:-ghcr.io/askexe/exe-wiki:v0.9.2}
|
|
262
272
|
container_name: exe-wiki
|
|
263
273
|
restart: unless-stopped
|
|
274
|
+
# Wiki uses Prisma — runs migrate on boot via built-in entrypoint.
|
|
275
|
+
# If tables don't exist, Prisma creates them automatically.
|
|
264
276
|
depends_on:
|
|
265
277
|
exe-db:
|
|
266
278
|
condition: service_healthy
|
|
279
|
+
gotrue:
|
|
280
|
+
condition: service_healthy
|
|
267
281
|
env_file:
|
|
268
282
|
- path: .env
|
|
269
283
|
required: false
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# exe-os stack restore — restore from a backup archive.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ./restore.sh /path/to/exe-backup-YYYYMMDD-HHMMSS.tar.gz
|
|
6
|
+
#
|
|
7
|
+
# WARNING: This overwrites current config and database. Make a backup first.
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
|
11
|
+
info() { echo -e "${GREEN}[restore]${NC} $1"; }
|
|
12
|
+
warn() { echo -e "${YELLOW}[restore]${NC} $1"; }
|
|
13
|
+
err() { echo -e "${RED}[restore]${NC} $1" >&2; }
|
|
14
|
+
|
|
15
|
+
ARCHIVE="${1:-}"
|
|
16
|
+
[[ -z "$ARCHIVE" ]] && { err "Usage: ./restore.sh <backup-archive.tar.gz>"; exit 1; }
|
|
17
|
+
[[ ! -f "$ARCHIVE" ]] && { err "File not found: $ARCHIVE"; exit 1; }
|
|
18
|
+
|
|
19
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
20
|
+
TEMP_DIR=$(mktemp -d)
|
|
21
|
+
trap "rm -rf $TEMP_DIR" EXIT
|
|
22
|
+
|
|
23
|
+
info "Extracting backup..."
|
|
24
|
+
tar -xzf "$ARCHIVE" -C "$TEMP_DIR"
|
|
25
|
+
BACKUP_DIR=$(ls -d "$TEMP_DIR"/exe-backup-* 2>/dev/null | head -1)
|
|
26
|
+
[[ -z "$BACKUP_DIR" ]] && { err "Invalid backup archive — no exe-backup-* directory found"; exit 1; }
|
|
27
|
+
|
|
28
|
+
echo ""
|
|
29
|
+
warn "This will OVERWRITE current config and restore the database."
|
|
30
|
+
warn "Current data will be LOST. Make sure you have a backup of the current state."
|
|
31
|
+
read -p "Type 'RESTORE' to confirm: " CONFIRM
|
|
32
|
+
[[ "$CONFIRM" != "RESTORE" ]] && { err "Aborted."; exit 1; }
|
|
33
|
+
|
|
34
|
+
# 1. Restore config files
|
|
35
|
+
info "Restoring config files..."
|
|
36
|
+
[[ -f "$BACKUP_DIR/env.bak" ]] && cp "$BACKUP_DIR/env.bak" "$SCRIPT_DIR/.env" && info ".env restored"
|
|
37
|
+
[[ -f "$BACKUP_DIR/gateway.json" ]] && cp "$BACKUP_DIR/gateway.json" "$SCRIPT_DIR/gateway.json" && info "gateway.json restored"
|
|
38
|
+
[[ -f "$BACKUP_DIR/branding.json" ]] && cp "$BACKUP_DIR/branding.json" "$SCRIPT_DIR/branding.json" && info "branding.json restored"
|
|
39
|
+
[[ -d "$BACKUP_DIR/cloudflared" ]] && cp -r "$BACKUP_DIR/cloudflared" "$SCRIPT_DIR/" && info "cloudflared config restored"
|
|
40
|
+
|
|
41
|
+
# 2. Restore postgres
|
|
42
|
+
if [[ -f "$BACKUP_DIR/postgres.sql.gz" ]]; then
|
|
43
|
+
info "Restoring postgres database..."
|
|
44
|
+
docker compose up -d exe-db 2>/dev/null
|
|
45
|
+
sleep 5 # wait for postgres to be ready
|
|
46
|
+
gunzip -c "$BACKUP_DIR/postgres.sql.gz" | docker exec -i exe-db psql -U exe 2>/dev/null
|
|
47
|
+
info "Postgres restored"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# 3. Restore gateway auth state
|
|
51
|
+
if [[ -d "$BACKUP_DIR/gateway-data" ]]; then
|
|
52
|
+
info "Restoring gateway WhatsApp auth state..."
|
|
53
|
+
docker compose up -d exe-gateway 2>/dev/null
|
|
54
|
+
sleep 3
|
|
55
|
+
docker cp "$BACKUP_DIR/gateway-data/." exe-gateway:/data/ 2>/dev/null
|
|
56
|
+
docker restart exe-gateway 2>/dev/null
|
|
57
|
+
info "Gateway auth state restored (WhatsApp should reconnect)"
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# 4. Restore wiki storage
|
|
61
|
+
if [[ -d "$BACKUP_DIR/wiki-storage" ]]; then
|
|
62
|
+
info "Restoring wiki storage..."
|
|
63
|
+
docker compose up -d exe-wiki 2>/dev/null
|
|
64
|
+
sleep 3
|
|
65
|
+
docker cp "$BACKUP_DIR/wiki-storage/." exe-wiki:/app/server/storage/ 2>/dev/null
|
|
66
|
+
info "Wiki storage restored"
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# 5. Start full stack
|
|
70
|
+
info "Starting full stack..."
|
|
71
|
+
docker compose up -d 2>&1
|
|
72
|
+
|
|
73
|
+
info "Restore complete. Run ./status.sh to verify."
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# exe-os stack first-time setup — run once on a fresh VPS.
|
|
3
|
+
# Usage: ./setup.sh --client <name> --domain <domain> [--license <key>]
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
|
7
|
+
info() { echo -e "${GREEN}[setup]${NC} $1"; }
|
|
8
|
+
warn() { echo -e "${YELLOW}[setup]${NC} $1"; }
|
|
9
|
+
err() { echo -e "${RED}[setup]${NC} $1" >&2; }
|
|
10
|
+
|
|
11
|
+
# Parse args
|
|
12
|
+
CLIENT="" DOMAIN="" LICENSE=""
|
|
13
|
+
while [[ $# -gt 0 ]]; do
|
|
14
|
+
case $1 in
|
|
15
|
+
--client) CLIENT="$2"; shift 2;;
|
|
16
|
+
--domain) DOMAIN="$2"; shift 2;;
|
|
17
|
+
--license) LICENSE="$2"; shift 2;;
|
|
18
|
+
*) err "Unknown arg: $1"; exit 1;;
|
|
19
|
+
esac
|
|
20
|
+
done
|
|
21
|
+
[[ -z "$CLIENT" || -z "$DOMAIN" ]] && { err "Usage: ./setup.sh --client <name> --domain <domain>"; exit 1; }
|
|
22
|
+
|
|
23
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
24
|
+
cd "$SCRIPT_DIR"
|
|
25
|
+
|
|
26
|
+
# Step 1: Docker + GHCR auth
|
|
27
|
+
info "Step 1: Docker registry authentication"
|
|
28
|
+
if ! docker info >/dev/null 2>&1; then
|
|
29
|
+
err "Docker is not running. Install Docker first: https://docs.docker.com/engine/install/"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if [[ -f .ghcr-token ]]; then
|
|
34
|
+
info "Logging into GHCR with stored token..."
|
|
35
|
+
cat .ghcr-token | docker login ghcr.io -u exe-os-pull --password-stdin 2>/dev/null || true
|
|
36
|
+
elif [[ -n "${GHCR_TOKEN:-}" ]]; then
|
|
37
|
+
info "Logging into GHCR with GHCR_TOKEN env var..."
|
|
38
|
+
echo "$GHCR_TOKEN" | docker login ghcr.io -u exe-os-pull --password-stdin 2>/dev/null || true
|
|
39
|
+
else
|
|
40
|
+
warn "No GHCR token found. Set GHCR_TOKEN env var or create .ghcr-token file."
|
|
41
|
+
warn "Images must be pullable — public or pre-authed."
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Step 2: Generate .env
|
|
45
|
+
info "Step 2: Generating .env file"
|
|
46
|
+
if [[ -f .env ]]; then
|
|
47
|
+
warn ".env already exists — skipping generation. Delete .env to regenerate."
|
|
48
|
+
else
|
|
49
|
+
if command -v node >/dev/null 2>&1; then
|
|
50
|
+
node -e "
|
|
51
|
+
const { generateEnv } = require('../../dist/deploy/compose/generate-env.js');
|
|
52
|
+
console.log(generateEnv({ clientName: '$CLIENT', domain: '$DOMAIN', licenseKey: '${LICENSE:-}' || undefined }));
|
|
53
|
+
" > .env 2>/dev/null || {
|
|
54
|
+
# Fallback: generate inline
|
|
55
|
+
info "Generating secrets inline..."
|
|
56
|
+
gen() { openssl rand -hex "$1"; }
|
|
57
|
+
cat > .env << ENVEOF
|
|
58
|
+
POSTGRES_USER=exe
|
|
59
|
+
POSTGRES_PASSWORD=$(gen 32)
|
|
60
|
+
POSTGRES_DB=exedb
|
|
61
|
+
CLICKHOUSE_DB=default
|
|
62
|
+
CLICKHOUSE_USER=exe
|
|
63
|
+
CLICKHOUSE_PASSWORD=$(gen 32)
|
|
64
|
+
REDIS_PASSWORD=$(gen 32)
|
|
65
|
+
GOTRUE_JWT_SECRET=$(gen 48)
|
|
66
|
+
GOTRUE_SITE_URL=https://crm.${DOMAIN}
|
|
67
|
+
GOTRUE_EXTERNAL_URL=https://auth.${DOMAIN}
|
|
68
|
+
GOTRUE_DISABLE_SIGNUP=false
|
|
69
|
+
GOTRUE_MAILER_AUTOCONFIRM=true
|
|
70
|
+
CRM_IMAGE_TAG=ghcr.io/askexe/exe-crm:v0.9.3
|
|
71
|
+
CRM_SERVER_URL=https://crm.${DOMAIN}
|
|
72
|
+
CRM_APP_SECRET=$(gen 48)
|
|
73
|
+
EXE_CRM_ADMIN_TOKEN=$(gen 48)
|
|
74
|
+
CRM_HOST_PORT=3000
|
|
75
|
+
WIKI_IMAGE_TAG=ghcr.io/askexe/exe-wiki:v0.9.4
|
|
76
|
+
WIKI_DB_SCHEMA=wiki
|
|
77
|
+
WIKI_VECTOR_DB=postgres
|
|
78
|
+
WIKI_AUTH_TOKEN=$(gen 48)
|
|
79
|
+
EXE_WIKI_ADMIN_TOKEN=$(gen 48)
|
|
80
|
+
WIKI_JWT_SECRET=$(gen 48)
|
|
81
|
+
WIKI_SIG_KEY=$(gen 48)
|
|
82
|
+
WIKI_SIG_SALT=$(gen 16)
|
|
83
|
+
WIKI_HOST_PORT=3001
|
|
84
|
+
EXE_OS_IMAGE_TAG=ghcr.io/askexe/exe-os:v0.9.155
|
|
85
|
+
EXED_MCP_TOKEN=$(gen 48)
|
|
86
|
+
EXED_DEVICE_ID=vps-${CLIENT}
|
|
87
|
+
EXE_CLOUD_SYNC_TO_POSTGRES=true
|
|
88
|
+
EXE_LICENSE_KEY=${LICENSE:-CHANGEME_EXE_LICENSE_KEY}
|
|
89
|
+
GATEWAY_IMAGE_TAG=ghcr.io/askexe/exe-gateway:v0.9.3
|
|
90
|
+
EXE_GATEWAY_AUTH_TOKEN=$(gen 48)
|
|
91
|
+
EXE_GATEWAY_WS_RELAY_AUTH_TOKEN=$(gen 48)
|
|
92
|
+
EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN=$(gen 32)
|
|
93
|
+
API_ROUTER_URL=https://gateway.${DOMAIN}
|
|
94
|
+
GATEWAY_HTTP_HOST_PORT=3100
|
|
95
|
+
GATEWAY_WS_HOST_PORT=3101
|
|
96
|
+
MONITOR_HUB_IMAGE_TAG=ghcr.io/askexe/exe-monitor-hub:v0.9.4
|
|
97
|
+
MONITOR_AGENT_IMAGE_TAG=ghcr.io/askexe/exe-monitor-agent:v0.9.4
|
|
98
|
+
EXE_MONITOR_ADMIN_TOKEN=$(gen 48)
|
|
99
|
+
MONITOR_HUB_URL=https://monitor.${DOMAIN}
|
|
100
|
+
MONITOR_AGENT_TOKEN=CHANGEME_MONITOR_AGENT_TOKEN
|
|
101
|
+
MONITOR_AGENT_KEY=CHANGEME_MONITOR_AGENT_KEY
|
|
102
|
+
MONITOR_AGENT_LISTEN=:45876
|
|
103
|
+
MONITOR_HUB_PORT=8090
|
|
104
|
+
ENVEOF
|
|
105
|
+
}
|
|
106
|
+
fi
|
|
107
|
+
info ".env generated with auto-generated secrets"
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Step 3: Cloudflared tunnel config
|
|
111
|
+
info "Step 3: Cloudflare Tunnel setup"
|
|
112
|
+
if [[ ! -f cloudflared/config.yml ]]; then
|
|
113
|
+
if [[ -f cloudflared/config.yml.example ]]; then
|
|
114
|
+
warn "Copy cloudflared/config.yml.example → cloudflared/config.yml"
|
|
115
|
+
warn "Then set TUNNEL_ID and DOMAIN in the config."
|
|
116
|
+
warn "Create tunnel: cloudflared tunnel create exe-${CLIENT}"
|
|
117
|
+
fi
|
|
118
|
+
else
|
|
119
|
+
info "Cloudflared config exists."
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Step 4: Pull images
|
|
123
|
+
info "Step 4: Pulling Docker images..."
|
|
124
|
+
docker compose pull 2>&1 || { err "Image pull failed — check GHCR authentication"; exit 1; }
|
|
125
|
+
|
|
126
|
+
# Step 5: Start stack
|
|
127
|
+
info "Step 5: Starting stack..."
|
|
128
|
+
docker compose up -d 2>&1
|
|
129
|
+
|
|
130
|
+
# Step 6: Wait for health
|
|
131
|
+
info "Step 6: Waiting for services to be healthy..."
|
|
132
|
+
sleep 10
|
|
133
|
+
HEALTHY=0
|
|
134
|
+
for i in $(seq 1 30); do
|
|
135
|
+
COUNT=$(docker ps --filter "health=healthy" --format '{{.Names}}' | wc -l | tr -d ' ')
|
|
136
|
+
TOTAL=$(docker ps --format '{{.Names}}' | wc -l | tr -d ' ')
|
|
137
|
+
echo -ne "\r $COUNT/$TOTAL healthy (attempt $i/30)..."
|
|
138
|
+
if [[ "$COUNT" -ge "$TOTAL" ]]; then HEALTHY=1; break; fi
|
|
139
|
+
sleep 5
|
|
140
|
+
done
|
|
141
|
+
echo ""
|
|
142
|
+
[[ "$HEALTHY" -eq 1 ]] && info "All services healthy!" || warn "Some services not healthy yet — check docker ps"
|
|
143
|
+
|
|
144
|
+
# Step 7: Verify
|
|
145
|
+
info "Step 7: Verification"
|
|
146
|
+
docker ps --format 'table {{.Names}}\t{{.Status}}'
|
|
147
|
+
echo ""
|
|
148
|
+
info "Stack deployed! Next steps:"
|
|
149
|
+
echo " 1. Configure Cloudflare tunnel (if not done)"
|
|
150
|
+
echo " 2. Open https://crm.${DOMAIN} to create admin account"
|
|
151
|
+
echo " 3. Open https://wiki.${DOMAIN} to set up wiki"
|
|
152
|
+
echo " 4. Configure WhatsApp: edit gateway.json, restart gateway, pair at https://gateway.${DOMAIN}/pair/<name>"
|
|
153
|
+
echo " 5. Verify: curl https://crm.${DOMAIN}/healthz && curl https://wiki.${DOMAIN}/api/ping"
|
|
154
|
+
|
|
155
|
+
# Step 8: Firewall — ensure outbound HTTPS is open
|
|
156
|
+
info "Step 8: Checking network connectivity..."
|
|
157
|
+
if curl -s --max-time 5 https://ghcr.io >/dev/null 2>&1; then
|
|
158
|
+
info "Outbound HTTPS working (GHCR reachable)"
|
|
159
|
+
else
|
|
160
|
+
warn "Cannot reach ghcr.io — check firewall/network. Docker pulls will fail."
|
|
161
|
+
fi
|
|
162
|
+
if curl -s --max-time 5 https://api.cloudflare.com >/dev/null 2>&1; then
|
|
163
|
+
info "Cloudflare reachable"
|
|
164
|
+
else
|
|
165
|
+
warn "Cannot reach Cloudflare — tunnel won't work."
|
|
166
|
+
fi
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# exe-os stack health check — run anytime to verify all services.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
|
|
6
|
+
|
|
7
|
+
echo "=== exe-os Stack Health ==="
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Container status
|
|
11
|
+
echo "Containers:"
|
|
12
|
+
docker ps --format 'table {{.Names}}\t{{.Status}}' 2>/dev/null
|
|
13
|
+
echo ""
|
|
14
|
+
|
|
15
|
+
# Service health endpoints
|
|
16
|
+
echo "Service Endpoints:"
|
|
17
|
+
DOMAIN="${1:-localhost}"
|
|
18
|
+
check() {
|
|
19
|
+
local name=$1 url=$2
|
|
20
|
+
CODE=$(curl -sk -o /dev/null -w "%{http_code}" --max-time 5 "$url" 2>/dev/null || echo "000")
|
|
21
|
+
if [[ "$CODE" == "200" ]]; then
|
|
22
|
+
echo -e " ${GREEN}✅${NC} $name ($CODE)"
|
|
23
|
+
elif [[ "$CODE" == "401" ]]; then
|
|
24
|
+
echo -e " ${YELLOW}🔒${NC} $name ($CODE — auth required, service is up)"
|
|
25
|
+
else
|
|
26
|
+
echo -e " ${RED}❌${NC} $name ($CODE)"
|
|
27
|
+
fi
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
check "CRM" "http://127.0.0.1:3000/healthz"
|
|
31
|
+
check "Wiki" "http://127.0.0.1:3001/api/ping"
|
|
32
|
+
check "Gateway" "http://127.0.0.1:3100/health"
|
|
33
|
+
check "Monitor" "http://127.0.0.1:8090/api/health"
|
|
34
|
+
check "GoTrue" "http://127.0.0.1:9999/health"
|
|
35
|
+
check "exe-os" "http://127.0.0.1:8765/health"
|
|
36
|
+
|
|
37
|
+
echo ""
|
|
38
|
+
|
|
39
|
+
# Database
|
|
40
|
+
echo "Database:"
|
|
41
|
+
docker exec exe-db psql -U exe -d exedb -c "SELECT schemaname, COUNT(*) as tables FROM pg_tables WHERE schemaname NOT IN ('pg_catalog','information_schema') GROUP BY schemaname ORDER BY schemaname;" 2>/dev/null || echo " ❌ Cannot connect to database"
|
|
42
|
+
|
|
43
|
+
echo ""
|
|
44
|
+
|
|
45
|
+
# Disk/Memory
|
|
46
|
+
echo "Resources:"
|
|
47
|
+
echo " RAM: $(free -h 2>/dev/null | awk '/^Mem:/ {print $3 "/" $2}' || echo 'N/A')"
|
|
48
|
+
echo " Disk: $(df -h / 2>/dev/null | awk 'NR==2 {print $3 "/" $2 " (" $5 " used)"}' || echo 'N/A')"
|
package/dist/bin/stack-update.js
CHANGED
|
@@ -508,11 +508,36 @@ async function runStackUpdate(options) {
|
|
|
508
508
|
return { status: "planned", targetVersion: plan.targetVersion, changes: plan.changes, lockFile };
|
|
509
509
|
}
|
|
510
510
|
await postDeployAudit(options, "started", plan.targetVersion, previousVersion);
|
|
511
|
-
const
|
|
511
|
+
const stackDir = path.dirname(options.envFile);
|
|
512
|
+
const backupDir = path.join(stackDir, ".exe-stack-backups");
|
|
512
513
|
mkdirSync(backupDir, { recursive: true });
|
|
513
514
|
const stamp = now().toISOString().replace(/[:.]/g, "-");
|
|
514
|
-
const
|
|
515
|
+
const updateBackupDir = path.join(backupDir, `pre-update-${stamp}`);
|
|
516
|
+
mkdirSync(updateBackupDir, { recursive: true });
|
|
517
|
+
const backupEnvFile = path.join(updateBackupDir, "env.bak");
|
|
515
518
|
writeFileSync(backupEnvFile, envRaw, { mode: 384 });
|
|
519
|
+
const protectedFiles = ["gateway.json", "branding.json"];
|
|
520
|
+
for (const f of protectedFiles) {
|
|
521
|
+
const src = path.join(stackDir, f);
|
|
522
|
+
try {
|
|
523
|
+
if (existsSync(src)) {
|
|
524
|
+
copyFileSync(src, path.join(updateBackupDir, f));
|
|
525
|
+
}
|
|
526
|
+
} catch {
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
const cfDir = path.join(stackDir, "cloudflared");
|
|
530
|
+
try {
|
|
531
|
+
if (existsSync(cfDir)) {
|
|
532
|
+
const cfBackup = path.join(updateBackupDir, "cloudflared");
|
|
533
|
+
mkdirSync(cfBackup, { recursive: true });
|
|
534
|
+
for (const f of readdirSync(cfDir)) {
|
|
535
|
+
copyFileSync(path.join(cfDir, f), path.join(cfBackup, f));
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
} catch {
|
|
539
|
+
}
|
|
540
|
+
console.log(`[stack-update] Config backed up to ${updateBackupDir}`);
|
|
516
541
|
const updates = Object.fromEntries(plan.changes.map((c) => [c.key, c.after]));
|
|
517
542
|
const patched = patchEnv(envRaw, updates);
|
|
518
543
|
const tmp = `${options.envFile}.tmp-${process.pid}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.157",
|
|
4
4
|
"description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
package/release-notes.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
|
-
"current": "0.9.
|
|
2
|
+
"current": "0.9.157",
|
|
3
3
|
"notes": {
|
|
4
|
-
"0.9.
|
|
5
|
-
"version": "0.9.
|
|
4
|
+
"0.9.157": {
|
|
5
|
+
"version": "0.9.157",
|
|
6
6
|
"date": "2026-05-28",
|
|
7
7
|
"features": [
|
|
8
|
+
"update safety + portable backups + restore",
|
|
9
|
+
"complete deployment readiness — all 14 second-pass blind spots fixed",
|
|
8
10
|
"production-ready stack — all 15 blind spots fixed",
|
|
9
11
|
"blocked task notification — ping dispatcher immediately on status change",
|
|
10
12
|
"self-improving skills — usage tracking, success counting, and refinement daemon",
|
|
@@ -27,9 +29,7 @@
|
|
|
27
29
|
"device-scoped behaviors — add device_id column + filter on load",
|
|
28
30
|
"gateway prompt injection defense — 3-tier security hardening",
|
|
29
31
|
"add diagnostics(action=\"merge_agent_memories\") for reassigning memories across agent IDs",
|
|
30
|
-
"add task dependency tree visualization (action=dependency_tree)"
|
|
31
|
-
"graceful COO auto-relaunch after context-full exit",
|
|
32
|
-
"desktop push notifications on task completion (macOS/Linux)"
|
|
32
|
+
"add task dependency tree visualization (action=dependency_tree)"
|
|
33
33
|
],
|
|
34
34
|
"fixes": [
|
|
35
35
|
"add scope import to prompt-submit — gate pass",
|
|
@@ -104,10 +104,13 @@
|
|
|
104
104
|
"exe-daemon.ts kills old embed.pid process and cleans up"
|
|
105
105
|
]
|
|
106
106
|
},
|
|
107
|
-
"0.9.
|
|
108
|
-
"version": "0.9.
|
|
107
|
+
"0.9.156": {
|
|
108
|
+
"version": "0.9.156",
|
|
109
109
|
"date": "2026-05-28",
|
|
110
110
|
"features": [
|
|
111
|
+
"complete deployment readiness — all 14 second-pass blind spots fixed",
|
|
112
|
+
"production-ready stack — all 15 blind spots fixed",
|
|
113
|
+
"blocked task notification — ping dispatcher immediately on status change",
|
|
111
114
|
"self-improving skills — usage tracking, success counting, and refinement daemon",
|
|
112
115
|
"4 retrieval improvements — query expansion, stop words, contradiction resolution, abstention",
|
|
113
116
|
"competitive roadmap — serverless tier, identity depth, self-improving skills, user modeling",
|
|
@@ -129,12 +132,13 @@
|
|
|
129
132
|
"gateway prompt injection defense — 3-tier security hardening",
|
|
130
133
|
"add diagnostics(action=\"merge_agent_memories\") for reassigning memories across agent IDs",
|
|
131
134
|
"add task dependency tree visualization (action=dependency_tree)",
|
|
132
|
-
"graceful COO auto-relaunch after context-full exit"
|
|
133
|
-
"desktop push notifications on task completion (macOS/Linux)",
|
|
134
|
-
"rename GHCR image exed → exe-os across all deploy/stack references",
|
|
135
|
-
"passive daemon-restart detection — agents get one-time /mcp notice"
|
|
135
|
+
"graceful COO auto-relaunch after context-full exit"
|
|
136
136
|
],
|
|
137
137
|
"fixes": [
|
|
138
|
+
"add scope import to prompt-submit — gate pass",
|
|
139
|
+
"add writeFileSync import to config.ts",
|
|
140
|
+
"persist cloud endpoint migration to config.json — stop logging on every boot",
|
|
141
|
+
"include memory_type in pushToPostgres metadata — was stripped on sync",
|
|
138
142
|
"add scope import to daemon-orchestration — satisfies customer-readiness gate",
|
|
139
143
|
"skill-refinement.ts — correct writeMemory field names + updateIdentity 3rd arg",
|
|
140
144
|
"make skill lifecycle fields optional on Behavior interface — unblocks publish",
|
|
@@ -155,11 +159,7 @@
|
|
|
155
159
|
"close remaining session-scoping findings from Bob's audit",
|
|
156
160
|
"close 3 more session-scoping leaks from Bob's audit (LEAK-4, LEAK-7, LEAK-8)",
|
|
157
161
|
"diagnostics check_update ENOENT + healthcheck timeout",
|
|
158
|
-
"close 8 session-scoping leaks — daemon ALS trust + review cleanup + close-task + inbox"
|
|
159
|
-
"correct graph column names in federated recall query",
|
|
160
|
-
"review notifications never reached reviewer — signal file gate was dead code",
|
|
161
|
-
"remove osascript fallback — desktop notifications use OSC 9 only on macOS",
|
|
162
|
-
"generate valid UUIDs in projection worker stableId + add wiki.* projection"
|
|
162
|
+
"close 8 session-scoping leaks — daemon ALS trust + review cleanup + close-task + inbox"
|
|
163
163
|
],
|
|
164
164
|
"security": [
|
|
165
165
|
"fix shell injection, SSRF, socket leaks, backup validation",
|
|
@@ -176,6 +176,8 @@
|
|
|
176
176
|
"fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
|
|
177
177
|
],
|
|
178
178
|
"other": [
|
|
179
|
+
"rename memory schema → graph across codebase",
|
|
180
|
+
"unified access control — admin token + GoTrue across all services",
|
|
179
181
|
"capture data pipeline spec — raw → filter → wiki + CRM projection",
|
|
180
182
|
"bump to v0.9.149 — task lifecycle simplification + review notification fix",
|
|
181
183
|
"capture gateway connection observability requirements (2026-05-28)",
|
|
@@ -198,19 +200,20 @@
|
|
|
198
200
|
"v0.9.140 publish + heap cap 4GB (was 33% unbounded)",
|
|
199
201
|
"PG-1 cross-repo entity federation design document",
|
|
200
202
|
"add lint step + automated npm publish workflow",
|
|
201
|
-
"audit: scoped SQL + package budget + TUI vendored + TODO classification"
|
|
202
|
-
"add full readiness audit evidence",
|
|
203
|
-
"roadmap: Cross-Repo Ontology — Palantir-level graph (PG-1 through PG-10)"
|
|
203
|
+
"audit: scoped SQL + package budget + TUI vendored + TODO classification"
|
|
204
204
|
],
|
|
205
205
|
"migration_notes": [
|
|
206
206
|
"If daemon goes down, agents will now fail instead of silently",
|
|
207
207
|
"exe-daemon.ts kills old embed.pid process and cleans up"
|
|
208
208
|
]
|
|
209
209
|
},
|
|
210
|
-
"0.9.
|
|
211
|
-
"version": "0.9.
|
|
210
|
+
"0.9.155": {
|
|
211
|
+
"version": "0.9.155",
|
|
212
212
|
"date": "2026-05-28",
|
|
213
213
|
"features": [
|
|
214
|
+
"production-ready stack — all 15 blind spots fixed",
|
|
215
|
+
"blocked task notification — ping dispatcher immediately on status change",
|
|
216
|
+
"self-improving skills — usage tracking, success counting, and refinement daemon",
|
|
214
217
|
"4 retrieval improvements — query expansion, stop words, contradiction resolution, abstention",
|
|
215
218
|
"competitive roadmap — serverless tier, identity depth, self-improving skills, user modeling",
|
|
216
219
|
"run database migrations before container swap in stack-update",
|
|
@@ -232,12 +235,18 @@
|
|
|
232
235
|
"add diagnostics(action=\"merge_agent_memories\") for reassigning memories across agent IDs",
|
|
233
236
|
"add task dependency tree visualization (action=dependency_tree)",
|
|
234
237
|
"graceful COO auto-relaunch after context-full exit",
|
|
235
|
-
"desktop push notifications on task completion (macOS/Linux)"
|
|
236
|
-
"rename GHCR image exed → exe-os across all deploy/stack references",
|
|
237
|
-
"passive daemon-restart detection — agents get one-time /mcp notice",
|
|
238
|
-
"daemon restart orchestrator — single authority for all restart decisions"
|
|
238
|
+
"desktop push notifications on task completion (macOS/Linux)"
|
|
239
239
|
],
|
|
240
240
|
"fixes": [
|
|
241
|
+
"add scope import to prompt-submit — gate pass",
|
|
242
|
+
"add writeFileSync import to config.ts",
|
|
243
|
+
"persist cloud endpoint migration to config.json — stop logging on every boot",
|
|
244
|
+
"include memory_type in pushToPostgres metadata — was stripped on sync",
|
|
245
|
+
"add scope import to daemon-orchestration — satisfies customer-readiness gate",
|
|
246
|
+
"skill-refinement.ts — correct writeMemory field names + updateIdentity 3rd arg",
|
|
247
|
+
"make skill lifecycle fields optional on Behavior interface — unblocks publish",
|
|
248
|
+
"session isolation for tmux kill — block cross-scope session kills",
|
|
249
|
+
"session-scope daemon, push, capacity, and cleanup (P0 #7-#13)",
|
|
241
250
|
"add memory_type to crdt-sync MemoryRecord interface — unblocks publish",
|
|
242
251
|
"session-scope daemon, push, capacity, cleanup (P0 #7-#9, #13)",
|
|
243
252
|
"include memory_type in cloud sync push/pull + fix backfill re-sync",
|
|
@@ -252,17 +261,8 @@
|
|
|
252
261
|
"add shipped_version to support triage + clean platform procedures",
|
|
253
262
|
"close remaining session-scoping findings from Bob's audit",
|
|
254
263
|
"close 3 more session-scoping leaks from Bob's audit (LEAK-4, LEAK-7, LEAK-8)",
|
|
255
|
-
"close 8 session-scoping leaks — daemon ALS trust + review cleanup + close-task + inbox",
|
|
256
|
-
"correct graph column names in federated recall query",
|
|
257
264
|
"diagnostics check_update ENOENT + healthcheck timeout",
|
|
258
|
-
"
|
|
259
|
-
"remove osascript fallback — desktop notifications use OSC 9 only on macOS",
|
|
260
|
-
"generate valid UUIDs in projection worker stableId + add wiki.* projection",
|
|
261
|
-
"RSS backpressure + safe Metal shutdown for embedding daemon OOM",
|
|
262
|
-
"multi-Tom dispatch — per-task signal files + atomic claim + herd prevention",
|
|
263
|
-
"restrict project_name='all' to coordinators only in list_tasks",
|
|
264
|
-
"CRM Dockerfile multi-arch — BUILDPLATFORM for build stages, rebuild bcrypt",
|
|
265
|
-
"enhance intercom log with caller/task/trigger metadata for tracing"
|
|
265
|
+
"close 8 session-scoping leaks — daemon ALS trust + review cleanup + close-task + inbox"
|
|
266
266
|
],
|
|
267
267
|
"security": [
|
|
268
268
|
"fix shell injection, SSRF, socket leaks, backup validation",
|
|
@@ -279,6 +279,8 @@
|
|
|
279
279
|
"fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
|
|
280
280
|
],
|
|
281
281
|
"other": [
|
|
282
|
+
"rename memory schema → graph across codebase",
|
|
283
|
+
"unified access control — admin token + GoTrue across all services",
|
|
282
284
|
"capture data pipeline spec — raw → filter → wiki + CRM projection",
|
|
283
285
|
"bump to v0.9.149 — task lifecycle simplification + review notification fix",
|
|
284
286
|
"capture gateway connection observability requirements (2026-05-28)",
|
|
@@ -301,19 +303,20 @@
|
|
|
301
303
|
"v0.9.140 publish + heap cap 4GB (was 33% unbounded)",
|
|
302
304
|
"PG-1 cross-repo entity federation design document",
|
|
303
305
|
"add lint step + automated npm publish workflow",
|
|
304
|
-
"audit: scoped SQL + package budget + TUI vendored + TODO classification"
|
|
305
|
-
"add full readiness audit evidence",
|
|
306
|
-
"roadmap: Cross-Repo Ontology — Palantir-level graph (PG-1 through PG-10)"
|
|
306
|
+
"audit: scoped SQL + package budget + TUI vendored + TODO classification"
|
|
307
307
|
],
|
|
308
308
|
"migration_notes": [
|
|
309
309
|
"If daemon goes down, agents will now fail instead of silently",
|
|
310
310
|
"exe-daemon.ts kills old embed.pid process and cleans up"
|
|
311
311
|
]
|
|
312
312
|
},
|
|
313
|
-
"0.9.
|
|
314
|
-
"version": "0.9.
|
|
313
|
+
"0.9.154": {
|
|
314
|
+
"version": "0.9.154",
|
|
315
315
|
"date": "2026-05-28",
|
|
316
316
|
"features": [
|
|
317
|
+
"self-improving skills — usage tracking, success counting, and refinement daemon",
|
|
318
|
+
"4 retrieval improvements — query expansion, stop words, contradiction resolution, abstention",
|
|
319
|
+
"competitive roadmap — serverless tier, identity depth, self-improving skills, user modeling",
|
|
317
320
|
"run database migrations before container swap in stack-update",
|
|
318
321
|
"graph auto-extract from ARCHITECTURE.md — regex-based entity/relationship extraction",
|
|
319
322
|
"migrate cloud.askexe.com → api.askexe.com as canonical endpoint",
|
|
@@ -335,12 +338,21 @@
|
|
|
335
338
|
"graceful COO auto-relaunch after context-full exit",
|
|
336
339
|
"desktop push notifications on task completion (macOS/Linux)",
|
|
337
340
|
"rename GHCR image exed → exe-os across all deploy/stack references",
|
|
338
|
-
"passive daemon-restart detection — agents get one-time /mcp notice"
|
|
339
|
-
"daemon restart orchestrator — single authority for all restart decisions",
|
|
340
|
-
"query router cache tuning + cross-session tasks + shared skills",
|
|
341
|
-
"socket health probe + tmux env guard + reviewer queue fallback (features 1, 2)"
|
|
341
|
+
"passive daemon-restart detection — agents get one-time /mcp notice"
|
|
342
342
|
],
|
|
343
343
|
"fixes": [
|
|
344
|
+
"add scope import to daemon-orchestration — satisfies customer-readiness gate",
|
|
345
|
+
"skill-refinement.ts — correct writeMemory field names + updateIdentity 3rd arg",
|
|
346
|
+
"make skill lifecycle fields optional on Behavior interface — unblocks publish",
|
|
347
|
+
"session isolation for tmux kill — block cross-scope session kills",
|
|
348
|
+
"session-scope daemon, push, capacity, and cleanup (P0 #7-#13)",
|
|
349
|
+
"add memory_type to crdt-sync MemoryRecord interface — unblocks publish",
|
|
350
|
+
"session-scope daemon, push, capacity, cleanup (P0 #7-#9, #13)",
|
|
351
|
+
"include memory_type in cloud sync push/pull + fix backfill re-sync",
|
|
352
|
+
"session-scope signal file system — prevent cross-session task/review bleed",
|
|
353
|
+
"session-scope notification routing — use row.session_scope over ambient",
|
|
354
|
+
"daemon NEVER guesses session from tmux — header-only routing",
|
|
355
|
+
"3 daemon bugs — context-full TTL override, API watchdog kill-after-3, idle-kill verify",
|
|
344
356
|
"federated recall always searches code_context + graph — count threshold was useless",
|
|
345
357
|
"make cross-repo guardrail task-aware — allow multi-repo work when task scope permits",
|
|
346
358
|
"ONE postgres — replace crm-postgres with exe-db across entire stack",
|
|
@@ -348,24 +360,12 @@
|
|
|
348
360
|
"add shipped_version to support triage + clean platform procedures",
|
|
349
361
|
"close remaining session-scoping findings from Bob's audit",
|
|
350
362
|
"close 3 more session-scoping leaks from Bob's audit (LEAK-4, LEAK-7, LEAK-8)",
|
|
363
|
+
"diagnostics check_update ENOENT + healthcheck timeout",
|
|
351
364
|
"close 8 session-scoping leaks — daemon ALS trust + review cleanup + close-task + inbox",
|
|
352
365
|
"correct graph column names in federated recall query",
|
|
353
|
-
"diagnostics check_update ENOENT + healthcheck timeout",
|
|
354
366
|
"review notifications never reached reviewer — signal file gate was dead code",
|
|
355
367
|
"remove osascript fallback — desktop notifications use OSC 9 only on macOS",
|
|
356
|
-
"generate valid UUIDs in projection worker stableId + add wiki.* projection"
|
|
357
|
-
"RSS backpressure + safe Metal shutdown for embedding daemon OOM",
|
|
358
|
-
"multi-Tom dispatch — per-task signal files + atomic claim + herd prevention",
|
|
359
|
-
"restrict project_name='all' to coordinators only in list_tasks",
|
|
360
|
-
"CRM Dockerfile multi-arch — BUILDPLATFORM for build stages, rebuild bcrypt",
|
|
361
|
-
"enhance intercom log with caller/task/trigger metadata for tracing",
|
|
362
|
-
"project-scope review queries — no more cross-project review pollution",
|
|
363
|
-
"remove unused getActiveAgent import in list-tasks",
|
|
364
|
-
"project-scope ALL task queries — prevents cross-project pollution",
|
|
365
|
-
"hash-based cloud pull conflict detection + indentation-aware Python/Rust chunker",
|
|
366
|
-
"add sessionScopeFilter to worker-gate + create-task queries",
|
|
367
|
-
"replace require() with ESM import in shouldAutoInstance",
|
|
368
|
-
"intercom-check passes project_name to scanFromDb — prevents cross-project task pollution"
|
|
368
|
+
"generate valid UUIDs in projection worker stableId + add wiki.* projection"
|
|
369
369
|
],
|
|
370
370
|
"security": [
|
|
371
371
|
"fix shell injection, SSRF, socket leaks, backup validation",
|
|
@@ -382,6 +382,7 @@
|
|
|
382
382
|
"fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
|
|
383
383
|
],
|
|
384
384
|
"other": [
|
|
385
|
+
"capture data pipeline spec — raw → filter → wiki + CRM projection",
|
|
385
386
|
"bump to v0.9.149 — task lifecycle simplification + review notification fix",
|
|
386
387
|
"capture gateway connection observability requirements (2026-05-28)",
|
|
387
388
|
"bump to v0.9.146 for publish",
|
|
@@ -405,70 +406,69 @@
|
|
|
405
406
|
"add lint step + automated npm publish workflow",
|
|
406
407
|
"audit: scoped SQL + package budget + TUI vendored + TODO classification",
|
|
407
408
|
"add full readiness audit evidence",
|
|
408
|
-
"roadmap: Cross-Repo Ontology — Palantir-level graph (PG-1 through PG-10)"
|
|
409
|
-
"capture mcp restart self-healing roadmap"
|
|
409
|
+
"roadmap: Cross-Repo Ontology — Palantir-level graph (PG-1 through PG-10)"
|
|
410
410
|
],
|
|
411
411
|
"migration_notes": [
|
|
412
412
|
"If daemon goes down, agents will now fail instead of silently",
|
|
413
413
|
"exe-daemon.ts kills old embed.pid process and cleans up"
|
|
414
414
|
]
|
|
415
415
|
},
|
|
416
|
-
"0.9.
|
|
417
|
-
"version": "0.9.
|
|
418
|
-
"date": "2026-05-
|
|
416
|
+
"0.9.153": {
|
|
417
|
+
"version": "0.9.153",
|
|
418
|
+
"date": "2026-05-28",
|
|
419
419
|
"features": [
|
|
420
|
-
"
|
|
421
|
-
"
|
|
422
|
-
"
|
|
423
|
-
"
|
|
424
|
-
"
|
|
425
|
-
"
|
|
426
|
-
"
|
|
427
|
-
"
|
|
428
|
-
"
|
|
429
|
-
"
|
|
430
|
-
"
|
|
431
|
-
"
|
|
432
|
-
"
|
|
433
|
-
"
|
|
434
|
-
"
|
|
435
|
-
"
|
|
436
|
-
"
|
|
437
|
-
"
|
|
438
|
-
"
|
|
439
|
-
"
|
|
440
|
-
"
|
|
441
|
-
"
|
|
442
|
-
"
|
|
443
|
-
"
|
|
444
|
-
"
|
|
420
|
+
"4 retrieval improvements — query expansion, stop words, contradiction resolution, abstention",
|
|
421
|
+
"competitive roadmap — serverless tier, identity depth, self-improving skills, user modeling",
|
|
422
|
+
"run database migrations before container swap in stack-update",
|
|
423
|
+
"graph auto-extract from ARCHITECTURE.md — regex-based entity/relationship extraction",
|
|
424
|
+
"migrate cloud.askexe.com → api.askexe.com as canonical endpoint",
|
|
425
|
+
"federated recall — code_context + graph fallback when memory results weak",
|
|
426
|
+
"migrate cloud.askexe.com → api.askexe.com across all src/ defaults",
|
|
427
|
+
"rolling restart in stack-update — one service at a time with health verification",
|
|
428
|
+
"DMR benchmark harness + LoCoMo improvements for v0.9.145 evaluation",
|
|
429
|
+
"Windows/WSL support — WezTerm config + WSL detection in setup wizard",
|
|
430
|
+
"queryTaskRows() consolidation — single scoped query path for all task list operations",
|
|
431
|
+
"review signal files — reliable reviewer notification on update_task(done)",
|
|
432
|
+
"Ghostty-native notifications via OSC 9 — no more Script Editor popup",
|
|
433
|
+
"device-scoped behaviors — device_id column + filter in loading",
|
|
434
|
+
"dispatch reliability — 45s boot timeout, dispatch ack signals, agent heartbeat",
|
|
435
|
+
"setup wizard headless mode + daemon health check after restart",
|
|
436
|
+
"device-scoped behaviors — add device_id column + filter on load",
|
|
437
|
+
"gateway prompt injection defense — 3-tier security hardening",
|
|
438
|
+
"add diagnostics(action=\"merge_agent_memories\") for reassigning memories across agent IDs",
|
|
439
|
+
"add task dependency tree visualization (action=dependency_tree)",
|
|
440
|
+
"graceful COO auto-relaunch after context-full exit",
|
|
441
|
+
"desktop push notifications on task completion (macOS/Linux)",
|
|
442
|
+
"rename GHCR image exed → exe-os across all deploy/stack references",
|
|
443
|
+
"passive daemon-restart detection — agents get one-time /mcp notice",
|
|
444
|
+
"daemon restart orchestrator — single authority for all restart decisions"
|
|
445
445
|
],
|
|
446
446
|
"fixes": [
|
|
447
|
-
"
|
|
448
|
-
"
|
|
449
|
-
"
|
|
450
|
-
"
|
|
451
|
-
"
|
|
452
|
-
"
|
|
453
|
-
"
|
|
454
|
-
"
|
|
455
|
-
"
|
|
456
|
-
"
|
|
457
|
-
"
|
|
458
|
-
"
|
|
459
|
-
"
|
|
460
|
-
"
|
|
461
|
-
"
|
|
462
|
-
"
|
|
463
|
-
"
|
|
464
|
-
"
|
|
465
|
-
"
|
|
466
|
-
"
|
|
467
|
-
"
|
|
468
|
-
"
|
|
469
|
-
"
|
|
470
|
-
"
|
|
471
|
-
"
|
|
447
|
+
"add memory_type to crdt-sync MemoryRecord interface — unblocks publish",
|
|
448
|
+
"session-scope daemon, push, capacity, cleanup (P0 #7-#9, #13)",
|
|
449
|
+
"include memory_type in cloud sync push/pull + fix backfill re-sync",
|
|
450
|
+
"session-scope signal file system — prevent cross-session task/review bleed",
|
|
451
|
+
"session-scope notification routing — use row.session_scope over ambient",
|
|
452
|
+
"daemon NEVER guesses session from tmux — header-only routing",
|
|
453
|
+
"3 daemon bugs — context-full TTL override, API watchdog kill-after-3, idle-kill verify",
|
|
454
|
+
"federated recall always searches code_context + graph — count threshold was useless",
|
|
455
|
+
"make cross-repo guardrail task-aware — allow multi-repo work when task scope permits",
|
|
456
|
+
"ONE postgres — replace crm-postgres with exe-db across entire stack",
|
|
457
|
+
"smart session-scoping gate + last boot cleanup leak + triage_bug docs",
|
|
458
|
+
"add shipped_version to support triage + clean platform procedures",
|
|
459
|
+
"close remaining session-scoping findings from Bob's audit",
|
|
460
|
+
"close 3 more session-scoping leaks from Bob's audit (LEAK-4, LEAK-7, LEAK-8)",
|
|
461
|
+
"close 8 session-scoping leaks — daemon ALS trust + review cleanup + close-task + inbox",
|
|
462
|
+
"correct graph column names in federated recall query",
|
|
463
|
+
"diagnostics check_update ENOENT + healthcheck timeout",
|
|
464
|
+
"review notifications never reached reviewer — signal file gate was dead code",
|
|
465
|
+
"remove osascript fallback — desktop notifications use OSC 9 only on macOS",
|
|
466
|
+
"generate valid UUIDs in projection worker stableId + add wiki.* projection",
|
|
467
|
+
"RSS backpressure + safe Metal shutdown for embedding daemon OOM",
|
|
468
|
+
"multi-Tom dispatch — per-task signal files + atomic claim + herd prevention",
|
|
469
|
+
"restrict project_name='all' to coordinators only in list_tasks",
|
|
470
|
+
"CRM Dockerfile multi-arch — BUILDPLATFORM for build stages, rebuild bcrypt",
|
|
471
|
+
"enhance intercom log with caller/task/trigger metadata for tracing"
|
|
472
472
|
],
|
|
473
473
|
"security": [
|
|
474
474
|
"fix shell injection, SSRF, socket leaks, backup validation",
|
|
@@ -485,7 +485,18 @@
|
|
|
485
485
|
"fix 4 pricing tier bypass vulnerabilities (audit F1-F4)"
|
|
486
486
|
],
|
|
487
487
|
"other": [
|
|
488
|
+
"capture data pipeline spec — raw → filter → wiki + CRM projection",
|
|
489
|
+
"bump to v0.9.149 — task lifecycle simplification + review notification fix",
|
|
490
|
+
"capture gateway connection observability requirements (2026-05-28)",
|
|
491
|
+
"bump to v0.9.146 for publish",
|
|
492
|
+
"Windows support architecture — WezTerm + WSL decision (2026-05-27)",
|
|
493
|
+
"Merge branch 'tom4-work' — device-scoped behaviors + push-notification fix",
|
|
494
|
+
"bump to v0.9.145 for publish",
|
|
495
|
+
"revert: keep workflow files unchanged — GitHub OAuth blocks workflow scope",
|
|
496
|
+
"stage remaining Yoshi fixes — features + bug cleanup",
|
|
497
|
+
"add tests for daemon restart orchestrator module",
|
|
488
498
|
"publish v0.9.144 — ESM require() fix + reliable task signals + OAuth 2.1",
|
|
499
|
+
"add MCP tool tests for message, cloud-sync, and file-copy",
|
|
489
500
|
"add coverage for send_message, cloud_sync, file_copy MCP tools (Track A)",
|
|
490
501
|
"Recover MCP sessions after daemon restart",
|
|
491
502
|
"publish v0.9.143 — all fixes live",
|
|
@@ -498,18 +509,7 @@
|
|
|
498
509
|
"add lint step + automated npm publish workflow",
|
|
499
510
|
"audit: scoped SQL + package budget + TUI vendored + TODO classification",
|
|
500
511
|
"add full readiness audit evidence",
|
|
501
|
-
"roadmap: Cross-Repo Ontology — Palantir-level graph (PG-1 through PG-10)"
|
|
502
|
-
"capture mcp restart self-healing roadmap",
|
|
503
|
-
"Enforce chain of command task review parity",
|
|
504
|
-
"document raw SQL fallback in orchestrator auto-approve path",
|
|
505
|
-
"Finalize orchestration rollout fixes",
|
|
506
|
-
"Scope device governance task queries",
|
|
507
|
-
"bump v0.9.138 — 7 critical bug fixes, 10 features, 16 commits",
|
|
508
|
-
"bump v0.9.137 — Memanto typed schema, push notifications, lazy consolidation",
|
|
509
|
-
"bump v0.9.136 — daemon OOM fix, process monitor, auto-notify reviewer",
|
|
510
|
-
"bump v0.9.135 — code debt cleanup, 28 new tests, full observability",
|
|
511
|
-
"Codex MCP regression tests (18) + DB singleton integration tests (10)",
|
|
512
|
-
"release notes for v0.9.134"
|
|
512
|
+
"roadmap: Cross-Repo Ontology — Palantir-level graph (PG-1 through PG-10)"
|
|
513
513
|
],
|
|
514
514
|
"migration_notes": [
|
|
515
515
|
"If daemon goes down, agents will now fail instead of silently",
|