From ae056eaf83b3d9ed273b68bce635aef8fdd1d665 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 15 Jul 2026 17:45:36 -0400 Subject: [PATCH] =?UTF-8?q?Initial=20resurrection=20kit=20=E2=80=94=2081?= =?UTF-8?q?=20scripts,=2062=20references,=20configs,=20systemd=20units,=20?= =?UTF-8?q?crons,=20Docker=20compose=20files,=20Caddy=20config,=20master?= =?UTF-8?q?=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 + README.md | 108 ++ caddy/Caddyfile | 66 + configs/.env.example | 46 + configs/config.yaml | 206 +++ configs/persona-and-brief.md | 0 cron/crontab.txt | 11 + docker/docuseal/docker-compose.yml | 17 + docker/komodo/docker-compose.yml | 56 + docker/litellm/docker-compose.yml | 33 + docker/mcp-email/Dockerfile | 10 + docker/mcp-email/requirements.txt | 4 + docker/mcp-filesystem/Dockerfile | 10 + docker/mcp-filesystem/requirements.txt | 3 + docker/mcp-git/Dockerfile | 10 + docker/mcp-git/requirements.txt | 4 + docker/searxng/docker-compose.yml | 26 + docker/super-search/exa.env | 1 + docker/twenty/.mcp.json | 22 + docker/twenty/CLAUDE.md | 224 +++ docker/twenty/DESIGN.md | 159 ++ docker/twenty/PRODUCT.md | 80 + docker/twenty/README.md | 164 ++ docker/twenty/docker-compose.yml | 139 ++ docker/twenty/nx.json | 284 ++++ docker/twenty/package.json | 113 ++ docker/twenty/tsconfig.base.json | 19 + docker/uptime-kuma/docker-compose.yml | 28 + docker/vaultwarden/CHANGELOG.md | 13 + docker/vaultwarden/docker-compose.yml | 17 + references/1-DR-Master-Plan-v2.md | 109 ++ references/2-Backup-Security-Standard.md | 137 ++ references/3-Per-Server-Runbooks.md | 227 +++ references/4-DR-Testing-Schedule.md | 144 ++ references/admin-ai-migration-plan.md | 216 +++ references/application-inventory.md | 56 + references/architecture-audit-2026-07-13.md | 559 +++++++ references/backup-policy.md | 72 + references/core-rebalance-plan.md | 1436 +++++++++++++++++ references/docker-management-research.md | 483 ++++++ references/dr-issue-log.md | 443 +++++ references/dre-credit-reporting.md | 439 +++++ references/dre-fee-structure.md | 82 + references/dre-letter-templates.md | 206 +++ references/dre-roles-guide.md | 83 + references/dre-specs.md | 178 ++ references/dre-temp-passwords.txt | 3 + references/hetzner-netcup-migration-plan.md | 170 ++ references/hetzner-server-audit.md | 839 ++++++++++ references/hetzner-server-inventory.md | 148 ++ references/immich-mcp-reference.md | 58 + references/incident-response-plan.md | 68 + references/ip-dns-changes.md | 92 ++ references/itpp-recovery-manual.md | 1349 ++++++++++++++++ references/master-apps-services.md | 340 ++++ references/memory-consolidation-proposal.md | 123 ++ references/model-price-research.md | 95 ++ references/network-diagram.md | 86 + references/ops-portal-audit-2026-07-12.md | 44 + references/ops-portal-recommendations.md | 549 +++++++ references/restore-plan-2026-07-11.md | 391 +++++ references/restore-runbooks.md | 324 ++++ references/server-dr-plans-public.md | 495 ++++++ references/server-dr-plans-redacted.md | 98 ++ references/server-dr-plans-v3.md | 655 ++++++++ references/server-dr-plans.md | 453 ++++++ references/server-inventory.md | 23 + .../server-provisioning-standard-public.md | 98 ++ .../server-provisioning-standard-review.md | 165 ++ references/server-provisioning-standard-v1.md | 137 ++ references/shark-game-recovery-manual.md | 581 +++++++ references/shark-game-trademark-research.md | 209 +++ references/sharkbait-domain-research.md | 200 +++ references/shonuff-closings.py | 10 + references/shonuff-image-b64.txt | 1 + references/shonuff-prompts.md | 16 + references/shonuff-signature-format.md | 38 + references/shonuff-signature.py | 63 + references/shonuff-titles.py | 15 + references/tony-vps.txt | 12 + scripts/.shonuff-processed.json | 1 + scripts/.shonuff-reply-processed.json | 1 + scripts/_fetch_body.py | 37 + scripts/anita-restart.sh | 3 + scripts/apex-mail-watchdog.py | 90 ++ scripts/apex-mail-watchdog.sh | 58 + scripts/audit-server.sh | 70 + scripts/backup-audit-check.sh | 41 + scripts/backup-uisp.sh | 66 + scripts/backup_portal.py | 461 ++++++ scripts/bounce-check.py | 121 ++ scripts/boxpilot-triage.py | 151 ++ scripts/boys-mail-monitor.py | 410 +++++ .../boys-mail-monitor.py.bak.20260712-191959 | 674 ++++++++ scripts/build-recovery.py | 229 +++ scripts/changelog.sh | 23 + scripts/daily-feed-summary.py | 267 +++ scripts/deploy-key.rsc | 3 + scripts/dre-approval-reminder.sh | 30 + scripts/dre-mail-poller.py | 288 ++++ scripts/firecrawl-usage.json | 1 + scripts/ft360-daily-stats.py | 102 ++ scripts/ft360-export.py | 218 +++ scripts/ft360-route-export.py | 108 ++ scripts/generate-script-contents.py | 80 + scripts/gitea-backup.sh | 69 + scripts/hermes-backup-worker.sh | 3 + scripts/hermes-backup.sh | 238 +++ scripts/hermes-consolidate.py | 161 ++ scripts/hermes-consolidate.sh | 79 + scripts/hermes-docker-sync.sh | 56 + scripts/hermes-live-sync.sh | 34 + scripts/hermes-standby-restore.sh | 92 ++ scripts/hermes-standby-watchdog.sh | 144 ++ scripts/hermes-standby.service | 16 + scripts/hermes-system-config-sync.sh | 68 + scripts/home-router-backup.sh | 49 + scripts/home-router-watchdog.sh | 1 + scripts/hudu-backup.sh | 55 + scripts/icloud_bills_calendar.py | 321 ++++ scripts/imap_triage.py | 371 +++++ scripts/imap_triage_autorun.py | 83 + scripts/imap_triage_collect.sh | 3 + scripts/imap_triage_watchdog.sh | 55 + scripts/list-hetzner-servers.py | 14 + .../logs/home-router-backup-2026-07-03.log | 60 + .../logs/home-router-backup-2026-07-04.log | 194 +++ .../logs/home-router-backup-2026-07-05.log | 60 + .../logs/home-router-backup-2026-07-06.log | 6 + .../logs/home-router-backup-2026-07-07.log | 12 + .../logs/home-router-backup-2026-07-08.log | 205 +++ .../logs/home-router-backup-2026-07-09.log | 102 ++ .../logs/home-router-backup-2026-07-10.log | 29 + .../logs/home-router-backup-2026-07-11.log | 29 + .../logs/home-router-backup-2026-07-12.log | 29 + .../logs/home-router-backup-2026-07-13.log | 29 + .../logs/home-router-backup-2026-07-14.log | 29 + .../logs/home-router-backup-2026-07-15.log | 29 + scripts/lynis-scan.sh | 28 + scripts/mcp-mysql.py | 92 ++ scripts/migration-backup/migration-creds.txt | 19 + .../migration-backup/migration-recovery.md | 63 + scripts/model-usage-tracker.sh | 32 + scripts/ops-data-collector.py | 889 ++++++++++ scripts/reboot-with-check.sh | 92 ++ scripts/restart-anita-gateway.sh | 18 + scripts/root-essentials-backup.sh | 57 + scripts/run-hermes-backup.sh | 3 + scripts/run-portal-backup.sh | 25 + scripts/run-wisp-backup.sh | 24 + scripts/send-back-online.sh | 31 + scripts/send-backup-email.py | 36 + scripts/send-backup-readme.py | 34 + scripts/send-dr-audit-email.py | 91 ++ scripts/send-dr-email.py | 163 ++ scripts/send-dr-v3.py | 159 ++ scripts/send-recovery.py | 44 + scripts/send-reset-notifications.sh | 26 + scripts/send-shonuff.py | 58 + scripts/service-health-check.sh | 50 + scripts/shark-draft-reminder.sh | 345 ++++ scripts/shark-scraper.sh | 11 + scripts/shonuff-email-responder.py | 301 ++++ scripts/shonuff-inbox-collect.py | 116 ++ scripts/snapshot-hetzner.py | 60 + scripts/spend-monitor-collect.sh | 36 + scripts/start-anita-gateway.sh | 5 + scripts/start-anita.sh | 4 + scripts/sync_ringlogix.py | 665 ++++++++ scripts/track-firecrawl.py | 85 + scripts/unifi-backup-sync.sh | 58 + scripts/unms-backup-sync.sh | 75 + scripts/vps-threshold-check.sh | 211 +++ scripts/watch-shonuff-inbox.py | 78 + scripts/wisp-backup/config.yaml | 40 + scripts/wisp-backup/home-router-keepalive.sh | 30 + scripts/wisp-backup/home-router-vpn.sh | 237 +++ scripts/wisp-backup/home-router-watchdog.sh | 22 + scripts/wisp-backup/wisp-backup.py | 366 +++++ systemd/dbus-org.freedesktop.Avahi.service | 32 + .../dbus-org.freedesktop.timesync1.service | 60 + systemd/dre-mcp.service | 17 + systemd/ft360-mcp.service | 16 + systemd/hermes-assistant.service | 14 + systemd/hermes-browser.service | 20 + systemd/hermes.service | 17 + systemd/mysql-tunnel.service | 14 + systemd/node_exporter.service | 11 + systemd/ollama.service | 13 + systemd/ops-portal.service | 14 + systemd/osint-api.service | 15 + systemd/osint-person.service | 17 + systemd/redis.service | 64 + systemd/shark-game.service | 14 + systemd/sshd.service | 22 + systemd/super-search.service | 17 + systemd/twilio-mcp.service | 17 + 197 files changed, 26127 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 caddy/Caddyfile create mode 100644 configs/.env.example create mode 100644 configs/config.yaml create mode 100644 configs/persona-and-brief.md create mode 100644 cron/crontab.txt create mode 100644 docker/docuseal/docker-compose.yml create mode 100644 docker/komodo/docker-compose.yml create mode 100644 docker/litellm/docker-compose.yml create mode 100644 docker/mcp-email/Dockerfile create mode 100644 docker/mcp-email/requirements.txt create mode 100644 docker/mcp-filesystem/Dockerfile create mode 100644 docker/mcp-filesystem/requirements.txt create mode 100644 docker/mcp-git/Dockerfile create mode 100644 docker/mcp-git/requirements.txt create mode 100644 docker/searxng/docker-compose.yml create mode 100644 docker/super-search/exa.env create mode 100644 docker/twenty/.mcp.json create mode 100644 docker/twenty/CLAUDE.md create mode 100644 docker/twenty/DESIGN.md create mode 100644 docker/twenty/PRODUCT.md create mode 100644 docker/twenty/README.md create mode 100644 docker/twenty/docker-compose.yml create mode 100644 docker/twenty/nx.json create mode 100644 docker/twenty/package.json create mode 100644 docker/twenty/tsconfig.base.json create mode 100644 docker/uptime-kuma/docker-compose.yml create mode 100644 docker/vaultwarden/CHANGELOG.md create mode 100644 docker/vaultwarden/docker-compose.yml create mode 100644 references/1-DR-Master-Plan-v2.md create mode 100644 references/2-Backup-Security-Standard.md create mode 100644 references/3-Per-Server-Runbooks.md create mode 100644 references/4-DR-Testing-Schedule.md create mode 100644 references/admin-ai-migration-plan.md create mode 100644 references/application-inventory.md create mode 100644 references/architecture-audit-2026-07-13.md create mode 100644 references/backup-policy.md create mode 100644 references/core-rebalance-plan.md create mode 100644 references/docker-management-research.md create mode 100644 references/dr-issue-log.md create mode 100644 references/dre-credit-reporting.md create mode 100644 references/dre-fee-structure.md create mode 100644 references/dre-letter-templates.md create mode 100644 references/dre-roles-guide.md create mode 100644 references/dre-specs.md create mode 100644 references/dre-temp-passwords.txt create mode 100644 references/hetzner-netcup-migration-plan.md create mode 100644 references/hetzner-server-audit.md create mode 100644 references/hetzner-server-inventory.md create mode 100644 references/immich-mcp-reference.md create mode 100644 references/incident-response-plan.md create mode 100644 references/ip-dns-changes.md create mode 100644 references/itpp-recovery-manual.md create mode 100644 references/master-apps-services.md create mode 100644 references/memory-consolidation-proposal.md create mode 100644 references/model-price-research.md create mode 100644 references/network-diagram.md create mode 100644 references/ops-portal-audit-2026-07-12.md create mode 100644 references/ops-portal-recommendations.md create mode 100644 references/restore-plan-2026-07-11.md create mode 100644 references/restore-runbooks.md create mode 100644 references/server-dr-plans-public.md create mode 100644 references/server-dr-plans-redacted.md create mode 100644 references/server-dr-plans-v3.md create mode 100644 references/server-dr-plans.md create mode 100644 references/server-inventory.md create mode 100644 references/server-provisioning-standard-public.md create mode 100644 references/server-provisioning-standard-review.md create mode 100644 references/server-provisioning-standard-v1.md create mode 100644 references/shark-game-recovery-manual.md create mode 100644 references/shark-game-trademark-research.md create mode 100644 references/sharkbait-domain-research.md create mode 100644 references/shonuff-closings.py create mode 100644 references/shonuff-image-b64.txt create mode 100644 references/shonuff-prompts.md create mode 100644 references/shonuff-signature-format.md create mode 100644 references/shonuff-signature.py create mode 100644 references/shonuff-titles.py create mode 100644 references/tony-vps.txt create mode 100644 scripts/.shonuff-processed.json create mode 100644 scripts/.shonuff-reply-processed.json create mode 100644 scripts/_fetch_body.py create mode 100644 scripts/anita-restart.sh create mode 100644 scripts/apex-mail-watchdog.py create mode 100755 scripts/apex-mail-watchdog.sh create mode 100755 scripts/audit-server.sh create mode 100755 scripts/backup-audit-check.sh create mode 100644 scripts/backup-uisp.sh create mode 100755 scripts/backup_portal.py create mode 100644 scripts/bounce-check.py create mode 100644 scripts/boxpilot-triage.py create mode 100755 scripts/boys-mail-monitor.py create mode 100755 scripts/boys-mail-monitor.py.bak.20260712-191959 create mode 100644 scripts/build-recovery.py create mode 100755 scripts/changelog.sh create mode 100755 scripts/daily-feed-summary.py create mode 100644 scripts/deploy-key.rsc create mode 100644 scripts/dre-approval-reminder.sh create mode 100755 scripts/dre-mail-poller.py create mode 100644 scripts/firecrawl-usage.json create mode 100755 scripts/ft360-daily-stats.py create mode 100755 scripts/ft360-export.py create mode 100644 scripts/ft360-route-export.py create mode 100644 scripts/generate-script-contents.py create mode 100755 scripts/gitea-backup.sh create mode 100755 scripts/hermes-backup-worker.sh create mode 100755 scripts/hermes-backup.sh create mode 100755 scripts/hermes-consolidate.py create mode 100755 scripts/hermes-consolidate.sh create mode 100755 scripts/hermes-docker-sync.sh create mode 100755 scripts/hermes-live-sync.sh create mode 100644 scripts/hermes-standby-restore.sh create mode 100644 scripts/hermes-standby-watchdog.sh create mode 100644 scripts/hermes-standby.service create mode 100755 scripts/hermes-system-config-sync.sh create mode 100755 scripts/home-router-backup.sh create mode 120000 scripts/home-router-watchdog.sh create mode 100755 scripts/hudu-backup.sh create mode 100755 scripts/icloud_bills_calendar.py create mode 100755 scripts/imap_triage.py create mode 100755 scripts/imap_triage_autorun.py create mode 100755 scripts/imap_triage_collect.sh create mode 100755 scripts/imap_triage_watchdog.sh create mode 100755 scripts/list-hetzner-servers.py create mode 100644 scripts/logs/home-router-backup-2026-07-03.log create mode 100644 scripts/logs/home-router-backup-2026-07-04.log create mode 100644 scripts/logs/home-router-backup-2026-07-05.log create mode 100644 scripts/logs/home-router-backup-2026-07-06.log create mode 100644 scripts/logs/home-router-backup-2026-07-07.log create mode 100644 scripts/logs/home-router-backup-2026-07-08.log create mode 100644 scripts/logs/home-router-backup-2026-07-09.log create mode 100644 scripts/logs/home-router-backup-2026-07-10.log create mode 100644 scripts/logs/home-router-backup-2026-07-11.log create mode 100644 scripts/logs/home-router-backup-2026-07-12.log create mode 100644 scripts/logs/home-router-backup-2026-07-13.log create mode 100644 scripts/logs/home-router-backup-2026-07-14.log create mode 100644 scripts/logs/home-router-backup-2026-07-15.log create mode 100644 scripts/lynis-scan.sh create mode 100644 scripts/mcp-mysql.py create mode 100644 scripts/migration-backup/migration-creds.txt create mode 100644 scripts/migration-backup/migration-recovery.md create mode 100644 scripts/model-usage-tracker.sh create mode 100755 scripts/ops-data-collector.py create mode 100644 scripts/reboot-with-check.sh create mode 100644 scripts/restart-anita-gateway.sh create mode 100755 scripts/root-essentials-backup.sh create mode 100755 scripts/run-hermes-backup.sh create mode 100755 scripts/run-portal-backup.sh create mode 100755 scripts/run-wisp-backup.sh create mode 100755 scripts/send-back-online.sh create mode 100755 scripts/send-backup-email.py create mode 100755 scripts/send-backup-readme.py create mode 100644 scripts/send-dr-audit-email.py create mode 100644 scripts/send-dr-email.py create mode 100644 scripts/send-dr-v3.py create mode 100644 scripts/send-recovery.py create mode 100755 scripts/send-reset-notifications.sh create mode 100644 scripts/send-shonuff.py create mode 100755 scripts/service-health-check.sh create mode 100755 scripts/shark-draft-reminder.sh create mode 100755 scripts/shark-scraper.sh create mode 100644 scripts/shonuff-email-responder.py create mode 100644 scripts/shonuff-inbox-collect.py create mode 100755 scripts/snapshot-hetzner.py create mode 100755 scripts/spend-monitor-collect.sh create mode 100644 scripts/start-anita-gateway.sh create mode 100644 scripts/start-anita.sh create mode 100755 scripts/sync_ringlogix.py create mode 100755 scripts/track-firecrawl.py create mode 100755 scripts/unifi-backup-sync.sh create mode 100755 scripts/unms-backup-sync.sh create mode 100755 scripts/vps-threshold-check.sh create mode 100644 scripts/watch-shonuff-inbox.py create mode 100644 scripts/wisp-backup/config.yaml create mode 100755 scripts/wisp-backup/home-router-keepalive.sh create mode 100755 scripts/wisp-backup/home-router-vpn.sh create mode 100755 scripts/wisp-backup/home-router-watchdog.sh create mode 100755 scripts/wisp-backup/wisp-backup.py create mode 100644 systemd/dbus-org.freedesktop.Avahi.service create mode 100644 systemd/dbus-org.freedesktop.timesync1.service create mode 100644 systemd/dre-mcp.service create mode 100644 systemd/ft360-mcp.service create mode 100644 systemd/hermes-assistant.service create mode 100644 systemd/hermes-browser.service create mode 100644 systemd/hermes.service create mode 100644 systemd/mysql-tunnel.service create mode 100644 systemd/node_exporter.service create mode 100644 systemd/ollama.service create mode 100644 systemd/ops-portal.service create mode 100644 systemd/osint-api.service create mode 100644 systemd/osint-person.service create mode 100644 systemd/redis.service create mode 100644 systemd/shark-game.service create mode 100644 systemd/sshd.service create mode 100644 systemd/super-search.service create mode 100644 systemd/twilio-mcp.service diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cb83598 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.pyc +__pycache__/ +.hetzner_token +*.pass +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..292620d --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# Hermes Recovery — Complete Resurrection Kit + +**If Sho'Nuff dies, this is how you bring him back.** + +## What's Here + +| Directory | What | Count | +|---|---|---| +| `scripts/` | All operational scripts | 81 | +| `configs/` | Hermes config.yaml, .env.example, persona, brief | 4 | +| `references/` | Design decisions, runbooks, specs, signature module | 62 | +| `systemd/` | All custom systemd service units | 25+ | +| `cron/` | Full crontab dump | 9 jobs | +| `caddy/` | Caddy reverse proxy config | 1 | +| `docker/` | Compose files for all services | 11 | + +## Resurrection Steps + +### 1. Provision Server +- netcup RS 2000 or higher (8+ vCPU, 16+ GB RAM) +- Debian 13, SSH key `itpp-infra` +- Open ports: 22, 80, 443 + +### 2. Install Base +```bash +apt-get update && apt-get install -y curl git python3 python3-pip docker.io docker-compose-plugin ufw caddy +ufw allow 22/tcp && ufw allow 80/tcp && ufw allow 443/tcp && ufw --force enable +``` + +### 3. Install Hermes Agent +```bash +curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash +``` + +### 4. Restore Configs +```bash +# Copy config.yaml to ~/.hermes/config.yaml +# Copy .env.example to ~/.hermes/.env → fill in actual secrets +# Copy persona to ~/.hermes/persona.md +``` + +### 5. Restore Scripts +```bash +cp scripts/* ~/.hermes/scripts/ +chmod +x ~/.hermes/scripts/*.sh +``` + +### 6. Deploy Services (Docker) +```bash +for d in docker/*/; do + cd "$d" && docker compose up -d +done +``` + +### 7. Restore Caddy +```bash +cp caddy/Caddyfile /etc/caddy/Caddyfile +systemctl restart caddy +``` + +### 8. Restore Cron Jobs +```bash +# Review crontab.txt, adjust paths if needed +crontab cron/crontab.txt +``` + +### 9. Restore Systemd Units +```bash +cp systemd/*.service /etc/systemd/system/ +systemctl daemon-reload +systemctl enable --now hermes.service +``` + +### 10. Restore Data from S3 +```bash +# Hermes state: aws s3 sync s3://hermes-vps-backups/live/ ~/.hermes/ +# Docker volumes: individual restore per service +``` + +## Critical Credentials (Fill These In) + +| File | What | +|---|---| +| `~/.hermes/.env` | All API keys, tokens, passwords | +| `~/.config/himalaya/*.pass` | Email account passwords | +| `~/.ssh/itpp-infra` | SSH private key | +| `~/.aws/credentials` | Wasabi S3 access | + +## Servers You Control + +| Server | IP | Provider | Role | +|---|---|---|---| +| Core | 152.53.192.33 | netcup RS2000 | Hermes + gateway | +| app1 | 152.53.36.131 | netcup RS4000 | Open WebUI, LiteLLM, Ollama, n8n, MCPs | +| app2 | 152.53.39.202 | netcup RS4000 | UNMS, Hudu, Traccar, UniFi, Gitea, Caddy | +| app3 | 152.53.241.111 | netcup RS2000 | WordPress, Apex Track | +| app1-bu | 5.161.114.8 | Hetzner CPX11 | Warm standby | +| wphost02 | 5.161.62.38 | Hetzner | WordPress | +| ai | 178.156.167.181 | Hetzner | admin-ai | + +## Documentation (Gitea) + +Full project docs at `https://git.itpropartner.com/ippadmin/`: +- `itpp-infrastructure` — Server inventory, DNS, architecture +- `disaster-recovery` — DR plan v3, recovery manual, issue log +- `hermes-skills` — 25 skill categories +- `hudu`, `unifi`, `unms`, `mcp-servers`, `scripts` +- `dre`, `shark-game`, `osint-tool`, `apex-track`, `boxpilot`, `fleettracker360`, `voipsimplicity`, `digital-signage` diff --git a/caddy/Caddyfile b/caddy/Caddyfile new file mode 100644 index 0000000..c3bc01c --- /dev/null +++ b/caddy/Caddyfile @@ -0,0 +1,66 @@ +{ + default_bind 152.53.192.33 + email info@itpropartner.com +} + +core.itpropartner.com { + handle_path /vault/* { + reverse_proxy localhost:8080 + } + reverse_proxy 127.0.0.1:8090 +} + +sign.core.itpropartner.com { + reverse_proxy 127.0.0.1:8090 +} + +vault.iamgmb.com { + reverse_proxy localhost:8080 +} + +ops.itpropartner.com { + header Cache-Control "no-cache, no-store, must-revalidate" + handle_path /osint/* { + root * /var/www/osint/ + file_server + } + handle_path /api/search/* { + reverse_proxy 127.0.0.1:8100 + } + handle_path /api/health { + reverse_proxy 127.0.0.1:8100 + } + handle_path /data/* { + root * /var/www/ops/data/ + file_server + } + handle_path /js/* { + root * /opt/ops-portal/static/js + file_server + } + handle_path /css/* { + root * /opt/ops-portal/static/css + file_server + } + reverse_proxy 127.0.0.1:8090 +} + +shark.iamgmb.com { + reverse_proxy 127.0.0.1:8083 +} + +portal.debtrecoveryexperts.com { + root * /var/www/internal/ + file_server +} + +sign.iamgmb.com { + reverse_proxy 127.0.0.1:8090 +} + +uptimekuma.itpropartner.com { + handle /health { + respond "OK" 200 + } + reverse_proxy localhost:3001 +} diff --git a/configs/.env.example b/configs/.env.example new file mode 100644 index 0000000..c14004a --- /dev/null +++ b/configs/.env.example @@ -0,0 +1,46 @@ +FIRECRAWL_API_KEY=REDACTED +CLOUDFLARE_API_TOKEN=REDACTED +NETCUP_API_KEY=REDACTED + +# netcup CCP API (authenticated via Keycloak) +NETCUP_CUSTOMER=389212 +NETCUP_PASSWORD=REDACTED! +NETCUP_KEY=REDACTED +NETCUP_API_KEY=REDACTED +SYNCROMSP_API_TOKEN=REDACTED + +# Telegram Integration +TELEGRAM_BOT_TOKEN=8359374835:AAEsPPBWGVa53jHkwSo9j4mAxIGsdp6SGUY +TELEGRAM_ALLOWED_USERS=5813481339 +TELEGRAM_HOME_CHANNEL=5813481339 + +# New netcup servers — Jul 10, 2026 +# app1/app2/app3 mapping TBD +SERVER_152_53_241_111_PASS=ab6eogprILQI6UX +SERVER_152_53_36_131_PASS=heUa1ucN6Xwta2O +SERVER_152_53_39_202_PASS=NKCS0I9wMn3yy86 + +# Exa AI search API +EXA_API_KEY=REDACTED +ADMIN_PASSWORD=itpp2026! +# RingLogix CPaaS API +RINGLOGIX_CLIENT_ID=0-t1706-c284088-r284061 +RINGLOGIX_CLIENT_SECRET=REDACTED +RINGLOGIX_USERNAME=106@284088 +RINGLOGIX_PASSWORD=Bruce.leroy85 +RINGLOGIX_DOMAIN=284088 + +# AI Provider API Keys (tested 2026-07-14) +OPENAI_API_KEY=sk-REDACTED +PERPLEXITY_API_KEY=REDACTED +GROQ_API_KEY=REDACTED +XAI_API_KEY=REDACTED +MISTRAL_API_KEY=REDACTED +FIREWORKS_API_KEY=fw_EpWLvWX3i5XDAAfwPScbwB +ANTHROPIC_API_KEY=sk-REDACTED +GOOGLE_AI_STUDIO_KEY=AQ.Ab8RN6IZmtXPrQewzo3DGqbvMWfwUwSLKg16SVTx8nidn_L14A +COHERE_API_KEY=REDACTED +AI21_API_KEY=REDACTED +DEEPGRAM_API_KEY=REDACTED +DEEPSEEK_API_KEY=sk-REDACTED +OPENROUTER_API_KEY=sk-REDACTED diff --git a/configs/config.yaml b/configs/config.yaml new file mode 100644 index 0000000..177870e --- /dev/null +++ b/configs/config.yaml @@ -0,0 +1,206 @@ +_config_version: 33 +agent: + api_max_retries: 3 + clarify_timeout: 600 + disabled_toolsets: [] + environment_hint: '' + environment_probe: true + gateway_auto_continue_freshness: 3600 + gateway_notify_interval: 180 + gateway_timeout: 1800 + gateway_timeout_warning: 900 + image_input_mode: auto + max_turns: 150 + reasoning_effort: high + restart_drain_timeout: 180 + service_tier: '' + task_completion_guidance: true + tool_use_enforcement: auto + verbose: false +approvals: + cron_mode: deny + mode: manual + timeout: 60 +auxiliary: + compression: + provider: auto + timeout: 120 + skills_hub: + provider: auto + timeout: 30 + vision: + model: gemini-flash-latest + provider: admin-ai + timeout: 120 +browser: + cloud_provider: local + inactivity_timeout: 120 + use_gateway: true +code_execution: + max_tool_calls: 50 + timeout: 300 +compression: + enabled: true + protect_first_n: 3 + protect_last_n: 20 + target_ratio: 0.2 + threshold: 0.5 +credits: + provider: openrouter + warning_threshold: 0.8 +cron: + wrap_response: true +delegation: + model: deepseek/deepseek-chat + provider: openrouter +display: + compact: false + interface: cli + language: en + platforms: + telegram: + streaming: true + skin: default + streaming: true + tui_status_indicator: kaomoji +fallback_providers: + - model: deepseek-v4-pro + provider: admin-ai + - model: deepseek/deepseek-chat + provider: openrouter + - model: llama3.2:3b + provider: ollama-local +gateway: + strict: false + trust_recent_files: true + trust_recent_files_seconds: 600 +logging: + backup_count: 3 + level: INFO + max_size_mb: 5 +mcp_servers: + dre: + enabled: true + url: http://127.0.0.1:8900/mcp + exa: + enabled: true + url: https://mcp.exa.ai/mcp + ft360: + enabled: true + url: http://127.0.0.1:8903/mcp + mysql: + args: + - /root/.hermes/scripts/mcp-mysql.py + command: python3 + enabled: true + env: + MYSQL_DB: apextrackexperience_1781549652 + MYSQL_HOST: 127.0.0.1 + MYSQL_PASS: K3E1ZZWvHDu0q8ZmoBCAhzKUZawEapdGBlbaPME1sOTKgGk9FCuYS + MYSQL_PORT: '33060' + MYSQL_USER: apextrackexperience_1781549652 + osint-person: + enabled: true + url: http://127.0.0.1:8902/mcp + super-search: + enabled: true + url: http://127.0.0.1:8899/mcp + twilio: + enabled: true + url: http://127.0.0.1:8901/mcp +memory: + consolidate_threshold: 5000 + flush_min_turns: 6 + max_chars: 10000 + memory_char_limit: 10000 + memory_enabled: true + nudge_interval: 10 + provider: holographic + user_char_limit: 5000 + user_profile_enabled: true +model: + default: openai/gpt-5.5 + fallbacks: + - model: deepseek/deepseek-r1 + provider: openrouter + - model: deepseek-v4-pro + provider: admin-ai + - model: deepseek/deepseek-chat + provider: openrouter + - model: llama3.2:3b + provider: ollama-local + provider: custom:openrouter +model_catalog: + enabled: true + ttl_hours: 1 + url: https://hermes-agent.nousresearch.com/docs/api/model-catalog.json +onboarding: + seen: + busy_input_prompt: true + profile_build_offered: true + tool_progress_prompt: true +providers: + admin-ai: + api_key: sk-REDACTED + base_url: https://admin-ai.itpropartner.com/v1 + ollama-local: + base_url: http://localhost:11434/v1 + default_model: llama3.2:3b + openrouter: + api_key: sk-REDACTED + base_url: https://openrouter.ai/api/v1 +security: + allow_lazy_installs: true + redact_secrets: true + tirith_enabled: true + tirith_fail_open: true + tirith_path: tirith + tirith_timeout: 5 +terminal: + backend: local + container_cpu: 1 + container_disk: 51200 + container_memory: 5120 + container_persistent: true + cwd: . + lifetime_seconds: 300 + timeout: 180 +timezone: America/New_York +tools: + tool_search: + enabled: auto + threshold_pct: 10 +toolsets: + - hermes-cli +vision: + model: gemini-flash-latest + provider: admin-ai +web: + backend: firecrawl + use_gateway: false +web_extract: + provider: firecrawl +web_search: + provider: firecrawl + +# ── Fallback Model ──────────────────────────────────────────────────── +# Automatic provider failover when primary is unavailable. +# Uncomment and configure to enable. Triggers on rate limits (429), +# overload (529), service errors (503), or connection failures. +# +# Supported providers: +# openrouter (OPENROUTER_API_KEY) — routes to any model +# openai-codex (OAuth — hermes auth) — OpenAI Codex +# nous (OAuth — hermes auth) — Nous Portal +# zai (ZAI_API_KEY) — Z.AI / GLM +# kimi-coding (KIMI_API_KEY) — Kimi / Moonshot +# kimi-coding-cn (KIMI_CN_API_KEY) — Kimi / Moonshot (China) +# minimax (MINIMAX_API_KEY) — MiniMax +# minimax-cn (MINIMAX_CN_API_KEY) — MiniMax (China) +# bedrock (AWS IAM / boto3) — AWS Bedrock (Converse API) +# +# For custom OpenAI-compatible endpoints, add base_url and key_env. +# +# fallback_model: +# provider: openrouter +# model: anthropic/claude-sonnet-4 diff --git a/configs/persona-and-brief.md b/configs/persona-and-brief.md new file mode 100644 index 0000000..e69de29 diff --git a/cron/crontab.txt b/cron/crontab.txt new file mode 100644 index 0000000..338f9ef --- /dev/null +++ b/cron/crontab.txt @@ -0,0 +1,11 @@ +# Hermes crontab — managed entries +TZ=America/New_York + +* * * * * /root/.hermes/scripts/dre-mail-poller.py +0 * * * * /root/.hermes/scripts/boys-mail-monitor.py collect 2>&1 | logger -t boys-mail-collect +0 19 * * * /root/.hermes/scripts/boys-mail-monitor.py summary 2>&1 | logger -t boys-mail-summary +0 8 * * * /root/shark-game/scraper/run.sh +*/15 * * * * /root/.hermes/scripts/shark-draft-reminder.sh 2>&1 | logger -t shark-draft-reminder +0 1 * * * /root/.hermes/scripts/hermes-backup.sh 2>&1 | logger -t hermes-full-backup +0 2 * * * /root/.hermes/scripts/backup-audit-check.sh 2>&1 | logger -t backup-audit +0 3 * * * /root/.hermes/scripts/root-essentials-backup.sh 2>&1 | logger -t root-essentials-backup diff --git a/docker/docuseal/docker-compose.yml b/docker/docuseal/docker-compose.yml new file mode 100644 index 0000000..361b42c --- /dev/null +++ b/docker/docuseal/docker-compose.yml @@ -0,0 +1,17 @@ +services: + docuseal: + image: docuseal/docuseal:latest + container_name: docuseal + restart: always + ports: + - "127.0.0.1:3000:3000" + volumes: + - ./data:/data + environment: + - HOST=http://localhost:3000 + - FORCE_SSL=false + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" diff --git a/docker/komodo/docker-compose.yml b/docker/komodo/docker-compose.yml new file mode 100644 index 0000000..0c774d6 --- /dev/null +++ b/docker/komodo/docker-compose.yml @@ -0,0 +1,56 @@ +services: + mongo: + image: mongo + restart: unless-stopped + command: --quiet --wiredTigerCacheSizeGB 0.25 + volumes: + - ./data/mongo-data:/data/db + - ./data/mongo-config:/data/configdb + networks: + - komodo-net + deploy: + resources: + limits: + memory: 1G + + core: + image: ghcr.io/moghtech/komodo-core:2 + init: true + restart: unless-stopped + ports: + - 9120:9120 + depends_on: + - mongo + volumes: + - ./backups:/backups + - ./keys:/config/keys + environment: + - KOMODO_DATABASE_ADDRESS=mongo:27017 + - KOMODO_PORT=9120 + - KOMODO_HOST=https://komodo.itpropartner.com + - KOMODO_TITLE=Komodo + - KOMODO_LOCAL_AUTH=true + - KOMODO_INIT_ADMIN_USERNAME=admin + - KOMODO_INIT_ADMIN_PASSWORD=changeme + - KOMODO_FIRST_SERVER_NAME=core + - KOMODO_PERIPHERY_PUBLIC_KEY=file:/config/keys/periphery.pub + - KOMODO_DISABLE_CONFIRM_DIALOG=false + - KOMODO_DISABLE_INIT_RESOURCES=false + - KOMODO_WEBHOOK_SECRET=komodo-webhook-secret + - KOMODO_JWT_SECRET=komodo-jwt-secret-change-me + - KOMODO_JWT_TTL=1-day + - KOMODO_MONITORING_INTERVAL=15-sec + - KOMODO_RESOURCE_POLL_INTERVAL=1-hr + - KOMODO_DISABLE_USER_REGISTRATION=false + - KOMODO_ENABLE_NEW_USERS=false + - KOMODO_TRANSPARENT_MODE=false + networks: + - komodo-net + deploy: + resources: + limits: + memory: 512M + +networks: + komodo-net: + driver: bridge diff --git a/docker/litellm/docker-compose.yml b/docker/litellm/docker-compose.yml new file mode 100644 index 0000000..2f17f09 --- /dev/null +++ b/docker/litellm/docker-compose.yml @@ -0,0 +1,33 @@ +version: "3.8" + +services: + openwebui: + image: ghcr.io/open-webui/open-webui:main + container_name: openwebui + ports: + - "3000:3000" + volumes: + - openwebui_data:/app/backend/data + environment: + - WEBUI_SECRET_KEY=your_secret_key + restart: unless-stopped + + litellm: + build: ../litellm + container_name: litellm + ports: + - "4000:4000" + volumes: + - litellm_data:/app/data + restart: unless-stopped + + mcp-email: + build: ../mcp-email + container_name: mcp-email + ports: + - "8902:8902" + restart: unless-stopped + +volumes: + openwebui_data: + litellm_data: \ No newline at end of file diff --git a/docker/mcp-email/Dockerfile b/docker/mcp-email/Dockerfile new file mode 100644 index 0000000..51dd023 --- /dev/null +++ b/docker/mcp-email/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.13-slim + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8902"] \ No newline at end of file diff --git a/docker/mcp-email/requirements.txt b/docker/mcp-email/requirements.txt new file mode 100644 index 0000000..f42f424 --- /dev/null +++ b/docker/mcp-email/requirements.txt @@ -0,0 +1,4 @@ +fastapi +fastmcp>=3.0 +uvicorn +python-dotenv \ No newline at end of file diff --git a/docker/mcp-filesystem/Dockerfile b/docker/mcp-filesystem/Dockerfile new file mode 100644 index 0000000..828bbf0 --- /dev/null +++ b/docker/mcp-filesystem/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.13-slim + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8900"] \ No newline at end of file diff --git a/docker/mcp-filesystem/requirements.txt b/docker/mcp-filesystem/requirements.txt new file mode 100644 index 0000000..cf7daf1 --- /dev/null +++ b/docker/mcp-filesystem/requirements.txt @@ -0,0 +1,3 @@ +fastapi>=0.68.0 +uvicorn>=0.15.0 +python-multipart>=0.0.5 \ No newline at end of file diff --git a/docker/mcp-git/Dockerfile b/docker/mcp-git/Dockerfile new file mode 100644 index 0000000..a1594b6 --- /dev/null +++ b/docker/mcp-git/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.13-slim + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY server.py . + +CMD ["python", "server.py"] \ No newline at end of file diff --git a/docker/mcp-git/requirements.txt b/docker/mcp-git/requirements.txt new file mode 100644 index 0000000..81cbd59 --- /dev/null +++ b/docker/mcp-git/requirements.txt @@ -0,0 +1,4 @@ +fastapi>=0.68.0 +uvicorn>=0.15.0 +requests>=2.26.0 +fastmcp>=3.0.0 \ No newline at end of file diff --git a/docker/searxng/docker-compose.yml b/docker/searxng/docker-compose.yml new file mode 100644 index 0000000..47d4ec7 --- /dev/null +++ b/docker/searxng/docker-compose.yml @@ -0,0 +1,26 @@ +version: '3.8' +services: + searxng: + image: searxng/searxng:latest + container_name: searxng + restart: always + ports: + - "127.0.0.1:8888:8080" + volumes: + - ./searxng-data:/etc/searxng:rw + - ./searxng-themes:/usr/local/searxng/searx/static/themes:rw + environment: + - SEARXNG_BASE_URL=http://localhost:8080 + - SEARXNG_SECRET_KEY=${SEARXNG_SECRET_KEY:-changeme} + cap_drop: + - ALL + cap_add: + - CHOWN + - SETGID + - SETUID + - DAC_OVERRIDE + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" diff --git a/docker/super-search/exa.env b/docker/super-search/exa.env new file mode 100644 index 0000000..b028166 --- /dev/null +++ b/docker/super-search/exa.env @@ -0,0 +1 @@ +EXA_API_KEY=d1720047-10bb-47d5-95a3-74e6eabeea16 diff --git a/docker/twenty/.mcp.json b/docker/twenty/.mcp.json new file mode 100644 index 0000000..0320cab --- /dev/null +++ b/docker/twenty/.mcp.json @@ -0,0 +1,22 @@ +{ + "mcpServers": { + "postgres": { + "type": "stdio", + "command": "bash", + "args": ["-c", "source packages/twenty-server/.env && npx -y @modelcontextprotocol/server-postgres \"$PG_DATABASE_URL\""], + "env": {} + }, + "playwright": { + "type": "stdio", + "command": "npx", + "args": ["@playwright/mcp@latest", "--no-sandbox", "--headless"], + "env": {} + }, + "context7": { + "type": "stdio", + "command": "npx", + "args": ["-y", "@upstash/context7-mcp"], + "env": {} + } + } +} diff --git a/docker/twenty/CLAUDE.md b/docker/twenty/CLAUDE.md new file mode 100644 index 0000000..0220510 --- /dev/null +++ b/docker/twenty/CLAUDE.md @@ -0,0 +1,224 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Twenty is an open-source CRM built with modern technologies in a monorepo structure. The codebase is organized as an Nx workspace with multiple packages. + +## Key Commands + +### Development +```bash +# Start development environment (frontend + backend + worker) +yarn start + +# Individual package development +npx nx start twenty-front # Start frontend dev server +npx nx start twenty-server # Start backend server +npx nx run twenty-server:worker # Start background worker +``` + +### Testing +```bash +# Preferred: run a single test file (fast) +npx jest path/to/test.test.ts --config=packages/PROJECT/jest.config.mjs + +# Run all tests for a package +npx nx test twenty-front # Frontend unit tests +npx nx test twenty-server # Backend unit tests +npx nx run twenty-server:test:integration:with-db-reset # Integration tests with DB reset +# To run an individual test or a pattern of tests, use the following command: +cd packages/{workspace} && npx jest "pattern or filename" + +# Storybook +npx nx storybook:build twenty-front +npx nx storybook:test twenty-front + +# When testing the UI end to end, click on "Continue with Email" and use the prefilled credentials. +``` + +### Code Quality +```bash +# Linting (diff with main - fastest, always prefer this) +npx nx lint:diff-with-main twenty-front +npx nx lint:diff-with-main twenty-server +npx nx lint:diff-with-main twenty-front --configuration=fix # Auto-fix + +# Linting (full project - slower, use only when needed) +npx nx lint twenty-front +npx nx lint twenty-server + +# Type checking +npx nx typecheck twenty-front +npx nx typecheck twenty-server + +# Format code +npx nx fmt twenty-front +npx nx fmt twenty-server +``` + +### Build +```bash +# Build packages (twenty-shared must be built first) +npx nx build twenty-shared +npx nx build twenty-front +npx nx build twenty-server +``` + +### Database Operations +```bash +# Database management +npx nx database:reset twenty-server # Reset database +npx nx run twenty-server:database:init:prod # Initialize database +npx nx run twenty-server:database:migrate:prod # Run instance commands (fast only) + +# Generate an instance command (fast or slow) +npx nx run twenty-server:database:migrate:generate --name --type +``` + +### Database Inspection (Postgres MCP) + +A read-only Postgres MCP server is configured in `.mcp.json`. Use it to: +- Inspect workspace data, metadata, and object definitions while developing +- Verify migration results (columns, types, constraints) after running migrations +- Explore the multi-tenant schema structure (core, metadata, workspace-specific schemas) +- Debug issues by querying raw data to confirm whether a bug is frontend, backend, or data-level +- Inspect metadata tables to debug GraphQL schema generation issues + +This server is read-only — for write operations (reset, migrations, sync), use the CLI commands above. + +### GraphQL +```bash +# Generate GraphQL types (run after schema changes) +npx nx run twenty-front:graphql:generate +npx nx run twenty-front:graphql:generate --configuration=metadata +``` + +## Architecture Overview + +### Tech Stack +- **Frontend**: React 18, TypeScript, Jotai (state management), Linaria (styling), Vite +- **Backend**: NestJS, TypeORM, PostgreSQL, Redis, GraphQL (with GraphQL Yoga) +- **Monorepo**: Nx workspace managed with Yarn 4 + +### Package Structure +``` +packages/ +├── twenty-front/ # React frontend application +├── twenty-server/ # NestJS backend API +├── twenty-ui/ # Shared UI components library +├── twenty-shared/ # Common types and utilities +├── twenty-emails/ # Email templates with React Email +├── twenty-website/ # Next.js marketing website +├── twenty-docs/ # Documentation website +├── twenty-zapier/ # Zapier integration +└── twenty-e2e-testing/ # Playwright E2E tests +``` + +### Key Development Principles +- **Functional components only** (no class components) +- **Named exports only** (no default exports) +- **Types over interfaces** (except when extending third-party interfaces) +- **String literals over enums** (except for GraphQL enums) +- **No 'any' type allowed** — strict TypeScript enforced +- **Event handlers preferred over useEffect** for state updates +- **Props down, events up** — unidirectional data flow +- **Composition over inheritance** +- **No abbreviations** in variable names (`user` not `u`, `fieldMetadata` not `fm`) + +### Naming Conventions +- **Variables/functions**: camelCase +- **Constants**: SCREAMING_SNAKE_CASE +- **Types/Classes**: PascalCase (suffix component props with `Props`, e.g. `ButtonProps`) +- **Files/directories**: kebab-case with descriptive suffixes (`.component.tsx`, `.service.ts`, `.entity.ts`, `.dto.ts`, `.module.ts`) +- **TypeScript generics**: descriptive names (`TData` not `T`) + +### File Structure +- Components under 300 lines, services under 500 lines +- Components in their own directories with tests and stories +- Use `index.ts` barrel exports for clean imports +- Import order: external libraries first, then internal (`@/`), then relative + +### Comments +- Use short-form comments (`//`), not JSDoc blocks +- Explain WHY (business logic), not WHAT +- Do not comment obvious code +- Multi-line comments use multiple `//` lines, not `/** */` + +### State Management +- **Jotai** for global state: atoms for primitive state, selectors for derived state, atom families for dynamic collections +- Component-specific state with React hooks (`useState`, `useReducer` for complex logic) +- GraphQL cache managed by Apollo Client +- Use functional state updates: `setState(prev => prev + 1)` + +### Backend Architecture +- **NestJS modules** for feature organization +- **TypeORM** for database ORM with PostgreSQL +- **GraphQL** API with code-first approach +- **Redis** for caching and session management +- **BullMQ** for background job processing + +### Database & Upgrade Commands +- **PostgreSQL** as primary database +- **Redis** for caching and sessions +- **ClickHouse** for analytics (when enabled) +- When changing entity files, generate an **instance command** (`database:migrate:generate --name --type `) +- **Fast** instance commands handle schema changes; **slow** ones add a `runDataMigration` step for data backfills +- **Workspace commands** iterate over all active/suspended workspaces for per-workspace upgrades +- Commands use `@RegisteredInstanceCommand` and `@RegisteredWorkspaceCommand` decorators for automatic discovery +- Include both `up` and `down` logic in instance commands +- Never delete or rewrite committed instance command `up`/`down` logic +- See `packages/twenty-server/docs/UPGRADE_COMMANDS.md` for full documentation + +### Utility Helpers +Use existing helpers from `twenty-shared` instead of manual type guards: +- `isDefined()`, `isNonEmptyString()`, `isNonEmptyArray()` + +## Development Workflow + +IMPORTANT: Use Context7 for code generation, setup or configuration steps, or library/API documentation. Automatically use the Context7 MCP tools to resolve library IDs and get library docs without waiting for explicit requests. + +### Before Making Changes +1. Always run linting (`lint:diff-with-main`) and type checking after code changes +2. Test changes with relevant test suites (prefer single-file test runs) +3. Ensure instance commands are generated for entity changes (`database:migrate:generate`) +4. Check that GraphQL schema changes are backward compatible +5. Run `graphql:generate` after any GraphQL schema changes + +### Code Style Notes +- Use **Linaria** for styling with zero-runtime CSS-in-JS (styled-components pattern) +- Follow **Nx** workspace conventions for imports +- Use **Lingui** for internationalization +- Apply security first, then formatting (sanitize before format) + +### Testing Strategy +- **Test behavior, not implementation** — focus on user perspective +- **Test pyramid**: 70% unit, 20% integration, 10% E2E +- Query by user-visible elements (text, roles, labels) over test IDs +- Use `@testing-library/user-event` for realistic interactions +- Descriptive test names: "should [behavior] when [condition]" +- Clear mocks between tests with `jest.clearAllMocks()` + +## Dev Environment Setup + +All dev environments (Claude Code web, Cursor, local) use one script: + +```bash +bash packages/twenty-utils/setup-dev-env.sh +``` + +This handles everything: starts Postgres + Redis (auto-detects local services vs Docker), creates databases, copies `.env` files, and initializes the database schema (runs migrations) on a fresh database. Idempotent — safe to run multiple times. + +- `--docker` — force Docker mode (uses `packages/twenty-docker/docker-compose.dev.yml`) +- `--down` — stop services +- `--reset` — wipe data and restart fresh +- **Skip the setup script** for tasks that only read code — architecture questions, code review, documentation, etc. + +**Note:** CI workflows (GitHub Actions) manage services via Actions service containers and run setup steps individually — they don't use this script. + +## Important Files +- `nx.json` - Nx workspace configuration with task definitions +- `tsconfig.base.json` - Base TypeScript configuration +- `package.json` - Root package with workspace definitions +- `.cursor/rules/` - Detailed development guidelines and best practices diff --git a/docker/twenty/DESIGN.md b/docker/twenty/DESIGN.md new file mode 100644 index 0000000..9d3db7f --- /dev/null +++ b/docker/twenty/DESIGN.md @@ -0,0 +1,159 @@ +# Twenty Website — DESIGN.md + +> Visual system for the Twenty marketing site. Distilled from `packages/twenty-website/src/theme/`. Loaded by every `impeccable` invocation alongside PRODUCT.md. + +## Theme + +**Light by default.** A founder browsing a partner profile in daylight on a 14–27 inch monitor is the default scene. The site does ship a `data-scheme="dark"` override (see `css-variables.ts`), but no current public page opts into it. Treat dark as a deferred surface. + +## Color + +Palette is OKLCH-equivalent neutrals at the surface level. The brand accents (blue, pink, yellow, green) are present in the token system but used sparingly — none of them appear on the partner pages. + +### Strategy: Restrained + +Tinted neutrals + one accent ≤10%. The accent for partner pages is the deep ink black (`var(--color-black-100)`) used in CTAs and hover states. Anything beyond a hairline border, an icon glyph, or a primary CTA should question whether it needs color at all. + +### Tokens (from `src/theme/colors.ts` + `css-variables.ts`) + +Neutrals (the workhorses): + +| Token | Hex (computed) | Role | +| --- | --- | --- | +| `colors.primary.background[100]` | `#ffffff` | Page + card surface | +| `colors.primary.text[100]` | `#1c1c1c` | Headlines, primary text | +| `colors.primary.text[80]` | `#1c1c1ccc` | Body text | +| `colors.primary.text[60]` | `#1c1c1c99` | Eyebrows, meta, captions | +| `colors.primary.text[40]` | `#1c1c1c66` | Disabled / placeholder | +| `colors.primary.text[20]` | `#1c1c1c33` | Subtle separators | +| `colors.primary.text[10]` | `#1c1c1c1a` | Hairline borders | +| `colors.primary.text[5]` | `#1c1c1c0d` | Subtle fills (rates panel, skill chips) | +| `colors.primary.border[10]` | `#1c1c1c1a` | Default border | +| `colors.primary.border[20]` | `#1c1c1c33` | Hover border | + +Reverse palette (for dark CTAs): + +| Token | Role | +| --- | --- | +| `colors.secondary.background[100]` | Filled CTA background (deep ink) | +| `colors.secondary.text[100]` | Filled CTA text (white) | + +Brand accents (currently absent from partner pages; available if needed): + +- `colors.accent.blue` — `#4a38f5` / `#8174f8` +- `colors.accent.pink` — `#ed87fc` / `#f3abfd` +- `colors.accent.yellow` — `#feffb7` / `#feffd9` +- `colors.accent.green` — `#89fc9a` / `#b0fdbe` +- `colors.highlight` — same hue as blue accent + +**Do not introduce gradients, glass blurs, or saturated fills on partner pages.** Color is conviction here, not decoration. + +## Typography + +Three families, each load-balanced via CSS variables: + +| Family | Var | Use | +| --- | --- | --- | +| `theme.font.family.serif` | `--font-serif` | Headlines, partner names, headline values | +| `theme.font.family.sans` | `--font-sans` | Body, prose, interactive labels | +| `theme.font.family.mono` | `--font-mono` | Eyebrows, meta, currency labels, tabular numerics | +| `theme.font.family.retro` | `--font-retro` | Reserved (not used on partner pages) | + +### Weight + Size Contrast + +Weights: `light: 300`, `regular: 400`, `medium: 500`. No bold. Hierarchy is driven by scale and family contrast, never by weight alone. + +Scale (`theme.font.size(n)` → `calc(var(--font-base) * n)`, where `--font-base: 0.25rem` ≈ 4px): + +- Display / h1: size 9–12 (36–48px) +- h2 / section heads: size 7–8 (28–32px) +- h3 / card heads: size 5–6 (20–24px) +- Body / prose: size 4–5 (16–20px) +- Eyebrow / meta: size 3 (12px) with `letter-spacing: 0.06–0.08em` and `text-transform: uppercase` + +Body line length: cap at 65–75ch (the existing `PartnerProfileIntro` uses `max-width: 62ch` — keep that order of magnitude). + +### Hierarchy contract + +- A serif `

