Skip to content
prod 352bb92
Browse

2 · Apply the update

Objective — bring the new vendor files into the repo on a branch you can throw away, then merge and migrate — so your live code is never touched until the update is proven safe.

The schema diff (step 1) told you what will change. This step makes it happen — reversibly. Two safety nets do the work: a backup tag captured before anything changes, and the branch model where the new release lands on its own author/vY.Y.Y branch, frozen and pristine, before it ever merges into your working code.

That branch model is the spine of the whole vendor-update strategy. Each vendor release gets its own frozen author/vX.X.X branch; your changes live downstream on develop. Merging a new author branch into develop is what surfaces conflicts cleanly — and because your customizations sit in update-safe homes (Workflow 3), there should be almost none.

Keep Zaj-PROJECT.md open while applying the update. If the new release changes PHP/Composer/Node requirements, DB engine/collation assumptions, deploy paths, vendor version, or environment readiness, update Zaj-PROJECT.md and .tool-versions in the same branch. If the update changes vendor behavior rather than current facts, log that in Zaj-CUSTOMIZATIONS.md.

flowchart TD
T["Tag backup<br/>before-vY.Y.Y"] --> A["Branch<br/>author/vY.Y.Y"]
A --> U["Drop in new<br/>vendor files"]
U --> C["Commit frozen<br/>vendor baseline"]
C --> M["Merge into<br/>develop"]
M --> X["rm -rf vendor +<br/>composer install"]
X --> S["re-scan seam for<br/>backdoor signatures"]
S --> R["migrate +<br/>optimize:clear"]

1. Tag a rollback point before anything changes

Section titled “1. Tag a rollback point before anything changes”

The cheapest insurance there is. A backup tag is a named save-point — if the update goes wrong, you check it out and you’re back where you started.

  1. Create and push a dated backup tag from your current production state.

    Terminal window
    git checkout production
    git pull origin production
    git tag backup-$(date +%Y-%m-%d)-before-vY.Y.Y
    git push origin backup-$(date +%Y-%m-%d)-before-vY.Y.Y
    # Expected: a new tag named backup-<today>-before-vY.Y.Y exists locally and on the remote
    • ✅ A dated backup tag exists on the remote; git tag | grep backup lists it.

Branch off your current frozen baseline and name the new branch for the new version. This is where the vendor files land — kept clean, with none of your customizations, so it stays a true mirror of what the vendor shipped.

  1. Create the new author branch for the incoming version.

    Terminal window
    git checkout -b author/vY.Y.Y
    # Expected: now on branch author/vY.Y.Y, branched from your frozen baseline
    • git branch --show-current prints author/vY.Y.Y.

This branch must stay vendor-pure — never commit a customization here. Its only job is to record exactly what the vendor shipped, so future diffs (like the one you just ran) stay honest.

Replace the tracked vendor files with the new release. The clean way is to un-track everything, unzip the new files over the project, then re-add — so deletions and renames are captured, not just additions.

  1. Un-track the current vendor files so the next git add records a true replace.

    Terminal window
    git ls-files -z | xargs -0 git update-index --force-remove --
    # Expected: all tracked files are staged for removal (working files stay on disk)
    • git status shows the tracked tree staged as deleted; your files are still present on disk.
  2. Unzip the new vendor release over the project root — 👤 with your file manager, overwriting when prompted. Do not use the command line for this.

    • ✅ The new vendor files are in place; the version in the vendor’s own version file matches the release you downloaded.
  3. Re-add everything and commit the frozen baseline.

    Terminal window
    git add .
    git commit -m "Import vendor vY.Y.Y"
    git push origin author/vY.Y.Y
    # Expected: a single commit capturing the new vendor files as the frozen vY.Y.Y baseline
    • ✅ One commit records the new baseline; the author/vY.Y.Y branch is pushed.

Bring the new baseline down into your working branch, then install dependencies and run migrations. Because your customizations live in update-safe homes, conflicts should be rare — and the few that appear follow one simple rule.

  1. Merge the author branch into develop.

    Terminal window
    git checkout develop
    git merge author/vY.Y.Y
    # Expected: a clean merge, or conflicts confined to vendor files you deliberately edited
    • ✅ The merge completes; any conflicts are in known vendor files, not in your _zaj tables or ZajModules.
  2. Resolve conflicts by the golden rule — your changes win in your homes, vendor wins in theirs.

    ConflictResolution
    New vendor fileAccept the vendor version
    Vendor file you editedKeep your logic; re-apply over the new vendor base
    A _zaj table or ZajModuleShould never conflict — if it does, your customization strategy leaked into vendor space
    • ✅ Every conflict is resolved; no _zaj or ZajModule file was in conflict (or you’ve noted why it was).
  3. Rebuild a clean vendor/, then re-scan the seam before migrating. A vendor release ships a fresh vendor/ tree — and a new release can re-introduce the same nulled-license / phone-home backdoors you stripped at import time (see Extract & snapshot — the seam). Two traps to avoid:

    • composer install does NOT replace an already-installed, locked-version package — it prints “Nothing to install or update” and any tampered file the vendor shipped persists. To get clean upstream you must composer reinstall <pkg> (or rm -rf vendor && composer install).

    • A vendor update is exactly when a backdoor re-enters. Re-run the core-package guard + signature scan against the new vendor tree before you trust it.

      Terminal window
      if [ -d vendor ]; then
      mv vendor "vendor.backup.$(date +%Y%m%d-%H%M%S)"
      fi
      composer install # rebuild the whole tree clean (not an in-place skip)
      npm install && npm run build

    Re-scan the new vendor tree for the backdoor signatures (same as import-time §5):

    Section titled “Re-scan the new vendor tree for the backdoor signatures (same as import-time §5):”

    grep -rEl ‘getCourant|HeaderCodec|envato.|verify.js|getScript|gzinflate|str_rot13’ vendor/ 2>/dev/null
    && echo ” 🔴 backdoor signature present in the new release — STOP, classify + strip (composer reinstall) before deploying”
    || echo ” ✅ no known backdoor signature in the new vendor tree”

    php artisan migrate —pretend # preview one more time php artisan migrate php artisan optimize:clear

    Expected: clean vendor tree, no signature hit, only the classified changes applied, caches cleared

    Section titled “Expected: clean vendor tree, no signature hit, only the classified changes applied, caches cleared”
    - ✅ `vendor/` is rebuilt clean, the signature scan is empty, migrations apply exactly the changes you classified earlier, `Zaj-PROJECT.md` / `.tool-versions` are updated for any new requirements, and the app boots with `php artisan serve`.

Do not mark this step done until every box below is checked.

  • 🤖 Backup tagged — a dated backup-…-before-vY.Y.Y tag exists on the remote (plus a DB dump if a destructive change was flagged).
  • 🤖 Author branch created — on author/vY.Y.Y, branched from the frozen baseline.
  • 🔀 Vendor files imported — 👤 unzipped via file manager; 🤖 committed as one frozen-baseline commit and pushed.
  • 🤖 Merged to develop — merge clean; conflicts confined to known vendor files, none in _zaj/ZajModules.
  • 🤖 Seam re-scannedvendor/ rebuilt with rm -rf vendor && composer install (not an in-place composer install); the backdoor-signature grep -r over the new tree is empty (or any hit was classified + composer reinstall-stripped before proceeding).
  • 🤖 Project state updatedZaj-PROJECT.md / .tool-versions reflect any changed vendor, PHP, Composer, Node, DB, or deploy facts; vendor deviations are in Zaj-CUSTOMIZATIONS.md.
  • 🤖 Migratedmigrate ran; only the classified changes applied; app boots.