jetstream: hold cursor on transient apply failures
Previously, `handleJetstreamEvent` saved the time-based cursor after
every event regardless of whether `applyCommit` succeeded. That is fine
for permanently bad records (malformed JSON, schema violations) where
replaying achieves nothing, but wrong for transient infra failures
(SQLite busy, store closed during shutdown, disk full): the cursor
would advance past a perfectly good event and silently drop the
membership or repo row that backs it, with no way to recover short of
a manual replay.
`applyCommit` now distinguishes the two classes via a new
`badRecordError` wrapper. JSON decode failures in `applySpindleMember`,
`applyRepo`, and `applyRepoCollaborator` are wrapped with
`badRecord(...)` so they remain cursor-advancing. Everything else
returned from `applyCommit` is treated as transient:
`handleJetstreamEvent` logs it, returns the error to the scheduler, and
skips `SaveCursor` so the next reconnect (which already rewinds by
`jetstreamRewind`) will redeliver and retry.