bisync: default to fail-closed safety flags

New Bisync jobs and scheduled RC bodies start with checkAccess,
deltaList, recover, resilient, slowHashSyncOnly, conflictResolve=none,
maxDelete=50, and checksum compare. Explicit outer values still win.
This commit is contained in:
2026-09-10 00:00:15 +02:00
parent 7286008949
commit 5c8e5560d4
3 changed files with 28 additions and 4 deletions
+19
View File
@@ -1,3 +1,22 @@
// Fail-closed bisync RC defaults (forked rclone). Explicit outer values override.
export const BISYNC_SAFETY_DEFAULTS = {
checkAccess: true,
deltaList: true,
recover: true,
resilient: true,
slowHashSyncOnly: true,
conflictResolve: 'none',
maxDelete: 50,
compare: 'size,modtime,checksum',
} as const
export const BISYNC_SAFETY_SWITCH_DEFAULTS: Record<string, boolean> = {
checkAccess: true,
deltaList: true,
recover: true,
resilient: true,
}
export const RCLONE_CONFIG_DEFAULTS = { export const RCLONE_CONFIG_DEFAULTS = {
copy: { copy: {
'multi_thread_cutoff': '64M', 'multi_thread_cutoff': '64M',
+5 -1
View File
@@ -1,4 +1,5 @@
import type { FlagValue } from '../../types/rclone' import type { FlagValue } from '../../types/rclone'
import { BISYNC_SAFETY_DEFAULTS } from './constants'
import { getFsInfo } from '../format' import { getFsInfo } from '../format'
// Pure serialization of operation args into ready-to-POST rclone RC requests. This is the // Pure serialization of operation args into ready-to-POST rclone RC requests. This is the
@@ -492,7 +493,10 @@ export function buildBisyncRequests(args: BisyncArgs): RcRequest[] {
const { fullDirPath: srcFullDirPath, remoteName: srcRemoteName } = getFsInfo(source) const { fullDirPath: srcFullDirPath, remoteName: srcRemoteName } = getFsInfo(source)
const { fullDirPath: dstFullDirPath, remoteName: dstRemoteName } = getFsInfo(destination) const { fullDirPath: dstFullDirPath, remoteName: dstRemoteName } = getFsInfo(destination)
const outer = { ...(options.outer || {}) } const outer: Record<string, FlagValue> = {
...BISYNC_SAFETY_DEFAULTS,
...(options.outer || {}),
}
// Forked rclone: --delta-list refuses to run without --check-access unless --force. // Forked rclone: --delta-list refuses to run without --check-access unless --force.
if (outer.deltaList && !outer.force) { if (outer.deltaList && !outer.force) {
outer.checkAccess = true outer.checkAccess = true
+4 -3
View File
@@ -7,7 +7,7 @@ import { onErrorDialog } from '../../lib/errors'
import { getOptionsSubtitle } from '../../lib/flags' import { getOptionsSubtitle } from '../../lib/flags'
import { useFlags } from '../../lib/hooks' import { useFlags } from '../../lib/hooks'
import { startBisync } from '../../lib/rclone/api' import { startBisync } from '../../lib/rclone/api'
import { RCLONE_CONFIG_DEFAULTS } from '../../lib/rclone/constants' import { BISYNC_SAFETY_SWITCH_DEFAULTS, RCLONE_CONFIG_DEFAULTS } from '../../lib/rclone/constants'
import { useSchedulingAvailable } from '../../lib/scheduler' import { useSchedulingAvailable } from '../../lib/scheduler'
import OperationWindowContent from '../components/OperationWindowContent' import OperationWindowContent from '../components/OperationWindowContent'
import OperationWindowFooter from '../components/OperationWindowFooter' import OperationWindowFooter from '../components/OperationWindowFooter'
@@ -38,7 +38,7 @@ Here's a quick guide to using the Bisync command:
Use the path selectors at the top to choose Path1 and Path2. Both paths will be kept in sync with each other — there is no "source" or "destination", changes flow both ways. Use the path selectors at the top to choose Path1 and Path2. Both paths will be kept in sync with each other — there is no "source" or "destination", changes flow both ways.
2. CONFIGURE OPTIONS (Optional) 2. CONFIGURE OPTIONS (Optional)
Expand the accordion sections to customize your bisync operation. The Bisync section has important switches at the top: Expand the accordion sections to customize your bisync operation. Safety defaults are on: checkAccess, deltaList, recover, resilient, conflictResolve=none, maxDelete=50, compare=size,modtime,checksum, slowHashSyncOnly. Turn them off only if you understand the loss path.
• resync — Required for the first run, or to reset bisync after an error. This makes both paths contain a matching superset of all files by copying Path2 to Path1, then Path1 to Path2. Only use resync when starting fresh, after changing filter settings, or recovering from an error — using it routinely would prevent deletions from syncing (deleted files would keep reappearing from the other side). • resync — Required for the first run, or to reset bisync after an error. This makes both paths contain a matching superset of all files by copying Path2 to Path1, then Path1 to Path2. Only use resync when starting fresh, after changing filter settings, or recovering from an error — using it routinely would prevent deletions from syncing (deleted files would keep reappearing from the other side).
@@ -104,7 +104,8 @@ export default function Bisync() {
const filterGroup = optionGroups.filter const filterGroup = optionGroups.filter
const configGroup = optionGroups.config const configGroup = optionGroups.config
const [outerBisyncOptions, setOuterBisyncOptions] = useState<Record<string, boolean>>({}) const [outerBisyncOptions, setOuterBisyncOptions] =
useState<Record<string, boolean>>(BISYNC_SAFETY_SWITCH_DEFAULTS)
const [cronExpression, setCronExpression] = useState<string | null>(null) const [cronExpression, setCronExpression] = useState<string | null>(null)
const schedulingAvailable = useSchedulingAvailable() const schedulingAvailable = useSchedulingAvailable()