Remove encryption; user-data filters; SQLite safety; recovery, retention, scheduler

- No client-side encryption: plaintext content-addressed remote (SHA-256
  names), no backup key, no cryptography dependency (server disk encryption
  is the trust model).
- Filters back user data: images, archives, databases, PDFs accepted; 10 MiB
  cap; binary sniffing removed; temp names hardened (~$, #..#, .temp).
- SQLite zero-error policy: backup-API snapshots + integrity_check, journal
  folding, locked/corrupt loud skips, verified restores.
- Recovery: reindex from manifests, remote adopt, on-demand blob fetch,
  5-day retention + thinning, GC, date-guarded remote purge, metrics.
- Scheduler with WebDAV quota signal and 70% pressure backstop (floor kept).
- 37 tests incl. live-monitor capture safety and DB safety.
This commit is contained in:
retoor
2026-10-10 03:41:36 +02:00
parent 7e05e3d26c
commit 3499f6cda0
35 changed files with 3148 additions and 203 deletions
+13 -4
View File
@@ -10,9 +10,15 @@ from versiond.store import BlobStore
def test_filters_paths():
f = Filters()
ok = ["app.py", "src/main.go", ".env", ".env.production", "Makefile", "pkg/package.json", ".gitignore"]
ok = ["app.py", "src/main.go", ".env", ".env.production", "Makefile", "pkg/package.json", ".gitignore",
# user data: images, archives, databases, documents (backed up as raw files)
"photos/vacation.jpg", "img/logo.png", "backup/site.tar.gz", "data/archive.zip",
"app.db", "app.sqlite3", "report.pdf", "song.mp3", "clip.mp4"]
for p in ok:
assert f.path_reason(PurePath(p)) is None, p
journals = ["app.db-wal", "app.db-shm", "app.sqlite-journal", "data/x-wal"]
for p in journals:
assert f.path_reason(PurePath(p)) == "database-journal", p
rejected = {
"node_modules/x/index.js": "ignored-directory",
".git/config": "ignored-directory",
@@ -21,6 +27,10 @@ def test_filters_paths():
".bashrc_local": "hidden-file",
"notes.txt~": "temporary-file",
"main.py.swp": "ignored-extension",
"draft.temp": "ignored-extension",
"x.kate-swp": "ignored-extension",
"~$lock.docx": "temporary-file",
"#autosave#": "temporary-file",
"venv/lib/x.py": "ignored-directory",
"target/debug/build.rs": "ignored-directory",
"4913": "temporary-file",
@@ -28,9 +38,8 @@ def test_filters_paths():
}
for p, reason in rejected.items():
assert f.path_reason(PurePath(p)) == reason, p
assert f.size_reason(204_800) is None
assert f.size_reason(204_801) == "file-too-large"
assert f.content_reason(b"abc\x00def") == "binary-content"
assert f.size_reason(10_485_760) is None
assert f.size_reason(10_485_761) == "file-too-large"
def test_filter_patterns():