38686-vm/docs/plans/2026-04-22-push-to-ai-dev.md
Konrad du Plessis 3c28387dd3 WIP: 2026-04-22 session checkpoint
Complete working state of the session. Will be split into two deploy
phases (safety scaffolding then feature release) before merging to ai-dev.

Includes:
- Security fixes (email creds / SECRET_KEY / DEBUG / CSRF)
- Backup + restore management commands and browser endpoints
- WeasyPrint migration (replaces xhtml2pdf)
- New Worker fields + WorkerCertificate + WorkerWarning models
- Worker / Team / Project friendly management UIs
- Dashboard cert-expiry card + Manage All buttons
- Bootstrap tooltips (global init + theme-aware CSS)
- Django admin template override (taller M2M pickers)
- Money filter for ZAR currency formatting
- Resources dropdown nav
- Massive CLAUDE.md expansion + deploy plan docs

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 00:19:15 +02:00

12 KiB
Raw Permalink Blame History

Push redesign-weasyprintai-dev — Deploy Plan

Created: 22 April 2026 Status: Draft — awaiting your approval before execution Target: Deploy ~6 weeks of local work to Flatlogic production safely


What's going live

3 commits already committed (inherited from the redesign branch)

  • 82c1906 Redesign UI with premium orange theme, sidebar nav, bottom tab bar
  • 16d0342 Fix modal z-index stacking issue
  • deef851 Fix dark mode contrast

40 working-directory changes from this session (must be committed)

Security fixes (critical):

  • Remove hardcoded Gmail App Password + email defaults from settings.py
  • Remove weak SECRET_KEY default (raise in prod, safe fallback in dev)
  • Flip DEBUG default to false
  • Fix CSRF_TRUSTED_ORIGINS double-scheme bug

New database models (3 migrations to run on production):

  • 0009WorkerCertificate + WorkerWarning tables
  • 0010Worker fields: bank_name, bank_account_number, uif_number, drivers_license_code
  • 0011Worker.tax_number field
  • Plus 0007 / 0008 (vat_type defaults) — these were made locally but never committed

PDF engine — xhtml2pdf → WeasyPrint (requirements.txt pins weasyprint==68.1)

New features (all admin-only UI):

  • Worker management UI: /workers/, /workers/<id>/, /workers/<id>/edit/
  • Team management UI: /teams/ + detail + edit + batch report
  • Project management UI: /projects/ + detail + edit + batch report
  • Worker batch report: HTML + CSV + PDF
  • Team/Project batch reports: HTML + CSV
  • Payroll report: Resources dropdown nav, New Report button, money filter
  • Dashboard cert-expiry stat card (conditional)

Infrastructure:

  • Backup + restore management commands
  • /backup-data/ + /restore-data/ browser endpoints
  • Bootstrap tooltips (global init + theme-aware CSS)
  • Django admin template override (taller M2M pickers)
  • TEMPLATES.DIRS change so admin overrides work

Documentation:

  • Massive CLAUDE.md expansion: users/roles/permissions, backup/restore, admin overrides

⚠️ The backup problem

Our /backup-data/ feature is NOT yet on Flatlogic — it's on this local branch, not yet pushed. So we can't use it to back up production right now.

This matters because once we push, migrations will run (or need to be run via /run-migrate/), and the new code goes live. If something breaks badly, we'd have no restore path.

Three backup options, in order of my preference:

Phase 1 — A tiny push that just adds the backup/restore feature + security fixes + the 2 uncommitted "vat_type" migrations (which are tiny and safe).

  • Risk: very low. No new models, no PDF engine change, no UI.
  • Gets /backup-data/ live on production.
  • You download a backup via that URL.
  • Backup is on your laptop — you now have a real safety net.

Phase 2 — The big push with everything else.

  • Risk: significant, but now recoverable.
  • If anything breaks, restore from Phase 1 backup.

Option B: Ask Gemini to take a manual backup first

Ask Gemini in the Flatlogic chat:

Before a planned code push, please run python manage.py dumpdata --natural-foreign --natural-primary --exclude=contenttypes --exclude=auth.permission --output=/tmp/pre_deploy_backup_20260422.json and then make that file downloadable to me somehow (e.g., expose it at a temporary URL like we did with the env-setup page).

