feat(#237): snapshot transfer + master→slave injection (all conflict modes) #241

Merged
jmiller merged 4 commits from feature/237-snapshot-transfer into dev 2026-07-10 21:07:32 +00:00
Owner

Implements #237 — portable snapshot transfer plus direct master→slave injection.

  • Portable download of a snapshot as a .msbsnap (zip: manifest + payload + sha256).
  • Import an uploaded .msbsnap on the Snapshots page (materialises a local snapshot record you can restore).
  • Inject API POST /api/index.php/v1/mokosuitebackup/snapshot/inject — a master pushes a snapshot payload into a slave's Web Services API; slave must opt in via the new Allow Snapshot Injection option.
  • Three conflict modes: overwrite (replace matching by ID), create (skip existing, add new), and duplicate (insert as new copies with remapped IDs via Joomla's Table API — defensive per-item try/catch). Default mode set in Options → Snapshot Transfer, overridable per inject call.

NOT verified end-to-end this session (no dev build) — php -l clean throughout; the download→import→inject round-trip and the duplicate remap need a dev-site test pass before relying on them.

Refs #237

https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i

Implements #237 — portable snapshot transfer plus direct master→slave injection. - **Portable download** of a snapshot as a `.msbsnap` (zip: manifest + payload + sha256). - **Import** an uploaded `.msbsnap` on the Snapshots page (materialises a local snapshot record you can restore). - **Inject API** `POST /api/index.php/v1/mokosuitebackup/snapshot/inject` — a master pushes a snapshot payload into a slave's Web Services API; slave must opt in via the new *Allow Snapshot Injection* option. - **Three conflict modes**: `overwrite` (replace matching by ID), `create` (skip existing, add new), and `duplicate` (insert as new copies with remapped IDs via Joomla's Table API — defensive per-item try/catch). Default mode set in Options → Snapshot Transfer, overridable per inject call. **NOT verified end-to-end this session** (no dev build) — `php -l` clean throughout; the download→import→inject round-trip and the `duplicate` remap need a dev-site test pass before relying on them. Refs #237 https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
jmiller added 4 commits 2026-07-10 21:07:20 +00:00
feat(#237): portable snapshot transfer + master->slave injection API
Universal: Auto Version Bump / Version Bump (push) Successful in 16s
49fcd5e63c
Adds the first increment of snapshot transfer:

- SnapshotPortable engine: package a snapshot into a portable .msbsnap
  (zip of manifest.json + snapshot.json + sha256), and ingest one back
  (from a zip upload or an inline payload) by materialising a local
  snapshot record.
- Admin: per-row 'Download portable snapshot' + an Import modal
  (upload .msbsnap) on the Snapshots page.
- API: POST /snapshot/inject — master pushes a snapshot payload into a
  slave's Web Services API; gated by a new 'Allow Snapshot Injection'
  option. Route added to the webservices plugin.
- Restore engine: new 'create' mode (skip existing, insert only new) and
  mode-name normalisation (overwrite->replace, create, duplicate). The
  'duplicate' (insert-as-new-with-remapped-IDs) mode returns a clear
  'not yet available' — deferred to a dedicated, tested pass.
- Options: 'Snapshot Transfer' fieldset — default conflict mode +
  allow-inject toggle. Language keys added (en-GB fallback).

Reuses the existing mokosuitebackup.snapshot.manage ACL. NOTE: untested
end-to-end (no dev build this session) — verify download/import/inject
on a dev build.

Refs #237

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
feat(#237): implement duplicate snapshot mode (insert as new, remapped IDs)
Universal: Auto Version Bump / Version Bump (push) Successful in 7s
4e07eabc0f
Finishes the deferred 'duplicate' conflict mode. Inserts snapshot content
as brand-new records with remapped IDs, leaving existing content
untouched — for master->slave 'push as new copies'.

- Uses Joomla's Table API (bootComponent MVCFactory) for Article,
  Category and Module so assets, UCM entries, category/tag nested-sets
  and alias uniqueness are handled by core rather than hand-rolled.
- Remaps category parent_id (parents first), article catid, module menu
  assignments, and custom-field-value item_id; re-features articles.
- Tags are reused/created by title (resolveTagIds) and assigned via the
  article table's newTags so UCM/tag-map stay correct.
- uniqueAlias() avoids alias collisions per scope.
- DEFENSIVE: every item is wrapped in try/catch — a bad item is skipped
  and logged, never fatal — so an untested/partial import degrades
  gracefully instead of corrupting content.

NOTE: still needs a real test pass on a dev site before relying on it.

Refs #237

Claude-Session: https://claude.ai/code/session_01WbGBN9VyRK61zczYWcCQ2i
chore(version): auto-bump patch 02.58.23-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been cancelled
RC Revert / Rename rc/ back to dev/ (pull_request) Has been cancelled
50fbe683d9
jmiller merged commit 3587a05630 into dev 2026-07-10 21:07:32 +00:00
jmiller deleted branch feature/237-snapshot-transfer 2026-07-10 21:07:32 +00:00
Sign in to join this conversation.