@askexenow/exe-os 0.9.290 → 0.9.292
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/.env.customer.example +14 -1
- package/deploy/compose/.env.example +40 -1
- package/deploy/compose/backup.sh +147 -42
- package/deploy/compose/docker-compose.yml +128 -51
- package/deploy/compose/generate-env.ts +31 -0
- package/deploy/compose/setup.sh +11 -2
- package/dist/active-agent-5DCUU6QR.js +28 -0
- package/dist/active-agent-JTTDI66I.js +27 -0
- package/dist/active-agent-NQAHMQSR.js +27 -0
- package/dist/active-agent-QHGHLMYS.js +28 -0
- package/dist/agentic-ontology-7RXZLSZY.js +25 -0
- package/dist/agentic-ontology-BSSNX24R.js +25 -0
- package/dist/backfill-metadata-5I3PAO66.js +600 -0
- package/dist/backfill-metadata-F3KEE7WZ.js +600 -0
- package/dist/background-jobs-PUXOTBD4.js +25 -0
- package/dist/behaviors-AJFFFXT2.js +40 -0
- package/dist/behaviors-RXUKZLER.js +40 -0
- package/dist/bin/age-ontology-load.js +2 -2
- package/dist/bin/agentic-ontology-backfill.js +8 -7
- package/dist/bin/agentic-reflection-backfill.js +9 -8
- package/dist/bin/agentic-semantic-label.js +8 -7
- package/dist/bin/backfill-conversations.js +8 -7
- package/dist/bin/backfill-responses.js +8 -7
- package/dist/bin/backfill-vectors.js +11 -10
- package/dist/bin/bulk-sync-postgres.js +9 -8
- package/dist/bin/cc-doctor.js +7 -6
- package/dist/bin/cleanup-stale-review-tasks.js +13 -12
- package/dist/bin/cli.js +20 -20
- package/dist/bin/exe-agent-config.js +5 -4
- package/dist/bin/exe-agent.js +10 -9
- package/dist/bin/exe-assign.js +10 -9
- package/dist/bin/exe-boot.js +20 -19
- package/dist/bin/exe-call.js +6 -5
- package/dist/bin/exe-cloud.js +8 -7
- package/dist/bin/exe-dispatch.js +13 -12
- package/dist/bin/exe-doctor.js +2 -1
- package/dist/bin/exe-export-behaviors.js +9 -8
- package/dist/bin/exe-forget.js +8 -7
- package/dist/bin/exe-gateway.js +9 -8
- package/dist/bin/exe-healthcheck.js +11 -6
- package/dist/bin/exe-heartbeat.js +13 -12
- package/dist/bin/exe-kill.js +16 -15
- package/dist/bin/exe-launch-agent.js +20 -19
- package/dist/bin/exe-new-employee.js +9 -8
- package/dist/bin/exe-pending-messages.js +14 -13
- package/dist/bin/exe-pending-notifications.js +13 -12
- package/dist/bin/exe-pending-reviews.js +13 -12
- package/dist/bin/exe-rename.js +6 -5
- package/dist/bin/exe-review.js +15 -14
- package/dist/bin/exe-search.js +7 -6
- package/dist/bin/exe-session-cleanup.js +18 -17
- package/dist/bin/exe-settings.js +8 -7
- package/dist/bin/exe-start-codex.js +13 -12
- package/dist/bin/exe-start-opencode.js +10 -9
- package/dist/bin/exe-status.js +14 -13
- package/dist/bin/exe-support.js +3 -3
- package/dist/bin/exe-team.js +5 -4
- package/dist/bin/exe-watchdog.js +34 -1
- package/dist/bin/git-sweep.js +14 -13
- package/dist/bin/graph-backfill.js +8 -7
- package/dist/bin/graph-export.js +7 -6
- package/dist/bin/import-history.js +10 -9
- package/dist/bin/install-launchd.js +19 -1
- package/dist/bin/install.js +9 -8
- package/dist/bin/intercom-check.js +4 -4
- package/dist/bin/mcp-sessions.js +2 -2
- package/dist/bin/orchestration-metrics.js +6 -5
- package/dist/bin/postgres-agentic-reflection-backfill.js +4 -4
- package/dist/bin/postgres-agentic-semantic-backfill.js +3 -3
- package/dist/bin/scan-tasks.js +13 -12
- package/dist/bin/setup.js +2 -2
- package/dist/bin/shard-migrate.js +7 -6
- package/dist/bin/stack-update.js +4 -4
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/branding-RBMRJA5D.js +97 -0
- package/dist/capability-cards-DCWQI3NN.js +89 -0
- package/dist/capability-cards-TQVKK6TE.js +89 -0
- package/dist/capacity-monitor-7YZOMMMP.js +51 -0
- package/dist/capacity-monitor-S6GFT45S.js +51 -0
- package/dist/catchup-brief-DK7OD5DJ.js +175 -0
- package/dist/catchup-brief-J27L7LKR.js +175 -0
- package/dist/catchup-brief-JLMK2IP5.js +175 -0
- package/dist/chunk-2664Y4WA.js +14503 -0
- package/dist/chunk-2FTHXF6X.js +150 -0
- package/dist/chunk-2H2SCCA7.js +221 -0
- package/dist/chunk-2ISUEARV.js +76 -0
- package/dist/chunk-2RU66KAN.js +456 -0
- package/dist/chunk-2SI5Z24A.js +284 -0
- package/dist/chunk-2V6AASHE.js +668 -0
- package/dist/chunk-2ZMQI2J4.js +85 -0
- package/dist/chunk-3ET3QGXG.js +70 -0
- package/dist/chunk-3V6KXHSV.js +203 -0
- package/dist/chunk-3VT5IG2G.js +14439 -0
- package/dist/chunk-3YHG7W74.js +362 -0
- package/dist/chunk-434Z2LFO.js +30 -0
- package/dist/chunk-44SWZWGS.js +231 -0
- package/dist/chunk-4DFENB7E.js +128 -0
- package/dist/chunk-4EA3J7SE.js +333 -0
- package/dist/chunk-4JY5DRY2.js +1350 -0
- package/dist/chunk-5BUPY2ZC.js +81 -0
- package/dist/chunk-5FIQBJ5I.js +735 -0
- package/dist/chunk-5MQ4RUUP.js +244 -0
- package/dist/chunk-6CTHQKUS.js +1186 -0
- package/dist/chunk-6GEEAOFU.js +538 -0
- package/dist/chunk-6JOF37K6.js +1352 -0
- package/dist/chunk-6OAAN25C.js +727 -0
- package/dist/chunk-6S6QFQ33.js +382 -0
- package/dist/chunk-6U2BFODG.js +227 -0
- package/dist/chunk-76QWODZW.js +1119 -0
- package/dist/chunk-7BNDOTRZ.js +1094 -0
- package/dist/chunk-7HBACWKV.js +128 -0
- package/dist/chunk-7IWWRNJI.js +333 -0
- package/dist/chunk-7MH7VI6T.js +280 -0
- package/dist/chunk-7QKQE7J4.js +70 -0
- package/dist/chunk-7U4JXDBV.js +284 -0
- package/dist/chunk-7UF4323L.js +50 -0
- package/dist/chunk-7UUJMSFH.js +348 -0
- package/dist/chunk-7YEOKPZ6.js +185 -0
- package/dist/chunk-7Z3P23BX.js +244 -0
- package/dist/chunk-BK42Z2SX.js +1186 -0
- package/dist/chunk-BREJRA7B.js +171 -0
- package/dist/chunk-C3FMNIJT.js +94 -0
- package/dist/chunk-CCNSV7J5.js +128 -0
- package/dist/chunk-CKFT7GM6.js +128 -0
- package/dist/chunk-CRCB5S7I.js +454 -0
- package/dist/chunk-CSMTQ24E.js +97 -0
- package/dist/chunk-CSXNLHUU.js +185 -0
- package/dist/chunk-D3ELJGEI.js +97 -0
- package/dist/chunk-D6CCJVTB.js +214 -0
- package/dist/chunk-DEVITBD5.js +1079 -0
- package/dist/chunk-DKIFBCKT.js +157 -0
- package/dist/chunk-DRUPHYRL.js +286 -0
- package/dist/chunk-E4XU7EVT.js +1350 -0
- package/dist/chunk-EEZNLI6L.js +240 -0
- package/dist/chunk-EIA6LRM4.js +38 -0
- package/dist/chunk-FBIXI7WC.js +382 -0
- package/dist/chunk-FSQTZ57R.js +4349 -0
- package/dist/chunk-FW75WOTA.js +97 -0
- package/dist/chunk-GDSV52EC.js +85 -0
- package/dist/chunk-GMZTZ4KQ.js +345 -0
- package/dist/chunk-GNKHK5VD.js +1068 -0
- package/dist/chunk-GP3ZHQJO.js +362 -0
- package/dist/chunk-GSVK66OV.js +58 -0
- package/dist/chunk-GY2BY5VF.js +58 -0
- package/dist/chunk-HNDG5ZDJ.js +336 -0
- package/dist/chunk-HTD4AJUF.js +85 -0
- package/dist/chunk-HTU7RDZA.js +127 -0
- package/dist/chunk-HX4PBMY3.js +227 -0
- package/dist/chunk-IC2PIVLM.js +181 -0
- package/dist/chunk-IK3Q7NLP.js +2113 -0
- package/dist/chunk-IL5FQSUQ.js +2142 -0
- package/dist/chunk-ITWU5LJL.js +85 -0
- package/dist/chunk-IUIVLCAO.js +369 -0
- package/dist/chunk-JHJUV633.js +150 -0
- package/dist/chunk-JXOXGBC2.js +262 -0
- package/dist/chunk-KG55JL2G.js +604 -0
- package/dist/chunk-KGT7VT77.js +167 -0
- package/dist/chunk-L2DMZT56.js +210 -0
- package/dist/chunk-L57H26UP.js +33 -0
- package/dist/chunk-L5E3RXLR.js +197 -0
- package/dist/chunk-L5O4MFMV.js +402 -0
- package/dist/chunk-LAB3RQRN.js +204 -0
- package/dist/chunk-LCOPVYU2.js +3293 -0
- package/dist/chunk-LDI633LO.js +2078 -0
- package/dist/chunk-LJONNOFH.js +336 -0
- package/dist/chunk-LKM56CDI.js +2078 -0
- package/dist/chunk-LPO7KLSP.js +14470 -0
- package/dist/chunk-M46T2E3A.js +262 -0
- package/dist/chunk-MBJYQBUX.js +456 -0
- package/dist/chunk-MEWGYH6Z.js +190 -0
- package/dist/chunk-MHGR5CRN.js +731 -0
- package/dist/chunk-MR64FIZU.js +735 -0
- package/dist/chunk-MTRUOIND.js +159 -0
- package/dist/chunk-MUDCJP6B.js +68 -0
- package/dist/chunk-MUQ46NLH.js +3293 -0
- package/dist/chunk-MYVGG2VW.js +204 -0
- package/dist/chunk-NEFF4ATD.js +197 -0
- package/dist/chunk-NOC7GUHJ.js +836 -0
- package/dist/chunk-NOP22U7I.js +33 -0
- package/dist/chunk-OGFEQ264.js +448 -0
- package/dist/chunk-OGV67HHE.js +230 -0
- package/dist/chunk-OQ3CC5N2.js +54 -0
- package/dist/chunk-OTANU4LT.js +297 -0
- package/dist/chunk-P5A77YDA.js +58 -0
- package/dist/chunk-PIOBPKYE.js +377 -0
- package/dist/chunk-POEI5ZRV.js +731 -0
- package/dist/chunk-PS4W2VGW.js +129 -0
- package/dist/chunk-PT3URNVT.js +836 -0
- package/dist/chunk-Q4IL3S44.js +55 -0
- package/dist/chunk-QEDM5BJW.js +240 -0
- package/dist/chunk-QGYRNG7T.js +129 -0
- package/dist/chunk-QHNGZ6X2.js +538 -0
- package/dist/chunk-QOZQ2MYZ.js +42 -0
- package/dist/chunk-QPYEVLED.js +402 -0
- package/dist/chunk-QRTJNSKU.js +133 -0
- package/dist/chunk-R36FAN53.js +488 -0
- package/dist/chunk-R426G4MO.js +290 -0
- package/dist/chunk-RG4OHDY7.js +348 -0
- package/dist/chunk-RHNSYJCT.js +30 -0
- package/dist/chunk-RKYLET7V.js +1352 -0
- package/dist/chunk-RLSEMHP7.js +369 -0
- package/dist/chunk-ROGL26Q2.js +630 -0
- package/dist/chunk-RTC3JHFF.js +345 -0
- package/dist/chunk-RV62SMCL.js +171 -0
- package/dist/chunk-SC4MQTMY.js +192 -0
- package/dist/chunk-SCT6IMMD.js +630 -0
- package/dist/chunk-SOTS4FXN.js +546 -0
- package/dist/chunk-STS5552V.js +448 -0
- package/dist/chunk-SY65TI5X.js +424 -0
- package/dist/chunk-T67ELIV6.js +38 -0
- package/dist/chunk-TBSYE2WW.js +97 -0
- package/dist/chunk-TGRGBM7C.js +1094 -0
- package/dist/chunk-TGTJYERN.js +621 -0
- package/dist/chunk-THWAU77X.js +290 -0
- package/dist/chunk-TM7NUOZ7.js +574 -0
- package/dist/chunk-TNZWNC4O.js +106 -0
- package/dist/chunk-TRSYK4HA.js +1352 -0
- package/dist/chunk-TZIGQLY7.js +123 -0
- package/dist/chunk-U7PCRZEB.js +286 -0
- package/dist/chunk-UCBIETEA.js +373 -0
- package/dist/chunk-UGH4Z3BT.js +50 -0
- package/dist/chunk-UKRCNA3D.js +127 -0
- package/dist/chunk-ULUNIZOZ.js +2113 -0
- package/dist/chunk-UWTIDBMQ.js +411 -0
- package/dist/chunk-VJTS6RGD.js +81 -0
- package/dist/chunk-VLE2Z4JK.js +411 -0
- package/dist/chunk-VOGYUVYX.js +4349 -0
- package/dist/chunk-VPQAXUG4.js +210 -0
- package/dist/chunk-W3TXZRGP.js +1186 -0
- package/dist/chunk-WQKB25AU.js +1119 -0
- package/dist/chunk-WTEVY2WF.js +122 -0
- package/dist/chunk-X5CTZH7W.js +76 -0
- package/dist/chunk-XCZP6I5M.js +167 -0
- package/dist/chunk-XP3DCIAH.js +181 -0
- package/dist/chunk-XRN5MQRN.js +373 -0
- package/dist/chunk-XZXY66KH.js +123 -0
- package/dist/chunk-Y2SP7JYR.js +668 -0
- package/dist/chunk-Y5ZF5OFM.js +280 -0
- package/dist/chunk-YN7XRPQ6.js +546 -0
- package/dist/chunk-YQOOELC3.js +221 -0
- package/dist/chunk-YTKVJJSU.js +379 -0
- package/dist/chunk-YZJZXBPL.js +192 -0
- package/dist/chunk-Z2XRD6SJ.js +377 -0
- package/dist/chunk-ZBD56XE2.js +122 -0
- package/dist/chunk-ZE2XPYEC.js +299 -0
- package/dist/chunk-ZE4E4PMM.js +157 -0
- package/dist/chunk-ZIY6HVAD.js +214 -0
- package/dist/chunk-ZK4VCLCK.js +176 -0
- package/dist/chunk-ZOBV6QWD.js +54 -0
- package/dist/chunk-ZTGID7RE.js +1068 -0
- package/dist/co-activation-BOHQZWKI.js +74 -0
- package/dist/co-activation-KSBQKWYV.js +74 -0
- package/dist/co-occurrence-OSJQ2XQO.js +95 -0
- package/dist/co-occurrence-YKTIFNYA.js +95 -0
- package/dist/code-context-index-43MNXX4H.js +30 -0
- package/dist/conversation-entity-extractor-6PJUN5DP.js +114 -0
- package/dist/conversation-wiki-populator-PDL2SUZJ.js +105 -0
- package/dist/core-memory-TU636T4D.js +110 -0
- package/dist/core-memory-U74QUX6H.js +110 -0
- package/dist/crdt-sync-JTTYSLBV.js +33 -0
- package/dist/crdt-sync-UG3532QN.js +33 -0
- package/dist/crm-webhook-D5JCLN2M.js +10 -0
- package/dist/crm-webhook-Y2BDCVPM.js +10 -0
- package/dist/cto-delegation-gate-7TJT5EOE.js +280 -0
- package/dist/cto-delegation-gate-DCIFDJDX.js +280 -0
- package/dist/daemon-auth-CBMX4H6L.js +13 -0
- package/dist/daemon-orchestration-D5MFCNVH.js +139 -0
- package/dist/daemon-orchestration-XSDZPGYX.js +139 -0
- package/dist/db-backup-77QYAXID.js +37 -0
- package/dist/db-backup-LJVPP5AS.js +37 -0
- package/dist/db-restore-events-GNZS42YO.js +76 -0
- package/dist/doc-graph-extractor-3PI2M2LX.js +133 -0
- package/dist/doc-graph-extractor-CJU6HR2C.js +133 -0
- package/dist/dreaming-5A4MKONF.js +34 -0
- package/dist/dreaming-RFRHTYFN.js +34 -0
- package/dist/entity-boost-WXSBSZW4.js +375 -0
- package/dist/exe-drift-HBLGPMBH.js +70 -0
- package/dist/exe-drift-K7HAX5N4.js +70 -0
- package/dist/exe-export-JSJOEDBE.js +76 -0
- package/dist/exe-export-YVZMMVZZ.js +76 -0
- package/dist/exe-import-BO2GU36V.js +79 -0
- package/dist/exe-import-S6O6JTAB.js +79 -0
- package/dist/exe-key-5C5FYDC7.js +673 -0
- package/dist/exe-key-QVPXEUTV.js +673 -0
- package/dist/exe-org-35QVSGCM.js +73 -0
- package/dist/exe-snapshot-6MFTRMI5.js +338 -0
- package/dist/exe-snapshot-OFWZY3CY.js +338 -0
- package/dist/fast-db-init-E64KKZS2.js +7 -0
- package/dist/fast-db-init-ZSRLXT5Y.js +7 -0
- package/dist/founder-context-QAAWZEZM.js +96 -0
- package/dist/gateway/index.js +13 -12
- package/dist/git-staleness-3PLBSHA3.js +112 -0
- package/dist/git-staleness-XPWBDY2Q.js +112 -0
- package/dist/git-task-sweep-C5DM7CJS.js +42 -0
- package/dist/git-task-sweep-G2MKIFGS.js +42 -0
- package/dist/global-procedures-CGXY2AVS.js +22 -0
- package/dist/global-procedures-WLVOTD2Y.js +22 -0
- package/dist/graph-auto-extract-SAE3GKG5.js +183 -0
- package/dist/graph-auto-extract-ZLKCPSPD.js +183 -0
- package/dist/graph-query-AP5R6ZHO.js +28 -0
- package/dist/graph-rag-ZCJ4X7YL.js +35 -0
- package/dist/hook-integrity-A3NDG7EB.js +89 -0
- package/dist/hooks/bug-report-worker.js +15 -14
- package/dist/hooks/codex-stop-task-finalizer.js +15 -14
- package/dist/hooks/commit-complete.js +16 -15
- package/dist/hooks/error-recall.js +9 -8
- package/dist/hooks/exe-heartbeat-hook.js +6 -5
- package/dist/hooks/ingest-worker.js +5 -5
- package/dist/hooks/ingest.js +13 -12
- package/dist/hooks/instructions-loaded.js +7 -6
- package/dist/hooks/manifest.json +20 -20
- package/dist/hooks/notification.js +7 -6
- package/dist/hooks/post-compact.js +15 -14
- package/dist/hooks/post-tool-combined.js +7 -7
- package/dist/hooks/pre-compact.js +20 -19
- package/dist/hooks/pre-tool-use.js +28 -20
- package/dist/hooks/prompt-submit.js +28 -27
- package/dist/hooks/session-end.js +25 -24
- package/dist/hooks/session-start.js +27 -16
- package/dist/hooks/stop.js +22 -21
- package/dist/hooks/subagent-stop.js +20 -14
- package/dist/hooks/summary-worker.js +22 -21
- package/dist/index.js +23 -22
- package/dist/installer-ALESUE7P.js +298 -0
- package/dist/installer-APCDG6FF.js +40 -0
- package/dist/installer-BYIQKENA.js +40 -0
- package/dist/installer-JNHPJNO2.js +344 -0
- package/dist/installer-KWTPZCUH.js +40 -0
- package/dist/installer-MUKDPCXL.js +344 -0
- package/dist/installer-NR636CAL.js +298 -0
- package/dist/installer-O2S3ZLAH.js +344 -0
- package/dist/installer-T5XSDLBK.js +298 -0
- package/dist/key-backup-status-2EPRIAXU.js +39 -0
- package/dist/lib/agent-config.js +2 -2
- package/dist/lib/cloud-sync.js +7 -6
- package/dist/lib/config.js +1 -1
- package/dist/lib/consolidation.js +8 -7
- package/dist/lib/database.js +4 -3
- package/dist/lib/db-daemon-client.js +3 -3
- package/dist/lib/db.js +4 -3
- package/dist/lib/device-registry.js +1 -1
- package/dist/lib/embed-worker.js +6 -4
- package/dist/lib/embedder.js +4 -4
- package/dist/lib/employee-templates.js +6 -5
- package/dist/lib/employees.js +4 -3
- package/dist/lib/exe-daemon-client.js +3 -3
- package/dist/lib/exe-daemon.js +164 -63
- package/dist/lib/hybrid-search.js +7 -6
- package/dist/lib/identity.js +4 -3
- package/dist/lib/license.js +2 -2
- package/dist/lib/messaging.js +13 -12
- package/dist/lib/reminders.js +5 -4
- package/dist/lib/schedules.js +7 -6
- package/dist/lib/session-registry.js +10 -5
- package/dist/lib/skill-learning.js +8 -7
- package/dist/lib/store.js +6 -5
- package/dist/lib/task-router.js +5 -4
- package/dist/lib/tasks.js +14 -13
- package/dist/lib/tmux-routing.js +12 -11
- package/dist/lib/token-spend.js +5 -4
- package/dist/license-gate-O2LLJ6LS.js +16 -0
- package/dist/mcp/register-tools.js +69 -69
- package/dist/mcp/server.js +121 -90
- package/dist/mcp/tools/complete-reminder.js +6 -5
- package/dist/mcp/tools/create-reminder.js +6 -5
- package/dist/mcp/tools/create-task.js +16 -15
- package/dist/mcp/tools/deactivate-behavior.js +9 -8
- package/dist/mcp/tools/list-reminders.js +6 -5
- package/dist/mcp/tools/list-tasks.js +16 -15
- package/dist/mcp/tools/send-message.js +15 -14
- package/dist/mcp/tools/update-task.js +15 -14
- package/dist/mcp-http-config-XI53TYZL.js +29 -0
- package/dist/mcp-http-config-YQ3KWB73.js +29 -0
- package/dist/memory-cards-2F6RFUT5.js +180 -0
- package/dist/memory-cards-LLUWHHT3.js +180 -0
- package/dist/memory-graph-extractor-IT6HYWWM.js +22 -0
- package/dist/memory-graph-extractor-LZUQWU7P.js +22 -0
- package/dist/memory-poisoning-defense-45AMNLDK.js +224 -0
- package/dist/memory-poisoning-defense-FFO3YUFP.js +224 -0
- package/dist/memory-queue-HSHWXVZC.js +19 -0
- package/dist/memory-queue-client-AJ2WHEEE.js +16 -0
- package/dist/memory-reflection-JGA6ULGJ.js +244 -0
- package/dist/memory-reflection-ZT4ST2SS.js +244 -0
- package/dist/message-queue-client-SANA7URQ.js +92 -0
- package/dist/notifications-S5QQ3SBU.js +47 -0
- package/dist/notifications-YBJCZJDR.js +47 -0
- package/dist/oauth-server-VEMBOSS3.js +437 -0
- package/dist/orchestration-events-CYDARUFL.js +27 -0
- package/dist/orchestration-events-F67I3TG6.js +27 -0
- package/dist/orchestration-phase-EMDEZHIU.js +23 -0
- package/dist/orchestrator-B4CUAA7M.js +35 -0
- package/dist/orchestrator-GBONJR6S.js +35 -0
- package/dist/pipeline-router-FKCP3RCU.js +15 -0
- package/dist/pipeline-router-LIQTRMQW.js +15 -0
- package/dist/plan-limits-BQ2CEB66.js +28 -0
- package/dist/plan-limits-H63HOJ4H.js +28 -0
- package/dist/project-boot-4CLI3CLL.js +299 -0
- package/dist/project-boot-VSMQJDDI.js +299 -0
- package/dist/projection-worker-55EFFXOK.js +1084 -0
- package/dist/projection-worker-IQ55BIX7.js +1084 -0
- package/dist/prospective-memory-E7WBD5V4.js +232 -0
- package/dist/prospective-memory-GE7TW6EW.js +232 -0
- package/dist/push-notifications-CV5UD5CC.js +15 -0
- package/dist/reranker-PZWHSEGQ.js +19 -0
- package/dist/reranker-WSJEPXIY.js +19 -0
- package/dist/reranker-ZBN2GKIO.js +19 -0
- package/dist/retrieval-health-HBFTJ5M3.js +11 -0
- package/dist/retrieval-health-M2OE7USG.js +11 -0
- package/dist/review-polling-BBOASCWL.js +126 -0
- package/dist/review-polling-WTJZTCTD.js +126 -0
- package/dist/runtime/index.js +19 -18
- package/dist/session-events-POJ3YCUQ.js +38 -0
- package/dist/session-events-QVNSNSQN.js +38 -0
- package/dist/session-kill-telemetry-65TJ5XV7.js +31 -0
- package/dist/session-kill-telemetry-OC34JTYX.js +31 -0
- package/dist/session-scope-3WDVXSJH.js +88 -0
- package/dist/session-scope-KRQL3PIP.js +88 -0
- package/dist/setup-wizard-FE2MBSZS.js +12 -0
- package/dist/setup-wizard-UUAEUY3X.js +12 -0
- package/dist/shard-manager-P5ZJH4AX.js +30 -0
- package/dist/skill-refinement-5MCWYJW4.js +159 -0
- package/dist/skill-refinement-TRSMFCKK.js +159 -0
- package/dist/stack-update-OGFSAV6F.js +80 -0
- package/dist/steward-gate-L43S6CSV.js +15 -0
- package/dist/steward-gate-LCR46RJV.js +15 -0
- package/dist/support-outbox-QPQQK7F7.js +547 -0
- package/dist/task-enforcement-DRWNGNLH.js +506 -0
- package/dist/task-enforcement-STQBU5AM.js +506 -0
- package/dist/task-scope-A2IJJQQS.js +37 -0
- package/dist/task-scope-X3JOBCZV.js +37 -0
- package/dist/tasks-crud-66VBOQTI.js +79 -0
- package/dist/tasks-crud-ZD24ZQOL.js +79 -0
- package/dist/tasks-notify-EPWV6YRP.js +40 -0
- package/dist/tasks-notify-GHPMBTB3.js +40 -0
- package/dist/tasks-review-P6ZVW3ZV.js +49 -0
- package/dist/tasks-review-VXJVJ7ZT.js +49 -0
- package/dist/telemetry-upload-KCE2IT6P.js +741 -0
- package/dist/telemetry-upload-ZNAMKKNS.js +741 -0
- package/dist/token-budget-GHUZSDOD.js +86 -0
- package/dist/token-budget-O7B4NGY3.js +86 -0
- package/dist/tool-capability-index-3OZFBAC3.js +10 -0
- package/dist/tool-telemetry-EWAC3F75.js +17 -0
- package/dist/tool-telemetry-IO6L62QY.js +17 -0
- package/dist/tui/App.js +25 -24
- package/dist/tui-data-2KSB36YG.js +260 -0
- package/dist/tui-data-YVJ72ZVD.js +260 -0
- package/dist/webhook-pipe-PAPBITL4.js +114 -0
- package/dist/wiki-acl-HTRRAQGV.js +111 -0
- package/dist/wiki-acl-MNG2ROWJ.js +111 -0
- package/dist/wiki-client-Q4O6EMTP.js +157 -0
- package/dist/worker-gate-EVQTUUIF.js +21 -0
- package/dist/worker-gate-XKPDQQY4.js +21 -0
- package/dist/workflow-engine-JYGEDGTL.js +28 -0
- package/dist/workflow-engine-UBTXKWRV.js +28 -0
- package/dist/worktree-VPSXFHXP.js +28 -0
- package/dist/worktree-ZH5AT35X.js +28 -0
- package/dist/worktree-sweep-BIUP4BGY.js +21 -0
- package/dist/worktree-sweep-KEHR4NFP.js +21 -0
- package/package.json +2 -2
- package/release-notes.json +101 -101
- package/stack.release.json +8 -0
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
# Copy to .env before deployment and replace every CHANGEME_* value.
|
|
3
3
|
# Values under # SET_MANUALLY must be provided by the operator.
|
|
4
4
|
|
|
5
|
+
# --- Domain ---
|
|
6
|
+
# Customer apex domain. Drives auth gateway templating and GoTrue From address.
|
|
7
|
+
DOMAIN=CHANGEME_DOMAIN
|
|
8
|
+
|
|
5
9
|
# --- Data Layer ---
|
|
6
10
|
POSTGRES_USER=exe
|
|
7
11
|
POSTGRES_PASSWORD=CHANGEME_POSTGRES_PASSWORD
|
|
@@ -18,8 +22,17 @@ GOTRUE_JWT_SECRET=CHANGEME_GOTRUE_JWT_SECRET
|
|
|
18
22
|
GOTRUE_API_PORT=9999
|
|
19
23
|
GOTRUE_SITE_URL=https://crm.CHANGEME_DOMAIN
|
|
20
24
|
GOTRUE_EXTERNAL_URL=https://auth.CHANGEME_DOMAIN
|
|
25
|
+
# SSO redirect allow-list (bug 66f8e10a) — app origins for unified SSO.
|
|
26
|
+
GOTRUE_URI_ALLOW_LIST=https://crm.CHANGEME_DOMAIN,https://wiki.CHANGEME_DOMAIN,https://erp.CHANGEME_DOMAIN
|
|
21
27
|
GOTRUE_DISABLE_SIGNUP=true
|
|
22
28
|
GOTRUE_MAILER_AUTOCONFIRM=false
|
|
29
|
+
# Auth-email From address — customer domain, not askexe.com (bug 133c9d5b).
|
|
30
|
+
SMTP_FROM=noreply@CHANGEME_DOMAIN
|
|
31
|
+
# To enable verified email confirmation, set SMTP_* (MAILER_AUTOCONFIRM stays false).
|
|
32
|
+
SMTP_HOST=
|
|
33
|
+
SMTP_PORT=587
|
|
34
|
+
SMTP_USER=
|
|
35
|
+
SMTP_PASS=
|
|
23
36
|
|
|
24
37
|
# --- CRM ---
|
|
25
38
|
CRM_IMAGE_TAG=update.askexe.com/askexe/exe-crm:v0.9.47
|
|
@@ -48,7 +61,7 @@ EXE_MCP_HOST_PORT=48739
|
|
|
48
61
|
EXE_CLOUD_SYNC_TO_POSTGRES=true
|
|
49
62
|
|
|
50
63
|
# --- ERP (Frappe/ERPNext fork) ---
|
|
51
|
-
ERP_IMAGE_TAG=update.askexe.com/askexe/exe-erp:v0.2.0-
|
|
64
|
+
ERP_IMAGE_TAG=update.askexe.com/askexe/exe-erp:v0.2.0-final8
|
|
52
65
|
# Administrator password for the ERPNext site (created on first boot).
|
|
53
66
|
ERP_ADMIN_PASSWORD=CHANGEME_ERP_ADMIN_PASSWORD
|
|
54
67
|
ERP_SITE_NAME=erp.askexe.com
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
# Copy to .env before deployment and replace every CHANGEME_* value.
|
|
3
3
|
# Values under # SET_MANUALLY must be provided by the operator.
|
|
4
4
|
|
|
5
|
+
# --- Domain ---
|
|
6
|
+
# Customer apex domain. Drives auth gateway templating and GoTrue From address.
|
|
7
|
+
DOMAIN=CHANGEME_DOMAIN
|
|
8
|
+
|
|
5
9
|
# --- Data Layer ---
|
|
6
10
|
POSTGRES_USER=exe
|
|
7
11
|
POSTGRES_PASSWORD=CHANGEME_POSTGRES_PASSWORD
|
|
@@ -13,13 +17,48 @@ CLICKHOUSE_PASSWORD=CHANGEME_CLICKHOUSE_PASSWORD
|
|
|
13
17
|
|
|
14
18
|
REDIS_PASSWORD=CHANGEME_REDIS_PASSWORD
|
|
15
19
|
|
|
20
|
+
# --- Backups (bug 56a71515 off-box, fc71e7ca failure handling) ---
|
|
21
|
+
# Off-box upload: the daily cron runs `backup.sh --upload-r2`. Without this the
|
|
22
|
+
# encrypted archive only ever lands on the same disk as live data (disk death =
|
|
23
|
+
# total loss). R2 creds are reused from the R2_MEDIA_* vars when set.
|
|
24
|
+
# EXE_BACKUP_KEY=CHANGEME_EXE_BACKUP_KEY # 256-bit key — encrypts archives at rest
|
|
25
|
+
BACKUP_RETENTION_DAYS=7
|
|
26
|
+
# Override the DB container name if your topology differs (default: exe-db).
|
|
27
|
+
# BACKUP_DB_CONTAINER=exe-db
|
|
28
|
+
# Failure alerting (no silent success). Set either/both:
|
|
29
|
+
# BACKUP_ALERT_WEBHOOK — POST {host,stage,message} on any backup failure
|
|
30
|
+
# BACKUP_HEALTHCHECK_URL — ping on success, <url>/fail on failure (healthchecks.io)
|
|
31
|
+
# BACKUP_ALERT_WEBHOOK=
|
|
32
|
+
# BACKUP_HEALTHCHECK_URL=
|
|
33
|
+
|
|
34
|
+
# WAL archiving / Point-In-Time Recovery (bug 5176aa4e) — OPT-IN.
|
|
35
|
+
# Defaults below keep the stack booting exactly as before (archive_mode=off,
|
|
36
|
+
# RPO = nightly pg_dump). Set PG_ARCHIVE_MODE=on to enable continuous WAL
|
|
37
|
+
# archiving into the pg_wal_archive volume; back that volume off-box for PITR.
|
|
38
|
+
# PG_ARCHIVE_MODE=off
|
|
39
|
+
# PG_WAL_LEVEL=replica
|
|
40
|
+
# PG_ARCHIVE_TIMEOUT=300
|
|
41
|
+
# PG_MAX_WAL_SENDERS=3
|
|
42
|
+
# Custom archive target (e.g. push WAL straight to off-box storage). Leave unset
|
|
43
|
+
# to use the default copy into /var/lib/postgresql/wal_archive.
|
|
44
|
+
# PG_ARCHIVE_COMMAND=
|
|
45
|
+
|
|
16
46
|
# --- GoTrue (shared auth) ---
|
|
17
47
|
GOTRUE_JWT_SECRET=CHANGEME_GOTRUE_JWT_SECRET
|
|
18
48
|
GOTRUE_API_PORT=9999
|
|
19
49
|
GOTRUE_SITE_URL=https://crm.CHANGEME_DOMAIN
|
|
20
50
|
GOTRUE_EXTERNAL_URL=https://auth.CHANGEME_DOMAIN
|
|
51
|
+
# SSO redirect allow-list (bug 66f8e10a) — app origins for unified SSO.
|
|
52
|
+
GOTRUE_URI_ALLOW_LIST=https://crm.CHANGEME_DOMAIN,https://wiki.CHANGEME_DOMAIN,https://erp.CHANGEME_DOMAIN
|
|
21
53
|
GOTRUE_DISABLE_SIGNUP=true
|
|
22
54
|
GOTRUE_MAILER_AUTOCONFIRM=false
|
|
55
|
+
# From address for auth emails — customer domain, not askexe.com (bug 133c9d5b).
|
|
56
|
+
SMTP_FROM=noreply@CHANGEME_DOMAIN
|
|
57
|
+
# To enable verified email confirmation, set SMTP_* below (MAILER_AUTOCONFIRM stays false).
|
|
58
|
+
SMTP_HOST=
|
|
59
|
+
SMTP_PORT=587
|
|
60
|
+
SMTP_USER=
|
|
61
|
+
SMTP_PASS=
|
|
23
62
|
|
|
24
63
|
# --- CRM ---
|
|
25
64
|
CRM_IMAGE_TAG=ghcr.io/askexe/exe-crm:v0.9.47
|
|
@@ -73,7 +112,7 @@ ERROR_REPORTING_ENABLED=true
|
|
|
73
112
|
MONITOR_ERROR_URL=http://exe-monitor-hub:8090/api/exe-monitor/errors
|
|
74
113
|
|
|
75
114
|
# --- ERP (optional — Exe ERP, Frappe/ERPNext fork) ---
|
|
76
|
-
ERP_IMAGE_TAG=ghcr.io/askexe/exe-erp:v0.2.0-
|
|
115
|
+
ERP_IMAGE_TAG=ghcr.io/askexe/exe-erp:v0.2.0-final8
|
|
77
116
|
ERP_ADMIN_PASSWORD=CHANGEME_ERP_ADMIN_PASSWORD
|
|
78
117
|
EXE_ERP_ADMIN_TOKEN=CHANGEME_EXE_ERP_ADMIN_TOKEN
|
|
79
118
|
ERP_SITE_NAME=erp.askexe.com
|
package/deploy/compose/backup.sh
CHANGED
|
@@ -5,8 +5,19 @@
|
|
|
5
5
|
# ./backup.sh # Backup to /opt/exe-backups/
|
|
6
6
|
# ./backup.sh --output /tmp/backup # Backup to custom dir
|
|
7
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
|
|
8
|
+
# ./backup.sh --upload-r2 # Backup + upload to Cloudflare R2 (off-box)
|
|
9
|
+
# ./backup.sh --upload-s3 s3://bucket # Backup + upload to S3 (off-box)
|
|
10
|
+
#
|
|
11
|
+
# FAILURE HANDLING (bug fc71e7ca):
|
|
12
|
+
# The script aborts (non-zero exit) the moment a CRITICAL step fails — the
|
|
13
|
+
# postgres dump is gated on pg_dumpall's exit code, so it NEVER prints
|
|
14
|
+
# "backup ok" over a failed/empty dump. Failures are logged AND surface an
|
|
15
|
+
# alert via an optional webhook (BACKUP_ALERT_WEBHOOK) and/or a healthcheck
|
|
16
|
+
# ping (BACKUP_HEALTHCHECK_URL — e.g. healthchecks.io). No silent success.
|
|
17
|
+
#
|
|
18
|
+
# OFF-BOX (bug 56a71515): pass --upload-r2 (or --upload-s3) — or set the cron
|
|
19
|
+
# to do so — so the encrypted archive leaves the VPS disk. A backup that only
|
|
20
|
+
# ever lands on the same disk as live data does not survive disk/host loss.
|
|
10
21
|
#
|
|
11
22
|
set -euo pipefail
|
|
12
23
|
|
|
@@ -17,6 +28,51 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
17
28
|
DOWNLOAD_MODE=false
|
|
18
29
|
UPLOAD_R2=false
|
|
19
30
|
UPLOAD_S3=""
|
|
31
|
+
# Real DB container name. Past bug fc71e7ca referenced a non-existent
|
|
32
|
+
# 'crm-postgres'; the canonical stack DB container is 'exe-db'. Override via env.
|
|
33
|
+
DB_CONTAINER="${BACKUP_DB_CONTAINER:-exe-db}"
|
|
34
|
+
PG_USER="${POSTGRES_USER:-exe}"
|
|
35
|
+
|
|
36
|
+
# ------------------------------------------------------------------
|
|
37
|
+
# Alerting — surface failures loudly. Optional, configured via env:
|
|
38
|
+
# BACKUP_ALERT_WEBHOOK — POST a JSON {host,stage,message} on failure
|
|
39
|
+
# BACKUP_HEALTHCHECK_URL — ping <url> on success, <url>/fail on failure
|
|
40
|
+
# (compatible with healthchecks.io / Uptime Kuma)
|
|
41
|
+
# ------------------------------------------------------------------
|
|
42
|
+
HOST_NAME="$(hostname 2>/dev/null || echo unknown)"
|
|
43
|
+
ALERT_WEBHOOK="${BACKUP_ALERT_WEBHOOK:-}"
|
|
44
|
+
HEALTHCHECK_URL="${BACKUP_HEALTHCHECK_URL:-}"
|
|
45
|
+
if [[ -z "$ALERT_WEBHOOK" && -f "$SCRIPT_DIR/.env" ]]; then
|
|
46
|
+
ALERT_WEBHOOK=$(grep -E '^BACKUP_ALERT_WEBHOOK=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d= -f2- || true)
|
|
47
|
+
fi
|
|
48
|
+
if [[ -z "$HEALTHCHECK_URL" && -f "$SCRIPT_DIR/.env" ]]; then
|
|
49
|
+
HEALTHCHECK_URL=$(grep -E '^BACKUP_HEALTHCHECK_URL=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d= -f2- || true)
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
alert() {
|
|
53
|
+
# alert <stage> <message>
|
|
54
|
+
local stage="$1"; shift
|
|
55
|
+
local msg="$*"
|
|
56
|
+
echo "[backup][ERROR] stage=$stage: $msg" >&2
|
|
57
|
+
if [[ -n "$ALERT_WEBHOOK" ]] && command -v curl >/dev/null 2>&1; then
|
|
58
|
+
curl -fsS -m 10 -X POST "$ALERT_WEBHOOK" \
|
|
59
|
+
-H 'Content-Type: application/json' \
|
|
60
|
+
-d "{\"host\":\"$HOST_NAME\",\"stage\":\"$stage\",\"message\":\"$msg\"}" \
|
|
61
|
+
>/dev/null 2>&1 || echo "[backup] (alert webhook POST failed)" >&2
|
|
62
|
+
fi
|
|
63
|
+
if [[ -n "$HEALTHCHECK_URL" ]] && command -v curl >/dev/null 2>&1; then
|
|
64
|
+
curl -fsS -m 10 "${HEALTHCHECK_URL%/}/fail" >/dev/null 2>&1 || true
|
|
65
|
+
fi
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# fail <stage> <message> — emit alert and exit non-zero. No silent success.
|
|
69
|
+
fail() {
|
|
70
|
+
alert "$1" "$2"
|
|
71
|
+
exit 1
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# Any unexpected error (set -e) routes through here so we still alert.
|
|
75
|
+
trap 'fail "unexpected" "backup aborted at line $LINENO (see log above)"' ERR
|
|
20
76
|
|
|
21
77
|
while [[ $# -gt 0 ]]; do
|
|
22
78
|
case $1 in
|
|
@@ -34,12 +90,26 @@ mkdir -p "$ARCHIVE"
|
|
|
34
90
|
|
|
35
91
|
echo "[backup] Starting exe-os full stack backup ($DATE)"
|
|
36
92
|
|
|
37
|
-
# 1. Postgres dump (all databases)
|
|
38
|
-
echo
|
|
39
|
-
|
|
40
|
-
|
|
93
|
+
# 1. Postgres dump (all databases) — CRITICAL. Gate success on the exit code.
|
|
94
|
+
# Previously a failure here was swallowed by `|| echo` and the script still
|
|
95
|
+
# printed "backup ok" over an empty dump (bug fc71e7ca). Now we abort.
|
|
96
|
+
echo "[backup] Dumping postgres from container '$DB_CONTAINER'..."
|
|
97
|
+
if ! docker exec "$DB_CONTAINER" pg_dumpall -U "$PG_USER" > "$ARCHIVE/postgres.sql" 2> "$ARCHIVE/postgres.err"; then
|
|
98
|
+
cat "$ARCHIVE/postgres.err" >&2 || true
|
|
99
|
+
fail "pg_dumpall" "postgres dump failed (container=$DB_CONTAINER user=$PG_USER) — backup aborted, NOT marked ok"
|
|
100
|
+
fi
|
|
101
|
+
# Guard against a 0-byte / truncated dump that still exits 0.
|
|
102
|
+
if [[ ! -s "$ARCHIVE/postgres.sql" ]]; then
|
|
103
|
+
fail "pg_dumpall" "postgres dump produced an empty file — refusing to report success"
|
|
104
|
+
fi
|
|
105
|
+
rm -f "$ARCHIVE/postgres.err"
|
|
106
|
+
if ! gzip "$ARCHIVE/postgres.sql"; then
|
|
107
|
+
fail "gzip" "failed to compress postgres.sql"
|
|
108
|
+
fi
|
|
109
|
+
echo "[backup] Postgres dump OK ($(du -h "$ARCHIVE/postgres.sql.gz" | cut -f1))"
|
|
41
110
|
|
|
42
111
|
# 2. Customer config files (.env, gateway.json, branding.json, clickhouse-config.xml, cloudflared)
|
|
112
|
+
# Non-fatal: copy what exists. These are also recoverable from the operator's saved .env.
|
|
43
113
|
echo "[backup] Backing up config files..."
|
|
44
114
|
cp "$SCRIPT_DIR/.env" "$ARCHIVE/env.bak" 2>/dev/null || true
|
|
45
115
|
cp "$SCRIPT_DIR/gateway.json" "$ARCHIVE/gateway.json" 2>/dev/null || true
|
|
@@ -49,20 +119,22 @@ cp -r "$SCRIPT_DIR/cloudflared" "$ARCHIVE/cloudflared" 2>/dev/null || true
|
|
|
49
119
|
|
|
50
120
|
# 3. Gateway auth state (Baileys creds — critical for WhatsApp connection)
|
|
51
121
|
echo "[backup] Backing up gateway WhatsApp auth state..."
|
|
52
|
-
docker cp exe-gateway:/data/. "$ARCHIVE/gateway-data/" 2>/dev/null || echo "[backup] Gateway data skipped"
|
|
122
|
+
docker cp exe-gateway:/data/. "$ARCHIVE/gateway-data/" 2>/dev/null || echo "[backup] Gateway data skipped (container not running)"
|
|
53
123
|
|
|
54
124
|
# 4. Wiki storage (uploaded documents)
|
|
55
125
|
echo "[backup] Backing up wiki storage..."
|
|
56
|
-
docker cp exe-wiki:/app/server/storage/. "$ARCHIVE/wiki-storage/" 2>/dev/null || echo "[backup] Wiki storage skipped"
|
|
126
|
+
docker cp exe-wiki:/app/server/storage/. "$ARCHIVE/wiki-storage/" 2>/dev/null || echo "[backup] Wiki storage skipped (container not running)"
|
|
57
127
|
|
|
58
128
|
# 5. exe-os daemon state (optional — SQLCipher DB is local-first, not critical for VPS)
|
|
59
129
|
echo "[backup] Backing up exe-os state..."
|
|
60
|
-
docker cp exe-os:/home/exed/.exe-os/. "$ARCHIVE/exe-os-data/" 2>/dev/null || echo "[backup] exe-os data skipped"
|
|
130
|
+
docker cp exe-os:/home/exed/.exe-os/. "$ARCHIVE/exe-os-data/" 2>/dev/null || echo "[backup] exe-os data skipped (container not running)"
|
|
61
131
|
|
|
62
|
-
# 6. Create single archive (compressed)
|
|
132
|
+
# 6. Create single archive (compressed) — CRITICAL.
|
|
63
133
|
echo "[backup] Creating archive..."
|
|
64
134
|
TARFILE="$BACKUP_DIR/exe-backup-$DATE.tar.gz"
|
|
65
|
-
tar -czf "$TARFILE" -C "$BACKUP_DIR" "exe-backup-$DATE"
|
|
135
|
+
if ! tar -czf "$TARFILE" -C "$BACKUP_DIR" "exe-backup-$DATE"; then
|
|
136
|
+
fail "tar" "failed to create archive $TARFILE"
|
|
137
|
+
fi
|
|
66
138
|
rm -rf "$ARCHIVE"
|
|
67
139
|
echo "[backup] Archive: $TARFILE ($(du -h "$TARFILE" | cut -f1))"
|
|
68
140
|
|
|
@@ -71,28 +143,30 @@ echo "[backup] Archive: $TARFILE ($(du -h "$TARFILE" | cut -f1))"
|
|
|
71
143
|
# Without this key, R2 backups are unreadable — even AskExe cannot access them.
|
|
72
144
|
BACKUP_KEY="${EXE_BACKUP_KEY:-}"
|
|
73
145
|
if [[ -z "$BACKUP_KEY" && -f "$SCRIPT_DIR/.env" ]]; then
|
|
74
|
-
BACKUP_KEY=$(grep -E '^EXE_BACKUP_KEY=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d= -f2)
|
|
146
|
+
BACKUP_KEY=$(grep -E '^EXE_BACKUP_KEY=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d= -f2- || true)
|
|
75
147
|
fi
|
|
76
148
|
if [[ -n "$BACKUP_KEY" ]]; then
|
|
77
149
|
ENCRYPTED_FILE="${TARFILE}.enc"
|
|
78
150
|
echo "[backup] Encrypting with AES-256-CBC (customer-owned key)..."
|
|
79
|
-
openssl enc -aes-256-cbc -pbkdf2 -iter 100000 \
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
rm -f "$TARFILE"
|
|
84
|
-
TARFILE="$ENCRYPTED_FILE"
|
|
85
|
-
echo "[backup] Encrypted: $TARFILE ($(du -h "$TARFILE" | cut -f1))"
|
|
86
|
-
else
|
|
87
|
-
echo "[backup] Encryption failed — uploading compressed (unencrypted)"
|
|
151
|
+
if ! openssl enc -aes-256-cbc -pbkdf2 -iter 100000 \
|
|
152
|
+
-in "$TARFILE" -out "$ENCRYPTED_FILE" \
|
|
153
|
+
-pass "pass:${BACKUP_KEY}"; then
|
|
154
|
+
fail "encrypt" "openssl encryption failed — refusing to upload plaintext customer data"
|
|
88
155
|
fi
|
|
156
|
+
rm -f "$TARFILE"
|
|
157
|
+
TARFILE="$ENCRYPTED_FILE"
|
|
158
|
+
echo "[backup] Encrypted: $TARFILE ($(du -h "$TARFILE" | cut -f1))"
|
|
89
159
|
else
|
|
90
|
-
echo "[backup] WARNING: EXE_BACKUP_KEY not set — backup NOT encrypted. Set it in .env for E2E encryption."
|
|
160
|
+
echo "[backup] WARNING: EXE_BACKUP_KEY not set — backup NOT encrypted. Set it in .env for E2E encryption." >&2
|
|
91
161
|
fi
|
|
92
162
|
|
|
93
|
-
# 7. Retention — delete old backups
|
|
163
|
+
# 7. Retention — delete old backups (match BOTH .tar.gz and encrypted .tar.gz.enc).
|
|
94
164
|
echo "[backup] Cleaning backups older than $RETENTION_DAYS days..."
|
|
95
|
-
find "$BACKUP_DIR" -name "exe-backup-*.tar.gz" -mtime "+$RETENTION_DAYS" -delete 2>/dev/null
|
|
165
|
+
find "$BACKUP_DIR" -name "exe-backup-*.tar.gz" -mtime "+$RETENTION_DAYS" -delete 2>/dev/null || true
|
|
166
|
+
find "$BACKUP_DIR" -name "exe-backup-*.tar.gz.enc" -mtime "+$RETENTION_DAYS" -delete 2>/dev/null || true
|
|
167
|
+
|
|
168
|
+
# Track off-box result so we can refuse to claim success on an upload-only run.
|
|
169
|
+
OFFBOX_OK=true
|
|
96
170
|
|
|
97
171
|
# 8. Download instructions
|
|
98
172
|
if $DOWNLOAD_MODE; then
|
|
@@ -100,58 +174,89 @@ if $DOWNLOAD_MODE; then
|
|
|
100
174
|
echo "=== Download to your local machine ==="
|
|
101
175
|
echo "Run on your local machine:"
|
|
102
176
|
echo ""
|
|
103
|
-
HOSTNAME=$(hostname)
|
|
104
177
|
IP=$(curl -s ifconfig.me 2>/dev/null || echo "<VPS_IP>")
|
|
105
|
-
echo " scp root@$IP:$TARFILE
|
|
178
|
+
echo " scp root@$IP:$TARFILE ./$(basename "$TARFILE")"
|
|
106
179
|
echo ""
|
|
107
180
|
echo "Or via Tailscale:"
|
|
108
181
|
TS_IP=$(tailscale ip -4 2>/dev/null || echo "<TAILSCALE_IP>")
|
|
109
|
-
echo " scp root@$TS_IP:$TARFILE
|
|
182
|
+
echo " scp root@$TS_IP:$TARFILE ./$(basename "$TARFILE")"
|
|
110
183
|
echo ""
|
|
111
184
|
echo "To restore on a new VPS:"
|
|
112
|
-
echo " tar -xzf exe-backup-$DATE.tar.gz"
|
|
185
|
+
echo " tar -xzf exe-backup-$DATE.tar.gz # (decrypt the .enc first if encrypted)"
|
|
113
186
|
echo " cp env.bak /opt/exe-stack/.env"
|
|
114
187
|
echo " cp gateway.json /opt/exe-stack/"
|
|
115
188
|
echo " cp branding.json /opt/exe-stack/"
|
|
116
189
|
echo " cp clickhouse-config.xml /opt/exe-stack/"
|
|
117
190
|
echo " cp -r cloudflared/ /opt/exe-stack/"
|
|
118
|
-
echo " cat postgres.sql.gz | gunzip | docker exec -i
|
|
191
|
+
echo " cat postgres.sql.gz | gunzip | docker exec -i $DB_CONTAINER psql -U $PG_USER"
|
|
119
192
|
echo " docker compose up -d"
|
|
120
193
|
fi
|
|
121
194
|
|
|
122
|
-
# 9. Upload to R2 (Cloudflare) — uses same R2 credentials as media/cloud sync
|
|
195
|
+
# 9. Upload to R2 (Cloudflare) — uses same R2 credentials as media/cloud sync.
|
|
196
|
+
# OFF-BOX target (bug 56a71515): this is what survives disk/host death.
|
|
123
197
|
if $UPLOAD_R2; then
|
|
124
|
-
# Source .env for R2 credentials if not already in environment
|
|
125
198
|
if [[ -z "${R2_ENDPOINT:-}" && -f "$SCRIPT_DIR/.env" ]]; then
|
|
126
199
|
# Map R2_MEDIA_* vars to the aws-cli vars backup needs
|
|
127
|
-
eval "$(grep -E '^R2_MEDIA_' "$SCRIPT_DIR/.env" 2>/dev/null)"
|
|
200
|
+
eval "$(grep -E '^R2_MEDIA_' "$SCRIPT_DIR/.env" 2>/dev/null || true)"
|
|
128
201
|
export R2_ENDPOINT="${R2_ENDPOINT:-${R2_MEDIA_ENDPOINT:-}}"
|
|
129
202
|
export AWS_ACCESS_KEY_ID="${AWS_ACCESS_KEY_ID:-${R2_MEDIA_ACCESS_KEY:-}}"
|
|
130
203
|
export AWS_SECRET_ACCESS_KEY="${AWS_SECRET_ACCESS_KEY:-${R2_MEDIA_SECRET_KEY:-}}"
|
|
131
204
|
fi
|
|
132
205
|
|
|
133
206
|
R2_BACKUP_BUCKET="${R2_BACKUP_BUCKET:-${R2_MEDIA_BUCKET:-exe-backups}}"
|
|
134
|
-
R2_BACKUP_PREFIX="${R2_BACKUP_PREFIX:-backups/$
|
|
207
|
+
R2_BACKUP_PREFIX="${R2_BACKUP_PREFIX:-backups/$HOST_NAME}"
|
|
135
208
|
|
|
136
209
|
if [[ -z "${R2_ENDPOINT:-}" ]]; then
|
|
137
|
-
|
|
210
|
+
OFFBOX_OK=false
|
|
211
|
+
alert "r2-config" "R2 upload requested but R2_MEDIA_ENDPOINT not set in .env — backup stayed on-box only"
|
|
138
212
|
elif command -v rclone >/dev/null 2>&1; then
|
|
139
|
-
rclone copy "$TARFILE" "r2:${R2_BACKUP_BUCKET}/${R2_BACKUP_PREFIX}/"
|
|
213
|
+
if rclone copy "$TARFILE" "r2:${R2_BACKUP_BUCKET}/${R2_BACKUP_PREFIX}/"; then
|
|
214
|
+
echo "[backup] R2 upload complete → ${R2_BACKUP_BUCKET}/${R2_BACKUP_PREFIX}/"
|
|
215
|
+
else
|
|
216
|
+
OFFBOX_OK=false
|
|
217
|
+
alert "r2-upload" "rclone upload to ${R2_BACKUP_BUCKET}/${R2_BACKUP_PREFIX}/ failed — off-box copy missing"
|
|
218
|
+
fi
|
|
140
219
|
elif command -v aws >/dev/null 2>&1; then
|
|
141
|
-
aws s3 cp "$TARFILE" "s3://${R2_BACKUP_BUCKET}/${R2_BACKUP_PREFIX}/$(basename "$TARFILE")" \
|
|
142
|
-
|
|
220
|
+
if aws s3 cp "$TARFILE" "s3://${R2_BACKUP_BUCKET}/${R2_BACKUP_PREFIX}/$(basename "$TARFILE")" \
|
|
221
|
+
--endpoint-url "${R2_ENDPOINT}"; then
|
|
222
|
+
echo "[backup] R2 upload complete"
|
|
223
|
+
else
|
|
224
|
+
OFFBOX_OK=false
|
|
225
|
+
alert "r2-upload" "aws s3 cp to ${R2_BACKUP_BUCKET} failed — off-box copy missing"
|
|
226
|
+
fi
|
|
143
227
|
else
|
|
144
|
-
|
|
228
|
+
OFFBOX_OK=false
|
|
229
|
+
alert "r2-tooling" "neither rclone nor aws-cli installed — cannot push backup off-box. apt install rclone"
|
|
145
230
|
fi
|
|
146
231
|
fi
|
|
147
232
|
|
|
148
|
-
# 10. Upload to S3
|
|
233
|
+
# 10. Upload to S3 (off-box)
|
|
149
234
|
if [[ -n "$UPLOAD_S3" ]]; then
|
|
150
235
|
echo "[backup] Uploading to S3..."
|
|
151
|
-
|
|
236
|
+
if ! command -v aws >/dev/null 2>&1; then
|
|
237
|
+
OFFBOX_OK=false
|
|
238
|
+
alert "s3-tooling" "aws-cli not installed — cannot upload to $UPLOAD_S3"
|
|
239
|
+
elif aws s3 cp "$TARFILE" "$UPLOAD_S3/$(basename "$TARFILE")"; then
|
|
240
|
+
echo "[backup] S3 upload complete"
|
|
241
|
+
else
|
|
242
|
+
OFFBOX_OK=false
|
|
243
|
+
alert "s3-upload" "aws s3 cp to $UPLOAD_S3 failed — off-box copy missing"
|
|
244
|
+
fi
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
# 11. Final result. Only ping the healthcheck success URL if everything that was
|
|
248
|
+
# requested actually succeeded — including the off-box upload when asked for.
|
|
249
|
+
if { $UPLOAD_R2 || [[ -n "$UPLOAD_S3" ]]; } && [[ "$OFFBOX_OK" != true ]]; then
|
|
250
|
+
fail "offbox" "local archive created but off-box upload did not complete — DR copy is missing"
|
|
251
|
+
fi
|
|
252
|
+
|
|
253
|
+
if [[ -n "$HEALTHCHECK_URL" ]] && command -v curl >/dev/null 2>&1; then
|
|
254
|
+
curl -fsS -m 10 "$HEALTHCHECK_URL" >/dev/null 2>&1 || echo "[backup] (success healthcheck ping failed)" >&2
|
|
152
255
|
fi
|
|
153
256
|
|
|
154
|
-
|
|
257
|
+
# Clear the ERR trap before the clean exit.
|
|
258
|
+
trap - ERR
|
|
259
|
+
echo "[backup] Done — backup OK."
|
|
155
260
|
echo ""
|
|
156
261
|
echo "Backups:"
|
|
157
|
-
ls -lh "$BACKUP_DIR"/exe-backup-*.tar.gz 2>/dev/null | tail -5
|
|
262
|
+
ls -lh "$BACKUP_DIR"/exe-backup-*.tar.gz* 2>/dev/null | tail -5
|