fix(memos-local-plugin): per-agent legacy migration path + per-agent auth cookie#1548
Merged
hijzy merged 1 commit intoApr 27, 2026
Conversation
…auth cookie
Two viewer-side bugs surfaced when openclaw and hermes are installed
side by side on the same machine:
1. **Legacy DB migration always read openclaw's path.**
The "import from legacy plugin" feature hard-coded the source DB
to `~/.openclaw/memos-local/memos.db`, so running the migration
inside the hermes viewer imported openclaw's old memories. Make
the path agent-aware (`hermes` → `~/.hermes/memos-state/memos-local/memos.db`),
add a generic `/api/v1/migrate/legacy/{scan,run}` endpoint that
uses `options.agent`, and keep explicit `/openclaw/*` and
`/hermes/*` aliases for clarity. Response now carries `agent` +
`path` so the viewer / tests can verify which DB was read.
2. **Viewer logged out the other agent on refresh.**
Both servers issued the cookie name `memos_sess` with `Path=/`.
Browsers do not isolate cookies by port, so logging into one
agent overwrote the other's cookie; the next refresh failed MAC
verification and the AuthGate kicked the user back to the login
screen. Scope the cookie name per agent (`memos_sess_<agent>`),
plumb `options.agent` through `registerAuthRoutes` and
`requireSession`, and keep a legacy-name fallback on read so
already-logged-in users aren't kicked out by the upgrade itself.
Tests:
- `tests/unit/server/http.test.ts` covers the openclaw/hermes/legacy
migrate endpoints + the agent-aware path resolution.
- New `tests/unit/server/auth-cookie-isolation.test.ts` reproduces
the original "refresh-one-logs-out-the-other" scenario end-to-end
and pins per-agent isolation, cross-agent rejection, and legacy
cookie fallback.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two viewer-side bugs surface as soon as openclaw and hermes are installed side by side on the same host. Both are fixed in this PR.
1. Legacy DB migration always read openclaw's path
server/routes/migrate.tshard-coded the source DB to~/.openclaw/memos-local/memos.db, so triggering "import from legacy plugin" inside the hermes viewer happily imported openclaw's old memories. The hermes legacy plugin actually lived at~/.hermes/memos-state/memos-local/memos.db(note the extramemos-statesegment).options.agent:openclaw→~/.openclaw/memos-local/memos.dbhermes→~/.hermes/memos-state/memos-local/memos.dbGET/POST /api/v1/migrate/legacy/{scan,run}for the viewer to call (the running agent picks its own path)./openclaw/*and/hermes/*aliases kept for clarity + back-compat.agentandpathso the UI shows exactly which file was read.server.migratelog channel (registered incore/logger/channels.tsanddocs/LOGGING.md).2. Refreshing one viewer logged out the other
Both servers issued the cookie name
memos_sesswithPath=/. Browsers do not isolate cookies by port, so:memos_sess=tokenA(signed with openclaw'ssessionSecret).memos_sess=tokenB(signed with hermes'ssessionSecret). The second one overwrites the first.The fix scopes the cookie name per agent (
memos_sess_<agent>):registerAuthRoutes(routes, deps, options)andrequireSession(..., agent)now know which agent they serve.cookieNameFor(agent)returnsmemos_sess_<agent>when an agent is configured, otherwise the legacymemos_sess(so single-agent installs and test fixtures keep working).readSessionCookiefalls back to the legacy name on read, so users who were already logged in before the upgrade are not kicked out by the deploy itself; the next response writes the new per-agent cookie and the transition is silent.clearSessionCookieclears both the per-agent name and the legacy name on logout.Test plan
npx vitest run tests/unit/server— 56 of 56 pre-existing tests still pass; 12 new tests pass:tests/unit/server/http.test.tscovering openclaw/hermes/legacy endpoints + theagentfield + the path string.tests/unit/server/auth-cookie-isolation.test.ts:memos_sess, onlymemos_sess_<agent>)authenticated: true(the original bug)memos_sesscookie is still honourednpm run lintis clean on every file touched in this PR (the repo has unrelated pre-existing TS errors that this PR does not introduce).memos_sess_openclawandmemos_sess_hermescoexisting.~/.hermes/memos-state/memos-local/memos.dbpath (not.openclaw/...).Notes
mem-agent-0424(countEpisodes/countTraces/countSkillsmissing from the test stub) are not introduced by this PR — they reproduce on the unmodified target branch.