Pros: one push instead of two. Cons: relies on Gemini being able to do this cleanly; format may differ from our backup tool; another round of "build temp page, use it, delete it" like last time.

Option C: Push all at once, no backup

Pros: fastest. Cons: if anything goes wrong, you're relying on Flatlogic's internal backups (which exist but aren't something you've tested).


Phase 1 — Safety scaffolding (~10 minutes)

Scope: only these files

  • config/settings.py — security fixes
  • core/management/commands/backup_data.py (new)
  • core/management/commands/restore_data.py (new)
  • core/views.py — just the backup_data + restore_data view functions (not the other 8 new views)
  • core/urls.py — just the 2 new routes
  • core/migrations/0007_vat_type_default.py (new)
  • core/migrations/0008_vat_type_default_none.py (new)
  • CLAUDE.md — just the Backup & Restore section + the updated Authentication/Users section

NOT in Phase 1: new models, WeasyPrint, new UIs, the 3 new Worker migrations, new templates, tooltips, etc.

Sequence:

  1. On local redesign-weasyprint branch, make a sub-branch phase-1-safety:
    git checkout -b phase-1-safety
    
  2. Stage and commit only the Phase 1 files:
    git add config/settings.py core/management/commands/backup_data.py core/management/commands/restore_data.py core/migrations/0007_vat_type_default.py core/migrations/0008_vat_type_default_none.py
    git add -p core/views.py core/urls.py  # interactively pick just the backup/restore additions
    git add CLAUDE.md
    git commit -m "Security fixes + backup/restore feature + vat_type migrations"
    
  3. Switch to ai-dev, merge phase-1-safety:
    git checkout ai-dev
    git pull origin ai-dev           # important — Flatlogic may have auto-committed since
    git merge phase-1-safety
    
  4. Push:
    git push origin ai-dev
    
  5. Flatlogic auto-detects; click Pull Latest in the dashboard; wait ~5 min for rebuild.
  6. Visit /run-migrate/ to apply migrations 0007 + 0008.
  7. Visit /backup-data/ — download the JSON to your laptop. Keep this file safe.
  8. Basic verification: dashboard loads, payroll dashboard loads, an existing receipt can be viewed. Nothing should behave differently from before.

If Phase 1 fails at any step: revert the merge (git revert -m 1 <merge-commit>), push, Flatlogic rebuilds. Low risk because nothing user-facing changed.

Phase 2 — The big feature release (~3060 minutes)

Scope: everything else from this session — WeasyPrint, 3 new Worker migrations, worker/team/project UIs, tooltips, CSS tweaks, admin template override.

