# Push `redesign-weasyprint` → `ai-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):
- `0009` — `WorkerCertificate` + `WorkerWarning` tables
- `0010` — `Worker` fields: `bank_name`, `bank_account_number`, `uif_number`, `drivers_license_code`
- `0011` — `Worker.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**:

### Option A (RECOMMENDED): Split the push into two phases

**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).

---

## Recommended: Option A — two-phase push

### 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 (~30–60 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 5–7 logical commits rather than one giant one, so rollback can be surgical:
   - `feat: migrate PDF engine to WeasyPrint` — `requirements.txt`, `utils.py`, updated PDF templates
   - `feat: Worker certifications and warnings + new model fields` — `models.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)
