/**
* #74 Phase 1 — fire the SSH authorized_keys resync on IdentityRegistry
* replication updates, not only on local enroll/remove/boot.
*
* The add/remove handlers (lib/handlers/ssh-keys.js) resync only the daemon
* that took the write. So a key enrolled on backend A landed in the
* *replicated* IdentityRegistry view but A's peers stayed blind to it in their
* authorized_keys until their next boot — the #73 "enroll-on-stortron,
* push-to-tabertron is denied" propagation gap.
*
* Autobase 'update' fires on BOTH local append AND remote replication, so
* watching it materializes a peer-enrolled key into every backend within one
* replication round, no reboot. Debounced (default 1500ms, matching
* scheduleMirrorReannounce in pear-git.js) to coalesce an update burst into a
* single rebuild.
*
* Returns detach() — removes the listener and cancels any pending timer.
* A no-op (returns an empty detach) when base/resync are unusable, so the
* caller can wire it unconditionally.
*/
export function attachSshResyncTrigger ({ base, resync, debounceMs = 1500, onSynced, onError }) {
if (!base || typeof base.on !== 'function') return () => {}
if (typeof resync !== 'function') return () => {}
let timer = null
function schedule () {
if (timer) return
timer = setTimeout(() => {
timer = null
Promise.resolve()
.then(resync)
.then((r) => { if (typeof onSynced === 'function') onSynced(r) })
.catch((err) => { if (typeof onError === 'function') onError(err) })
}, debounceMs)
}
base.on('update', schedule)
return function detach () {
try { base.off('update', schedule) } catch {}
if (timer) { clearTimeout(timer); timer = null }
}
}