When reopening with existing identity, do not pass discovery key to
Autopass. That makes Autobase bootstrap from this device's local core
(name: 'local') instead of bootstrap.getUserData('autobase/local'),
which can point at another device's writer and open it read-only.
- Device that creates sync group is the Master; MASTER label in Linked devices table
- Create invite when already linked generates invite for same sync group (no wipe)
- Any peer can create invites so devices can be added when Master is offline
- Identity file stores isMaster; same sync group reused across native host restarts
- Update SYNC.md, NATIVE-HOST.md, ARCHITECTURE.md, CHANGELOG.md
- Add getStateSnapshot, applySnapshotData, setStateSaveSuppressed to holesail-manager
- Sync diffs snapshot vs current state and only removes/adds/updates changed tunnels
- Suppress saves during apply and write state.json once at the end
- Fall back to full cleanup + restore when incremental APIs are unavailable
- Backup: do not include autopass/ (may be in use); always include
autopass-identity.json so sync identity is never lost
- Restore: remove autopass/ after extract so autopass can recreate from
restored identity
- Docs: BACKUP.md, SYNC.md, ARCHITECTURE.md updated
- pairWithInvite: await store.ready() before pair; await pass.ready()
after pair.finished(); on error call pair.close() then closePass()
- createSyncInvite: on error await closePass() instead of nulling refs
- Remove autopass dir before createSyncInvite/pairWithInvite so Corestore
gets a fresh device-file (device-file throws when inode/mtime changes)
- Await sync/rdp/holesail cleanup on host shutdown so corestore closes
before process exit
- Reset initPromise on init failure so Create invite can retry after
removing corrupt autopass dir
- getSyncStatus: fire-and-forget push device hostname when missing so
linked peers see names after opening Sync page
- Backup/restore: close sync (corestore) before copy/extract so autopass
data is consistent; backup includes autopass/ and autopass-identity.json
- Installer: preserve sync data on re-run (comments and messages)
- Docs: BACKUP.md sync-in-backup and pause behaviour; SYNC.md backups
include sync data
- Sync: use OS hostname for each device in Linked devices table; persist
deviceNames in state and merge on save/apply so peers see each other's names
- Docs: expand SYNC.md (linked devices table, replace-state modal, multi-device,
offline); NATIVE-HOST getSyncStatus (deviceId, syncGroupId, linkedDevices,
deviceName/name); ARCHITECTURE sync-manager and autopass paths; README
features/dashboard/file locations/doc link; BACKUP and SECURITY cross-refs
- getSyncStatus() now iterates pass.base.activeWriters and returns
linkedDevices: [{ id, isCurrent }] for each writer in the sync group
- Dashboard Linked devices table shows every device: "This device" plus
"Device 2", "Device 3", etc. with their IDs; rows sorted by id
- Fallback to single "This device" row when activeWriters is missing
- Await restorePersistedTunnels so applyingSync stays true for full restore,
preventing saveState() during tunnel startup from pushing back and looping
- Debounce onRemoteUpdate (600ms) and skip apply when state unchanged
(canonical fingerprint) to avoid redundant restarts
- Add confirm modal before "Link device": warns that current state will be
replaced and suggests creating a backup first
- Add Linked devices table when linked: show This device ID (writerKey) and
Sync group ID (discoveryKey); getSyncStatus returns deviceId and syncGroupId
- Await restorePersistedTunnels in applySyncedState so applyingSync stays
true for the full restore. Prevents saveState() during tunnel startup
from pushing back to autopass and causing a feedback loop.
- Debounce onRemoteUpdate (600ms) so bursts of autopass 'update' events
trigger a single apply.
- Skip apply when remote state matches current state (canonical fingerprint)
to avoid redundant restarts and re-pushes.
- Clear remoteUpdateDebounceTimer in cleanup().
- Replace sudo with pkexec so PolicyKit shows a graphical auth dialog
when the native host is launched by the browser (no terminal).
- Pass DISPLAY and XAUTHORITY into the pkexec env so the polkit
agent can display the dialog in the current session.
- Keep copy + update-ca-certificates in a single pkexec sh -c for
one password prompt.
- Update SECURITY.md and JSDoc to describe pkexec / PolicyKit.
- Move connect-proxy and https-proxy into proxy/
- Move certificate-authority, backup-manager, ssh-manager, rdp-manager into managers/
- Move messenger.js into host/
- Move test-dirname.cjs into test/
- Update imports, CI lint paths, and ARCHITECTURE.md