` at size 9 light reads as a partner's name on the detail page. +- A mono eyebrow above or below it locates the partner (region · city · country). +- A serif size 6 light reads as a section head. +- Body prose is sans regular. +- Currency values are serif (they read as headline numbers, not stats). +- Currency labels and meta are mono. + +## Spacing & Layout + +Base unit `4px`. Spacing helper `theme.spacing(n)` returns `n * 4px`. Common rhythms on the partner pages: + +- Inter-section gap on the detail page: `theme.spacing(10–14)` — generous, editorial breathing room. +- Inter-element gap inside a section: `theme.spacing(3–5)`. +- Card padding: `theme.spacing(6)`. +- Page horizontal padding: `theme.spacing(4)` mobile, `theme.spacing(10)` ≥ md breakpoint. + +### Radius + +`theme.radius(n)` returns `n * 2px`. The default card radius is `theme.radius(2)` = 4px. Pills use `999px`. No softer rounding than that. + +### Borders + +Borders are hairline (`1px solid theme.colors.primary.border[10]`). They define edges quietly. On hover they step to `border[20]`. Never use a chunky border as decoration. + +## Components + +### Card (PartnerCard, RatesPanel) + +White surface, hairline border, 4px radius, 24px padding, soft shadow on hover only: + +```css +background-color: ${theme.colors.primary.background[100]}; +border: 1px solid ${theme.colors.primary.border[10]}; +border-radius: ${theme.radius(2)}; +padding: ${theme.spacing(6)}; + +&:hover { + border-color: ${theme.colors.primary.border[20]}; + box-shadow: 0 12px 32px -16px rgba(0, 0, 0, 0.18); + transform: translateY(-2px); +} +``` + +### Chip / Pill + +Rounded `999px`, 1px border, subtle background fill (`primary.text[5]` for filter pills, transparent for chip rows), `text[80]` color, mono or sans font. + +### Button / LinkButton + +Lives in `@/design-system/components`. Two color modes: `primary` (deep ink fill, white text) and `secondary` (transparent fill, ink text + 1px border). `variant="contained"` is what partner pages use. + +### Avatar + +`PartnerAvatar` is a deterministic generated mark from name + slug. Used as fallback when `profilePictureUrl` is missing. The real photo overlays it at 120px circle on the detail page, 56px on the list card. + +## Motion + +- Hover transitions: 250ms, ease-out (cubic-bezier curve in `PartnerCard`: `0.25s ease`). +- Card entrance: 700ms cubic-bezier `0.22, 1, 0.36, 1` (ease-out-quart), 90ms stagger per index. +- All motion respects `@media (prefers-reduced-motion: reduce)` — animations stop, hover translate disabled. +- **No bounce, no elastic, no parallax.** Editorial restraint. + +## Iconography + +`@tabler/icons-react`, 14–16px on body-level chips, 18–24px on buttons. Always `aria-hidden="true"` when decorative. Stroke width `2` (default). + +## Accessibility Defaults + +- Focus ring: `outline: 2px solid theme.colors.primary.text[100]; outline-offset: 4px` (already used on the card link). +- Touch target ≥ 40×40px on mobile. +- `aria-label` on icon-only buttons, `aria-labelledby` on sectioned regions. +- All `` includes `rel="noopener noreferrer"`. +- Color is never the sole carrier of meaning. The money pills carry both an icon and a text label. + +## Anti-patterns (project-specific) + +In addition to the impeccable shared absolute bans: + +- **Do not use the brand accent colors (blue/pink/yellow/green) on partner pages** unless we have a stronger reason than "to add color". +- **No skeuomorphic shadows on cards.** The hover shadow is `0 12px 32px -16px rgba(0,0,0,0.18)` — that's the ceiling. +- **No gradients on anything.** Including text, borders, and backgrounds. +- **No floating "Trusted by" logo bars** on partner pages. diff --git a/docker/twenty/PRODUCT.md b/docker/twenty/PRODUCT.md new file mode 100644 index 0000000..277a20b --- /dev/null +++ b/docker/twenty/PRODUCT.md @@ -0,0 +1,80 @@ +# Twenty Website — Product & Brand Context + +> Strategic context for design work on the Twenty marketing site (`packages/twenty-website`). Loaded by every `impeccable` invocation. + +## Register + +**Brand.** The marketing site is a public-facing surface where the design itself is part of the credibility argument. Prospects evaluate Twenty partly by how the site feels. The product app (`packages/twenty-front`) is a separate product-register surface, governed elsewhere. + +## Users & Purpose + +The primary audience varies by route, but the working assumption for partner-related pages is: + +- **Who:** A budget-holding decision maker (founder, RevOps lead, or COO) shopping for a CRM implementation partner. Already on Twenty's site, evaluating a shortlist of partners. +- **Context:** Doing a side-by-side comparison across 2–5 candidates over a single browsing session. Will spend 30–90 seconds on each profile before deciding whether to book a call. +- **Decision being made:** "Is this partner credible, the right size, the right specialty, and within budget? Do I trust them enough to commit 30 minutes to a discovery call?" + +What the partner pages must do, in priority order: +1. Communicate credibility (real firm, real person, real work). +2. Surface fit signals fast (skills, region, languages, deployment expertise, budget range). +3. Give the visitor a confident "next step" affordance (book a call or vet via LinkedIn) without pressure. + +## Desired Outcome + +The redesign should make `/partners/profile/[slug]` feel like a *thoughtfully curated profile of a top-tier partner*, not a generic templated card. A visitor should leave thinking "this firm is serious" even if they don't book a call this session. + +Specifically: +- **Confidence over information density.** A short, well-typeset profile beats a packed-but-busy one. +- **Editorial restraint.** White space, deliberate type hierarchy, and a few well-chosen details say more than dozens of small components. +- **Quiet conviction.** No hype copy, no growth-hack patterns, no "Trusted by" logo strips. The partner's own work and intro speak for themselves. + +## Brand Personality + +**Editorial · Founder-led · Considered.** + +The site reads like a thoughtful indie publication, not a SaaS landing page. Serif headlines, plenty of whitespace, deliberate typographic rhythm. Quietly opinionated — Twenty has a point of view about CRM (open-source, customizable, well-designed) and the site reflects that without shouting. + +Tonal anchors: +- Stripe's documentation for clarity, Linear's marketing for restraint, an editorial print magazine for typography choices. + +## Anti-references + +**Reject these patterns. They make the work read as generic AI / generic SaaS:** + +- **Generic SaaS landing.** Big-number heroes, identical icon-grid cards, gradient text, navy + lime accent color schemes, "supercharge your workflow" language. +- **Corporate enterprise tone.** Stock photos of diverse handshakes. "Trusted by Fortune 500" logo strips as the primary credibility move. Trust-badge bars. +- **Bento templates.** Repetitive same-size cards. Vercel-style scroll-pin animations on every section. +- **Side-stripe borders, gradient text, glassmorphism, hero-metric templates, identical card grids** — see impeccable's shared absolute bans. + +## Strategic Design Principles + +1. **Typography carries the design.** The brand has a serif/sans/mono trio. Hierarchy is set by scale + weight contrast, not by color or borders. +2. **Restrained palette.** Tinted neutrals (black/white via CSS variables, with alpha-tone variants for text and borders) carry 90%+ of the surface. Accent color used sparingly when it appears at all. +3. **Whitespace is a feature.** Tight cards feel cheap. Pages should breathe. +4. **Asymmetry over grid.** A 12-col bento is the wrong shape for a profile page. Use asymmetric two-column layouts where one column does heavy lifting. +5. **One opinionated detail per page.** Each surface should have one moment of editorial conviction (a typographic flourish, a precise micro-interaction, a deliberate space) rather than five generic flourishes. + +## Accessibility + +**WCAG AA + keyboard + screen reader baseline:** + +- All interactive elements reachable by keyboard, focus visible (`outline: 2px solid`, not just color shift). +- Semantic landmarks: `
`, `
`, `