Command: cat projects/event-control.md
Reviewing and modernizing a live event-control system
A PHP web system runs in-person events: attendees, check-in with a printed badge, support staff, booth sales with receipts and stock per event. It already existed and was live. I led a complete review: audits per module, a snapshot of every screen before touching anything, security and concurrency fixes and a new design system, with everything compared against the snapshot at the end.
open the demoa simulation of the system with fictional data · 4 screens
- Role
- Lead of the review and the modernization
- Period
- Sep 2026 – Sep 2026
- What I did
Me: The review method, the per-module audits, the screen snapshot and the final comparison, the integrity and security fixes, the design system and the release with backup and rollback.
Other people: The system already existed and ran in production before the review.
Private project, described without identifying the client, product or company.
Diagram
The PHP system in production serves admins and attendants, and the work ran on an anonymized copy of it. Before any change, the rules that could not change were written down and every screen was captured in a snapshot. Audits per module raised the findings, each with its proof. The fixes, within those rules, dealt with concurrency in the database, CSRF, session, login and headers, and brought a lean design system. At the end, everything was compared with the snapshot, every difference explained, and the release uses a backup, an atomic folder swap and a rollback.
Context
An organization uses a web system to run in-person events such as trade fairs and conferences: it registers or imports attendees, checks them in at the door and prints their badges, accredits support staff, sells products at its booth with receipts and controls the stock of each event. There are two profiles, administrator and attendant. The system was already in production; my job was to review all of it and modernize it without changing what could not change.
What I did
- Diagnosis before fixes. Four audits per module, an inventory of routes with method and permission, and a list of the business rules that could not change.
- A snapshot to compare against. 68 screens captured before the first change and compared at the end; every difference in a number got a written reason.
- Integrity. Race-free sale numbering, idempotent check-in, stock edits that do not undo sales made while the screen was open, and aggregation fixes in the dashboard and the report.
- Security. A baseline reviewed across categories A01, A03, A05 and A07 of the OWASP Top 10: CSRF, sessions, login limits with constant response time, headers and formula-free exports.
- Interface. A lean design system, a menu grouped by task (operation, sales and stock, reports, administration) and a dark theme designed for exhibition halls, with a light alternative.
- Release. Documented with a backup, an atomic folder swap and a prepared rollback.
Limits
The figures come from the review report and were not re-run independently. Revenue, attendee counts and event names belong to the client and stay out; the demo uses made-up events, people and amounts.
Constraints
- A production system, used at the counter on event days.
- A written list of the business rules that could not change, made before any fix.
- Development on an anonymized copy of production.
- The session has to last an 8-hour shift at the counter.
Decisions
Snapshot every screen before touching anything
- Context
- With no automated tests, a fix could change a report figure or break a screen without anyone noticing.
- Choice
- Capture 53 screens as an administrator and 15 as an attendant before the first change and compare everything at the end: HTTP status, PHP warnings and every number shown.
- Gains
- No difference went through without a documented reason.
- Costs
- The snapshot only covers what was captured; the rest relies on flow tests and on reading the code.
Audits per module, with the proof of every finding
- Context
- A finding without proof becomes an opinion, and opinions do not set priorities.
- Choice
- Four independent audits (sales, stock and products, people and core, interface), each finding tagged with its proof: confirmed over HTTP, through SQL or only by reading the code.
- Gains
- The order of the fixes followed what was proven, not what looked serious.
- Costs
- More diagnosis time before the first fix.
Concurrency solved in the database
- Context
- At the counter, simultaneous sales raced for the same number, and editing stock with the screen open could undo sales made in the meantime.
- Choice
- Race-free sale numbering, idempotent check-in and stock movements recorded as relative changes, under a lock.
- Gains
- Simultaneous sales recorded with no repeated number.
- A double tap on check-in does not undo attendance.
- Costs
- Every change to sales and stock now needs a concurrency test.
A lean design system instead of repeated CSS
- Context
- Every screen carried its own copy of the styles, and colors had no meaning.
- Choice
- One design system, with a single action color, green and yellow used only for meaning, a menu grouped by task, each profile seeing only what it can use, and tables that become cards on a phone.
- Gains
- Less code to maintain, and a dark theme designed for exhibition halls.
- Costs
- Every screen had to be reviewed and compared against the snapshot.
Stack and why
- PHP
- The existing system, reviewed and fixed without a rewrite.
- In-house CSS
- A design system of about 20 KB, with dark and light themes.
- Flow tests in PHP
- The sales flow with 51 checks.
- Python
- Comparing the screen snapshot before and after.
Results
Twelve simultaneous sales: before, 11 failed; after, all 12 recorded with no repeated number.
self-reportedThe review report68 screens compared before and after, with no HTTP status changed and no PHP warning.
self-reportedThe review reportBatch receipts down from 10.5 MB to 1.5 MB.
self-reportedThe review reportCSS down from about 216 KB of repeated styles to about 20 KB, and screen HTML 34% smaller overall.
self-reportedThe review report
Security angle
Attack surface
- Login for administrators and attendants.
- Booth sales and stock updates.
- Importing attendees from a spreadsheet.
- CSV and XLS exports.
Controls in place
- CSRF protection on every write.
- A hardened session that lasts an 8-hour shift.
- Login attempt limits, with the same response time for existing and non-existing users.
- Security headers.
- Formulas neutralized in CSV and XLS exports.
- Each profile sees and uses only what it may, and the system never allows zero administrators.
What I would test today
- An attendant reaching administrator screens through a direct URL.
- A race between a sale and a stock transfer.
- An import spreadsheet with formulas or an unexpected encoding.
Evidence
- audited private repositoryAudited local repository(Audit of the private repository, Sep 2026)