v1.86.0
EvoMap/evolverv1.86.0May 23, 2026by autogame-17
AI Summary
Introduces optional OS-keychain backing for the `workspace-id` secret, replacing the previous filesystem-only storage. This enhances security by moving secrets out of plain text files.
Key Highlights
- Workspace-id can now live in the OS keychain (macOS, Linux, Windows).
- New `EVOLVER_WORKSPACE_KEYCHAIN` environment variable controls behavior (auto/force/off).
- Fixes lifecycle 'hello' to prevent minting a fresh `node_id` when legacy files exist.
- New changelog integrity guard prevents misattribution of release sections.
New Features
- OS-keychain backing for workspace-id
Full Release Notes
## v1.86.0 — Optional OS-keychain backing for `workspace-id` (issue #111 Phase 1)
### Highlights
- **Workspace-id can now live in the OS keychain instead of `<workspace>/.evolver/workspace-id`.** Closes the same-uid readability gap left by v1.83's FS-only secret. Optional `@napi-rs/keyring` addon backs the secret onto macOS Keychain Services / libsecret on Linux / Windows Credential Manager. Behaviour is identical to v1.85.x for any deployment that doesn't install the optional addon.
### Added
- **`EVOLVER_WORKSPACE_KEYCHAIN={auto,force,off}` (default: `auto`)** — controls how `getWorkspaceId()` resolves the per-workspace secret:
- `auto` — try keychain, fall back to FS on any failure. Existing FS secrets migrate into the keychain on first call. The FS file is intentionally kept so bun-compiled binaries (which can't sideload the `.node` addon yet — Phase 2) keep agreeing with node-CLI sessions on the same id.
- `force` — keychain only. Throws if the addon isn't loaded, the keyring reports unavailable mid-call, or write fails. Use in CI to assert the addon is present and never falls back to FS plaintext.
- `off` — skip keychain entirely; FS only.
- `EVOLVER_WORKSPACE_ID` env override is unchanged and still wins over both keychain and FS.
### Fixed
- **Lifecycle `hello` no longer mints a fresh `node_id` when MailboxStore is empty but `~/.evomap/node_id` still exists.** Any install whose `state.json` was created or wiped after the legacy file existed (upgrade from a pre-lifecycle version, partial recovery flow) registered a brand-new A2ANode under the same owner on the next daemon boot, abandoning the original record's stake / reputation / aliases as an orphan in the web UI. The reader now consults the legacy hex file between the store lookup and the `crypto.randomBytes(6)` fallback so both paths agree on a single identity.
### Refactored
- **Lifecycle's legacy `node_id` reader now routes through `paths.getEvomapPath()`** so `EVOLVER_HOME` honours both reader and writer in lockstep (the writer in `src/gep/a2aProtocol.js` was consolidated onto the same helper in #114). No behaviour change beyond unifying the override semantics.
### Internal
- **End-to-end test for the issue #540 advisory-signal fix and a new CHANGELOG release-section integrity guard (#113 / #115).** PR #105 added function-level tests; the new e2e tests run `collect.js` outputs through `gep/signals.js` to lock in the full pipeline so a future refactor that breaks either end fails loudly. The new `scripts/check-changelog.js` + `pre_publish_check.js` integration catches the misattribution pattern that bit us in #540 / PR #107 (an entry filed under `## [X.Y.Z]` after vX.Y.Z was already published). `extractSection` is line-anchored so fenced code samples don't trigger false drift; `EVOLVER_CHANGELOG_GUARD_SOFT=1` is available as an interim escape hatch while private-dev still relies on public-mirror tags.
### Migration
- Existing v1.85.x installs that haven't installed `@napi-rs/keyring` continue to use the FS path with no behaviour change.
- To opt in: `npm install @napi-rs/keyring` (already in `optionalDependencies`, so a fresh `npm install` will pull it on supported platforms automatically).
- To enforce keychain-only on CI: `export EVOLVER_WORKSPACE_KEYCHAIN=force`.
### Issue / PR
- Issue #111 Phase 1 — PR #121
- Issue #113 / #540 — PR #115