Skip to content

fix: local vault inaccessible in remote mode — close the two-vaults residual (rc8)#190

Merged
cipher813 merged 1 commit into
mainfrom
fix/local-vault-inaccessible-in-remote-mode
Jun 4, 2026
Merged

fix: local vault inaccessible in remote mode — close the two-vaults residual (rc8)#190
cipher813 merged 1 commit into
mainfrom
fix/local-vault-inaccessible-in-remote-mode

Conversation

@cipher813
Copy link
Copy Markdown
Owner

Follow-up to #188 (rc7), which made mnemon serve proxy to the remote but left a residual hole.

The residual two-vaults hole

PR #188 fixed serve, but every other default-vault open — the local-vault CLI commands (rebuild/forget/standing/doctor/sync), the dashboard, the api — still opened, and would re-create, a local ~/.mnemon/default.sqlite when a remote vault is configured. Since the real local vault was decommissioned (moved aside) on 2026-06-04, any such call recreates a fresh empty local vault — silently resurrecting the exact two-vaults trap (this is why mcp__mnemon__* returned an empty timeline this session).

Fix — chokepoint guard

Store.__init__ now refuses to open the default local vault when a remote is configured (MNEMON_REMOTE_URL / ~/.mnemon/remote_url) and raises LocalVaultInaccessibleErrorfail loud, never empty/stale. Exempt:

  • explicit db_path (tests, migrations),
  • serve-remote (it is the vault — sets the override at its entrypoint),
  • MNEMON_ALLOW_LOCAL_STORE=1 (genuine local maintenance).

remote_mode_active() lifted to hooks._remote_client as the shared chokepoint both the CLI router and the Store guard key on (cli._remote_mode_active re-exports it, so existing test patches are unaffected).

Hermeticity

tests/conftest.py autouse fixture sets MNEMON_ALLOW_LOCAL_STORE=1 so the suite is independent of the dev machine's ~/.mnemon/remote_url (the guard's own TestRemoteModeGuard deletes it per-test). Caught a real topology issue: the integration tests run serve-remote as a subprocess that inherits the machine's remote_url file — fixed by having serve-remote bypass the client-guard (it's the vault).

Tests

+4 store-guard tests (blocked-default / explicit-path-exempt / override-exempt / not-remote-opens). Full suite 1016 passed. rc7 → rc8.

Principle: if a cloud vault exists, the local vault must be inaccessible — a second reachable source of truth is a silent-divergence trap. Leaving open for review/merge.

🤖 Generated with Claude Code

…esidual (rc8)

PR #188 (rc7) fixed `mnemon serve` to proxy to the remote, but every OTHER
default-vault open (rebuild/forget/standing/doctor/sync CLI, dashboard, api)
still opened — and re-created — a local ~/.mnemon/default.sqlite when a remote
vault is configured, silently resurrecting a second source of truth.

- Store.__init__ now refuses to open the DEFAULT local vault in remote mode and
  raises LocalVaultInaccessibleError (fail loud, never empty). Exempt: explicit
  db_path (tests/migrations), serve-remote (it IS the vault — sets the override),
  and MNEMON_ALLOW_LOCAL_STORE=1.
- remote_mode_active() lifted to hooks._remote_client as the shared chokepoint;
  cli._remote_mode_active re-exports it (test patches preserved).
- tests/conftest.py autouse fixture makes the suite hermetic w.r.t. the dev
  machine's ~/.mnemon/remote_url (bypasses the guard; the guard's own tests
  control the env per-test).

Principle: if a cloud vault exists, the local vault must be inaccessible.
+4 store-guard tests; full suite 1016 passed. rc7 → rc8.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cipher813 cipher813 merged commit cc69e02 into main Jun 4, 2026
10 checks passed
@cipher813 cipher813 deleted the fix/local-vault-inaccessible-in-remote-mode branch June 4, 2026 17:51
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