Skip to content

feat!: Migrate to Hermes Agent (v2.0.0) - #31

Merged
rekurt merged 5 commits into
masterfrom
migrate/hermes
Oct 25, 2026
Merged

rekurt merged 5 commits into
masterfrom
migrate/hermes

Conversation

@rekurt

@rekurt rekurt commented Oct 25, 2026

Copy link
Copy Markdown
Owner

Summary

Complete big-bang migration of CortexForge v2.0.0 from legacy OpenClaw to NousResearch Hermes Agent (nousresearch/hermes-agent:v0.22.5) with zero legacy references remaining.

Type of Change

  • ✨ New feature
  • 🔒 Security fix
  • 📚 Documentation
  • 🔧 Refactor / chore

Changes

  • Docker images & Compose: Switched instances/Dockerfile.user and instances/admin/Dockerfile to nousresearch/hermes-agent:v0.22.5; updated docker-compose.yml mounts (hermes_data:/opt/data, workspace:/opt/data/workspace), dashboard port (9119), HERMES_UID/GID=1000, and parameterized DOCKER_GID.
  • Configuration & Provisioning: Added instances/_template/hermes_config.yaml.template and instances/admin/config.yaml; created scripts/provision-hermes-data.sh (make bootstrap / make deploy) to provision hermes_data/, .env, SOUL.md sync, and 1000:1000 ownership while strictly isolating admin vs user quota keys.
  • Scripts & Security: Rewrote scripts/add-user.sh (mandatory TG_ID, fail-fast root .env check, first-free port allocation, SOUL.md sync); hardened scripts/backup.sh (umask 077, chmod 600, excluded .env and hermes_data/ssh/*); removed legacy OAuth scripts and historical OpenClaw migrations; fixed all ShellCheck warnings.
  • Documentation & Runbook: Added full migration plan and VPS cutover runbook in docs/migration-hermes.md; updated README.md, README.ru.md, CLAUDE.md, docs/SETUP.md, and CONTRIBUTING.md.

Testing

  • Ran python3 -m unittest discover tests/ -v — 130/130 tests pass
  • Ran python3 .github/scripts/ai_security_check.py — no findings
  • Ran shellcheck scripts/*.sh — 0 warnings / 0 errors
  • Ran make security-check — verified

Documentation

  • README updated (README.md, README.ru.md)
  • Relevant doc in docs/ updated (docs/SETUP.md, docs/SECURITY.md, docs/migration-hermes.md)
  • CHANGELOG.md entry added (or release-please will handle it)

Security

  • No secrets, tokens or credentials added to code or .env.example
  • No new subprocess.run() calls without input validation
  • No new network endpoints without auth

Notes for Reviewer

Reviewed across 3 full rounds by the agent team (Megatron, Ratchet, Quintus) until zero blocker/critical/high/medium issues remained.

BREAKING CHANGE: all instances now run NousResearch Hermes Agent instead
of OpenClaw. Fresh-install cutover: no data/session import, workspaces
are recreated from templates.

- images: Dockerfile.user / admin/Dockerfile on nousresearch/hermes-agent:stable
- compose: admin builds locally, hermes_data -> /opt/data, dashboard 9119
  (port map 18789 / 18790+N preserved), HERMES_UID/GID=1000
- configs: instances/_template/hermes_config.yaml.template + admin/config.yaml
  (quota-proxy provider, api_mode anthropic_messages, voice.stt openai)
- scripts: add-user.sh rewritten for hermes_data/.env scheme
  (TELEGRAM_BOT_TOKEN, TELEGRAM_ALLOWED_USERS, HERMES_GATEWAY_TOKEN);
  backup/fix-permissions/autoupdate/migrate-instances updated;
  refresh-oauth.py and update-token.py removed (OAuth lives in CLIProxyAPI)
- legacy cleanup: openclaw.json templates, legacy workspace migrations and
  all openclaw/clawdbot/moltbot references removed (grep = 0)
- docs: README x2, CLAUDE.md, docs/SECURITY.md rebranded; migration plan
  in docs/migration-hermes.md
Blockers/high:
- add-user.sh: TG_ID required (empty allowlist = silent dead bot), root
  .env required for quota registration, trailing-newline guard before
  append, first-free-port scan, SOUL.md copied to hermes_data (Hermes
  reads persona from ~/.hermes), docker compose config validation
- scripts/provision-hermes-data.sh + make bootstrap: hermes_data for
  admin and existing instances (dirs, .env mapped from legacy var names,
  SOUL.md, chown 1000:1000)
- legacy OAuth scripts removed: refresh-anthropic-token.sh,
  refresh_token.py (+CLAUDE.md row)
- sync-instances.sh: workspace path fixed (legacy -workspace layout was
  silently dead); WORKSPACE_PARENT removed everywhere
- compose: group_add ${DOCKER_GID:-999} (was hardcoded 988), honest
  docker.sock comment
- Dockerfiles: pinned v0.22.5 (no floating stable + 5-min autoupdate);
  admin installs only docker-compose-plugin (host CLI is mounted anyway)
- template config: provider anthropic + base_url override (invented
  'quota-proxy' provider name could fail validation)

Majors/minors:
- backup.sh: excludes .env secrets, chmod 600 archive
- fix-permissions.sh: chown 1000:1000 hermes_data
- migrate-instances.py: load_migration wrapped in try, dead code removed
- .env.example / CONTRIBUTING / README x2 / SETUP: TELEGRAM_ALLOWED_USERS,
  HERMES_GATEWAY_TOKEN, OPENAI_API_KEY
- .gitignore: OpenClaw-era entries removed
- template workspace ships .migrations_applied (fresh installs skip the
  20 historical migrations)
- docs/migration-hermes.md: VPS deploy runbook (token preservation!),
  honest rollback section, Q&A closed with doc evidence
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review 🔄 Running since 2026-10-25T09:32:36.379108Z c45bafb PR opened
🔒 Security Review ✅ Completed 2026-10-25T09:40:02.264447Z c45bafb PR opened

Security findings

Advisory findings (1)

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Security Check Results

Check Result
🔑 Secrets ✅ success
🐍 SAST Python ✅ success
🤖 AI Security ✅ success
🐳 Docker ✅ success
🐚 ShellCheck ✅ success
📦 Dependencies ✅ success

Все проверки пройдены.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ Codex Security Review · Automatically triggered

Here are some automated security review suggestions for this pull request.

Reviewed commit: c45bafbb39

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread scripts/provision-hermes-data.sh Outdated
# Персона: Hermes читает SOUL.md из ~/.hermes (=/opt/data), источником истины служит workspace/SOUL.md
if [ -f "$DIR/workspace/SOUL.md" ]; then
if [ ! -f "$DIR/hermes_data/SOUL.md" ] || ! diff -q "$DIR/workspace/SOUL.md" "$DIR/hermes_data/SOUL.md" >/dev/null 2>&1; then
cp "$DIR/workspace/SOUL.md" "$DIR/hermes_data/SOUL.md"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛡️ Codex Security Review · Automatically triggered

P1 Badge Security: Reject symlinks before synchronizing SOUL.md

An authenticated user or compromised user bot can exploit this when an operator next runs make deploy: both workspace and hermes_data are writable by the user container, so it can replace workspace/SOUL.md with a symlink to ../../../.env. This host-side cp dereferences the link and copies the root .env into the user's /opt/data/SOUL.md, exposing Anthropic, quota-admin, broker, monitor, and service credentials. Use descriptor-based no-follow copies or keep the authoritative source outside user-writable mounts.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 78ba1e9: rejected symlinks across scripts/provision-hermes-data.sh (using O_NOFOLLOW + S_ISREG descriptor copy), scripts/sync-instances.sh (! -L + cp -P), and scripts/migrate-instances.py (is_symlink() + follow_symlinks=False), and added regression coverage in tests/test_symlink_protection.py.

@rekurt
rekurt merged commit c68d20e into master Oct 25, 2026
12 checks passed
@rekurt
rekurt deleted the migrate/hermes branch October 25, 2026 13:58
rekurt pushed a commit that referenced this pull request Oct 26, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.0.0](v0.6.0...v1.0.0)
(2026-10-26)


### ⚠ BREAKING CHANGES

* Migrate to Hermes Agent (v2.0.0)
([#31](#31))

### Features

* Add Enterprise 1000-user scaling, SSE quota accounting, and bulk
provisioning ([#33](#33))
([02997fb](02997fb))
* Migrate to Hermes Agent (v2.0.0)
([#31](#31))
([c68d20e](c68d20e))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant