Commit graph

5 commits

Author SHA1 Message Date
Souta
b78471c616 fix(rpc): address PR #355 review — path-space mismatch + undefined guard
Multi-agent review caught a real regression in the daemon-reuse fix:

- C1 (CRITICAL): remotePath "~" → effectivePath "." →
  resolveRemotePath("." , home) = "/home/u/." but the daemon reports
  filepath.Abs(".") = "/home/u" via server.info → sameRemotePath
  (trailing-slash-only) = false → kill+redeploy on EVERY connect.
  Same for any "..", "//" in remotePath. The client (string-join) and
  daemon (filepath.Abs) lived in different path spaces.
- I1: reused.info.vaultRoot is typed string but an older/3rd-party
  daemon can omit it on the wire → undefined → sameRemotePath's
  .trim() threw TypeError → uncaught silent connect failure.
- I2: deploy() got the raw relative effectivePath as --vault-root →
  implicit daemon-cwd dependency.

Consolidated fix:
- ConnectionManager: compute the absolute vault root ONCE
  (resolveRemotePath(effectivePath, home)) and use it BOTH for the
  reuse compare AND as deploy()'s remoteVaultRoot — same path space
  on both sides, no cwd dependency (fixes C1 + I2 together).
- sameRemotePath: POSIX-normalise both sides (path.posix.normalize →
  collapses ./../ //, then strip trailing slash); null-safe
  (string|undefined); empty/blank never matches a real root, not
  even empty-vs-empty (always forces the safe redeploy). Fixes C1
  remainder + I1.
- haveRoot guarded `?? ''` at the call site; reused.close() catch
  now logger.warn (mirrors every other close in the file) instead of
  a silent swallow.
- JSDoc reworded: a spurious redeploy is SAFE but not cheap (full
  pkill + upload + restart) — normalisation exists to avoid firing
  it on legitimately-equal paths.

Tests: pathUtils.test.ts +6 (the "." / ~ loop case, ".."/"//"
collapse, empty-vs-empty=false, undefined-safe no-throw). The
startRpcSession reuse/mismatch glue is intentionally covered by the
now-exhaustive sameRemotePath unit suite + the connect e2e
(#351/#353) rather than a bespoke ssh/deployer mock harness —
disproportionate for thin control flow whose decision core is pure
and fully tested.

tsc clean, eslint clean, vitest 70 files / 1061 passed / 1 skipped.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 00:28:26 +09:00
Souta
cacc936833 fix(rpc): auto-redeploy daemon when reused vault-root is stale
Field repro: changing a profile's remotePath (or deleting the old
remote vault) had NO effect — `tryReuseExistingDaemon` reused the
already-running daemon purely on socket+token presence, never
checking that its `ServerInfo.vaultRoot` still matches the profile's
requested root. The daemon kept serving its original (now wrong /
deleted) vault-root, so `fs.walk("")` returned `no such file:`, the
shadow vault populated 0 files, and every op (incl. renaming a new
note) failed `no such file`. The only workaround was to SSH in and
`pkill` the daemon by hand — exactly what should be automatic.

Fix: in `ConnectionManager.startRpcSession`, after a reuse candidate
is found, resolve the profile's `effectivePath` to absolute
(`resolveRemotePath(effectivePath, home)`) and compare it with the
reused daemon's `reused.info.vaultRoot` via the new
`sameRemotePath` (trailing-slash/whitespace tolerant, otherwise
strict — a spurious redeploy is cheap, a false match reattaches to
the wrong root). On mismatch: close the connection and fall through
to `deployer.deploy()`, whose `killExisting:true` pkills the stale
daemon and redeploys at the correct root. No manual pkill ever
needed; a remotePath change now always takes effect.

`sameRemotePath` added to util/pathUtils with 6 unit cases incl. the
exact field bug (`/home/souta/work/VaultDev` vs `/home/souta/work`
→ false → redeploy). tsc/eslint clean, vitest 70 files / 1057
passed.

Chained on fix/bootstrap-first-run-appjson so one local build has
both fixes (empty-app.json deadlock + stale-daemon root) for
end-to-end verification.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 00:28:26 +09:00
Copilot
9fb3e4e605
Improve coverage for retry/error observability utilities (#257) 2026-05-08 10:41:04 +09:00
Souta
de3d0d6c32 chore(security): replace personal info with generic placeholders (0.3.2)
Security check turned up three places where the maintainer's
personal info had ended up in tracked source:

- plugin/tests/AdapterPatcher.test.ts:15
  `target.greet('souta')` → `target.greet('alice')`
- plugin/tests/pathUtils.test.ts:15
  `/home/souta/work/VaultDev/` → `/home/alice/vault/`
- plugin/scripts/dev-install.mjs
  Default fallback for the dev vault path was hard-coded to
  `../../SelfArchive-dev` (the maintainer's own dev vault folder
  name). Renamed to the generic `../../dev-vault`. The
  `REMOTE_SSH_DEV_VAULT` env var still wins, and the script accepts
  a positional argv override too — the maintainer's actual
  `SelfArchive-dev` keeps working with
  `REMOTE_SSH_DEV_VAULT=/path/to/SelfArchive-dev npm run build:full`.

What stays:
- `github.com/sotashimozono/...` in every Go file's import path —
  Go module canonical URL; this matches the repo URL on GitHub
  and isn't replaceable.
- `work/VaultDev` mentions in README / docs / a couple of test
  fixtures — generic enough not to identify the maintainer
  (anyone could name a folder that), kept as-is.

No private keys / tokens / IPs / emails / hostnames were in the
tree to begin with — those live only in the user's local
`data.json` and ssh agent, not in the repo.

Bumps to 0.3.2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 11:30:25 +09:00
Souta
21bb70a5d0 chore: monorepo restructure (plugin/ + server/ + proto/)
Move the entire Obsidian plugin tree under plugin/ and add an empty
server/ tree (Go) and proto/ directory so the upcoming
obsidian-remote-server daemon has a home in the same repo. The plugin
remains the only thing that builds today; the server is a hello-world
skeleton that prints "not implemented yet" and exits non-zero, with a
Makefile that knows how to cross-compile for linux/darwin × amd64/arm64
once real code lands.

Background:
  Approach A (vault-adapter monkey-patch) hit structural ceilings —
  vault index frozen at startup, third-party plugins bypass DataAdapter,
  empty-remote .obsidian read failures cascade through Templater/Kanban
  etc. We are pivoting to the VS Code Remote-SSH model: a small Go
  daemon on the remote host, JSON-RPC over a SSH-tunnelled WebSocket,
  fsnotify-driven push events, attachment serving over HTTP on the same
  socket. This restructure is the first mechanical step before the
  protocol and transport land.

Mechanical changes:
- git mv all plugin sources, manifest, configs, scripts, and tests
  into plugin/.
- plugin/scripts/dev-install.mjs walks one extra parent (`pluginRoot`
  → `repoRoot` → `..` for the dev vault) so REMOTE_SSH_DEV_VAULT
  defaulting still resolves to ../SelfArchive-dev relative to the
  repo, not to plugin/.
- CI: ci.yml runs lint/test/build with `working-directory: plugin`
  and a server job that builds + tests the Go module. release.yml
  builds out of plugin/ and uploads plugin/{main.js,manifest.json,
  styles.css}.
- Dependabot: npm directory becomes /plugin; new gomod directory /server.
- Labeler: paths re-anchored to plugin/, with new plugin/server/proto
  area labels.

Verification:
  cd plugin && npm install && npx tsc --noEmit && npm test (76/76)
  cd plugin && npm run build:install (367 KB; dev vault refreshed).
  Go side waits on CI (no Go toolchain on the dev host).
2026-04-25 10:52:52 +09:00
Renamed from tests/pathUtils.test.ts (Browse further)