Case files / PAN-115

PAN-115In flight

Casual contracts, checked nightly

A casual-workforce tool for a food business, replacing the spreadsheet HR used to track short contracts. It imports the old workbook, checks every chain of contracts against the minimum wage and the fixed-term limit, and sends each person only the alerts they may see. It flags. It does not give legal advice.

Control flow

  1. Import: the old workbook, row by row
  2. Review: HR maps, merges, previews
  3. Check: a nightly rules sweep
  4. Alert: one scoped digest per person
  5. Requisition: approval reruns the rules
  6. Offboard: end of service and notices
  7. Payroll: export rebuilt per download

Industry: Food · Stack: Python 3.13 · Django 5.2 · PostgreSQL 17 · HTMX · Docker Compose · Seed species: Sheaf

Problem

A business that runs on seasonal and casual labour signs a great many short contracts a year. Each chain of them has to stay inside the minimum wage, the fixed-term limit and the renewal rules. HR was tracking all of it in one spreadsheet, and a spreadsheet does not warn anyone.

How it works

The old workbook is imported row by row into a staging area. HR maps the values, merges duplicates and previews the result before anything is committed.

Every night a rules sweep checks every chain of contracts and raises flags. Each person gets one digest email with only the alerts they are allowed to see.

Every legal value, from the minimum wage to notice periods and retention years, is dated data, marked unverified until a lawyer signs it off and an HR admin ticks it. The tool flags. It does not give legal advice.

Before HR can approve a new contract line, the real contract is written inside a savepoint, the rules run as of today and as of the planned end date, and it rolls back if anything blocks. Only an HR admin can override a block, with a recorded reason. The check button runs the same code and always rolls back.

Payroll exports are never stored, because they hold ID numbers. Each download rebuilds the file and escapes formula injection. After five years people are anonymised in the live and history tables, but only once an HR admin types the confirmation. A test checks that no identity survives anywhere.

Method

All test data is a synthetic copy of the real workbook’s layout. Spreadsheets are blocked from git at three layers. Built with AI: six milestone commits, all co-authored by Claude.

What broke

Docker would not start on the build machine, so 239 tests passed against a hand-started database and the container stack has never run. A machine freeze left a template the right size and full of null bytes, and nothing noticed until it failed to render.

Two traps worth keeping: three months means calendar months, not ninety days. And the container clock is UTC, so for two hours every night it is already tomorrow locally.

Limitations

Not yet run on the client’s hardware. Unverified, and listed as such: the container stack, the scheduled worker, real email, the virus scanner, the payroll column headings, and an external pen test.

Next

First deployment on the client’s own server, a restore drill, and a labour lawyer’s review of every legal value.

Open the living case file