Implementation Status

Current state of the transport plugin work. All six phases complete. See also: testing, decisions.

Phase 0 — Verify Before Writing Code ✓

• wxFilePickerCtrl confirmed incompatible with URL input (calls wxFileName::FileExists() directly)

• Decision: replace with wxComboBox + Browse button in Phase 3

• pws_os::LoadLibrary confirmed Windows-only — use dlopen directly on Linux

Phase 1 — Transport Interface & Dispatch ✓

src/os/transport.h — PWSTransport struct, ABI version, all public API declarations

src/os/unix/transport.cpp — lazy loader, dlopen/dlsym, plugin cache, FILE* map, scheme validation, cache dir, lockd registry

src/os/unix/file.cpp — FileExists (×2), FOpen, FClose, LockFile, UnlockFile intercepts

src/os/CMakeLists.txt — transport.cpp added, plugins/file subdir, -ldl

Phase 2 — file: Reference Plugin ✓

src/os/plugins/file/transport-file.cpp

src/os/plugins/file/CMakeLists.txt

• Smoke-tested: all assertions pass

Phase 3 — UI: Accept URLs in Open Dialog ✓

src/ui/wxWidgets/DbSelectionPanel.h — wxComboBox replaces wxFilePickerCtrl

src/ui/wxWidgets/DbSelectionPanel.cpp — URL-aware DoValidation(), Browse button, transport error dialog

Phase 3b — File → Open URL… menu item ✓

src/ui/wxWidgets/OpenUrlDlg.h/.cpp — URL entry dialog with editable combo + history dropdown

src/ui/wxWidgets/MenuFileHandlers.cpp — OnOpenUrlClick, URL history helpers (wxConfig /URLHistory/)

src/ui/wxWidgets/PasswordSafeFrame.h/.cpp — ID_OPEN_URL, EVT_MENU binding, menu item after "Open..."

Phase 4 — WebDAV Plugin ✓

src/os/plugins/webdav/transport-webdav.cpp — libcurl GET/PUT/HEAD/OPTIONS/LOCK/UNLOCK

src/os/plugins/webdav/CMakeLists.txt — builds pwsafe-https.so, symlink for pwsafe-http.so

• First live smoke test: opened https://webdav.critchley.biz/test/test2.psafe3 successfully

Phase 5 — Lock Daemon ✓

src/os/unix/transport_lockd.cpp — fork/socketpair child process, binary IPC protocol, EOF-triggered cleanup

• Fixed: IsLockedFile uses in-process registry (pws_has_lock), not WebDAV HEAD

• Fixed: FClose routes store through daemon child when lock held (parent s_lock_tokens empty after fork)

• Fixed: SOCK_CLOEXEC on socketpair (self-review finding)

Test Infrastructure ✓

src/test/transport_standalone_test.cpp — standalone infrastructure tests

src/test/transport_webdav_test.cpp — WebDAV plugin tests (11 sections, 59 assertions)

src/test/transport_lock_lifecycle_test.cpp — lock daemon tests (6 sections, 49 assertions)

src/test/webdav_test_server.py — local wsgidav server for offline live tests

src/test/run_local_webdav_tests.sh — test runner with server lifecycle

Makefile.transport-tests — offline / local-live / live targets

Security Audits ✓

Three rounds: o3, gpt-5.2, self-review. All Critical+High findings fixed. See security_audits.

Dual Installation ✓

scripts/install-local.sh — installs stripped binary + plugins to ~/.local/share/pwsafe-webdav/

~/.local/share/applications/pwsafe-webdav.desktop — desktop launcher entry

• Both original (/usr/bin/pwsafe) and webdav-branch binary available from application launcher

Pending

• Windows/macOS transport support (file.cpp equivalents for those platforms)

• CI wxWidgets cache speedup

• Plugin ABI signature / Ed25519 verification (audit recommendation, future work)

version2
updated2026-02-27