Sequence:

  1. Back on redesign-weasyprint (or a new branch off it — doesn't matter since Phase 1 is already in ai-dev):
    git checkout redesign-weasyprint
    git rebase ai-dev   # pulls in Phase 1
    
  2. Commit the rest. I'll propose 57 logical commits rather than one giant one, so rollback can be surgical:
    • feat: migrate PDF engine to WeasyPrintrequirements.txt, utils.py, updated PDF templates
    • feat: Worker certifications and warnings + new model fieldsmodels.py, admin.py, migrations 0009-0011, WorkerForm changes
    • feat: Worker management UI — worker list/detail/edit/batch_report templates + views
    • feat: Team + Project management UI + Resources dropdown nav — team/project templates + views + base.html nav
    • feat: Dashboard tweaks + tooltip infrastructure + admin template override — index.html changes, tooltip CSS, base_site.html, settings.TEMPLATES.DIRS
    • docs: expand CLAUDE.md with users/permissions + backup/restore + admin sections
  3. Merge into ai-dev, push.
  4. Flatlogic rebuilds. Run /run-migrate/ to apply 0009, 0010, 0011.
  5. Verification checklist below.

If Phase 2 fails:

  • Identify which commit broke things (git bisect if needed)
  • git revert <bad-commit> on ai-dev, push, Flatlogic rebuilds
  • Worst case: revert the whole merge, restore from Phase 1 backup

Pre-push cleanup (required regardless of Option A vs B)

Before any commit, these files must be excluded:

Add to .gitignore (if not already):

.claude/
test_*.pdf
*.sqlite3-journal
nul

Delete from working directory (they're test artifacts):

rm -f nul test_report.pdf test_workers_report.pdf test_report_weasyprint.pdf test_payslip_weasyprint.pdf test_receipt_weasyprint.pdf "test_report modified manually.pdf"

Never commit:

  • .env file (lives on server only, not in git)
  • Any password / SECRET_KEY (all those live in .env now)
  • test_backup.json (if any dev backup exists locally)

Verification checklist (post-Phase-2)

Run these in order. Each should pass before moving to the next.

System checks

  • / loads — dashboard renders with all stat cards
  • /admin/ loads and you can log in
  • /payroll/ loads — pending payments table visible
  • /report/ — generate a payroll report with this month's dates, HTML renders

PDF engine (WeasyPrint) — critical

  • Download the payroll report PDF via /report/pdf/ — opens in a viewer, has content
  • Create a small test expense receipt, trigger the email, verify the PDF arrives in Spark Receipt (not just the email — the attached PDF)
  • Process a test payment for one worker, verify payslip PDF generates and emails correctly

New features

  • /workers/ list renders with ~14 workers
  • Click into a worker, see the new tabs (Profile / Certifications / Warnings / History)
  • /teams/ and /projects/ list pages load
  • Resources dropdown in topbar works on desktop
  • Bootstrap tooltips work (hover over the ⓘ icons on worker edit page)

Data integrity

  • Worker salary, daily_rate, employment_date all display correctly (no fields lost in migration)
  • An existing work log from months ago still shows workers correctly
  • A historical payslip (/payroll/payslip/<pk>/) still renders

Admin

  • /admin/core/worker/<id>/change/ shows the new inlines (certs + warnings)
  • /admin/auth/group/<id>/change/ shows taller M2M pickers (30em tall)

Security (quick)

  • Try loading /secret-env-setup/ — should be 404 (Gemini cleaned it up)
  • Settings log check (Flatlogic logs): no warning about missing email vars

Rollback procedures

Rollback Phase 1 (low risk)

# On ai-dev branch locally
git revert -m 1 <phase-1-merge-commit-hash>
git push origin ai-dev
# Flatlogic rebuilds, removes the changes

Rollback Phase 2 (after deploying)

Option 1 — Revert the code:

git revert -m 1 <phase-2-merge-commit-hash>
git push origin ai-dev

This reverts the code. BUT — if migrations 0009/0010/0011 have been applied, the new columns/tables exist in MySQL. That's safe (they're just unused), but you'd also want to roll back those migrations:

# Visit /run-migrate/ won't help here; we'd need:
python manage.py migrate core 0008

Which requires SSH or Gemini intervention.

Option 2 — Restore from Phase 1 backup (nuclear option):

  1. Visit /restore-data/ on production
  2. Upload the backup JSON from Phase 1
  3. Tick "Yes, I understand", click Restore
  4. All data returns to Phase 1 snapshot

Option 2 is the last resort. It only works if Phase 2 somehow corrupted data, not just broke the UI.


What I need from you before we start

  1. Confirm Option A (split into two phases) vs Option B (Gemini manual backup + single push) vs Option C (yolo single push, no backup).
  2. Have you revoked the old Gmail App Password yet? (previous plan step — want to confirm before we push, so the leaked password is fully dead before code deploys)
  3. Timing — when do you want to do this? It's ~10 minutes for Phase 1 + ~5 min Flatlogic rebuild + backup download, then Phase 2 is ~30 min of sequential commits + push + verification. Total ~1 hour if nothing goes wrong. Ideally a time when no one else is actively using the app.
  4. Commit authoring — do you want me to write the commit messages and make the commits for you (I can stage and commit from bash), or do you want to drive git yourself and I guide?

Once I have these three answers I'll proceed with execution.


Junk we should NOT deploy

For the record, these files exist locally but must NOT make it into the commits:

  • nul — accidental Windows shell artifact
  • test_report.pdf, test_workers_report.pdf, test_report_weasyprint.pdf, test_payslip_weasyprint.pdf, test_receipt_weasyprint.pdf, test_report modified manually.pdf — dev/test output
  • .claude/settings.local.json — IDE config
  • run_dev.bat — could go either way (Windows-specific dev convenience); I'd keep it out
  • test_backup.json (if still present from backup-command testing)