Commit Graph
4 Commits
Author SHA1 Message Date
flan 4b07ce459a Fix six audit findings: dead code, missing status records, missing fallback, unsafe JSON read
create_task.py:
- Remove dead make_client() call before the verify branch; it was called
  unconditionally with host=None/key=None, creating a broken client that was
  immediately discarded or overwritten.
- Remove "verify" from the dispatch dict; it was never reached through dispatch
  (the if/cmd==verify branch above it handled it). Dispatch now only contains
  commands that actually use a client.
- Wrap json.load() in try/except (OSError, JSONDecodeError) so a corrupt or
  partially-written status file produces a useful message instead of a traceback.

sitecustomize.py:
- Call _record_status() on the early-return paths in both _patch_b2 and
  _patch_restic. Without this, if TrueNAS natively supports B2 or the patch
  is already applied, the status file was never written and `verify` always
  reported failure even when everything was fine.
- Add idempotency guard to _record_status(): first call wins; duplicate calls
  for the same module are ignored so the entry count stays accurate.
- Make B2 get_restic_config a @staticmethod. The method never used self; the
  noqa comment was suppressing the evidence of a design mismatch. Removing the
  unused parameter makes the intent explicit.
- Add NamedTuple._replace() fallback after dataclasses.replace() in the restic
  wrapper. If ResticConfig is ever refactored to a NamedTuple, the TypeError
  from dataclasses.replace() would have surfaced as a backup job failure rather
  than a graceful recovery.
2026-06-15 02:59:57 +00:00
flan 06de1e15c0 Wrap original get_restic_config instead of replacing it; add hook status file
sitecustomize.py: _patch_restic no longer reimplements get_restic_config.
It now wraps the original: calls _orig(cloud_backup) to get a ResticConfig,
then post-processes only the -r argument to fix "b2:/bucket" → "b2:bucket"
when the URL contains a stray leading slash (the stock bug for empty-hostname
providers). Uses dataclasses.replace() to build the corrected result so new
ResticConfig fields added in future TrueNAS versions pass through unchanged.
This eliminates the transfer_setting gap, env dict mutation, and frozen-copy
drift that would occur over time.

Also adds a status file mechanism: sitecustomize.py writes
/data/truecloud-patch/hook_status.json atomically after both patches have
reported success or failure. This gives a machine-readable signal that the
hook fired correctly — without requiring log scraping.

create_task.py: new "verify" subcommand reads the status file and prints a
human-readable summary. Does not require --host or --api-key. --host and
--api-key are now optional at the parser level and validated only for
subcommands that actually need an API connection.

README: update troubleshooting to use "create_task.py verify" instead of
the manual Python introspection one-liner.
2026-06-15 02:47:59 +00:00
flan 0a54bcba9d Harden for Python 3.12+, add disclaimer, audit for robustness
- sitecustomize.py: replace deprecated find_module/load_module with
  find_spec/exec_module (required for Python 3.12+ / TrueNAS SCALE 25.x)
- apply.sh: remove set -e (PREINIT must not fail catastrophically);
  detect middlewared's actual Python binary instead of assuming python3;
  log rotation to avoid unbounded growth; independent failure per step
- patch_ui.py: detect multiple bundle matches; include TrueNAS version
  in pattern-not-found warning; better MARKER specificity
- uninstall.sh: mirror Python detection logic from apply.sh
- README: lead with Storj $5→$50 price context; prominent unsupported
  disclaimer; Python version compatibility matrix; post-update checklist
- Add MIT LICENSE
2026-06-15 02:13:24 +00:00
flan 21b9333324 Initial implementation: extend TrueCloud Backup to S3 and B2 providers
Patches middlewared at runtime via sitecustomize.py (no file edits to /usr/)
and widens the UI credential dropdown from Storj-only to S3+B2+Storj.
Persists across TrueNAS updates via PREINIT initshutdownscript stored in DB.
2026-06-15 02:02:17 +00:00