Demo identity switcher. Authority is checked on the server for every decision, so switching roles here cannot approve a gate you do not hold.

How it works

Testcell is a small, complete example of the thing legacy CFML applications are usually built around: a form, a queue, and a chain of approvals that has to be defensible afterwards.

Gates cannot be skipped

A request walks Safety Review, then Facility Readiness Review, then Scheduling Confirmation. The ordering rules live in one file (models/StateMachine.cfc) with no database and no framework dependency, so they can be read in one screen and tested without a datasource.

The check that makes gates un–skippable is that a reviewer may only decide the gate the request is actually sitting on. Reaching forward to pre–approve, or back to re–open a settled gate, is refused by the service layer — not by a UI that merely hides a button. Posting straight at the endpoint gets the same refusal.

Two reviewers, one advance

Approvals are taken under SELECT … FOR UPDATE on the request row, inside the transaction that writes the decision. A second reviewer pressing Approve at the same instant blocks, then re–reads the committed state and is refused, so the request advances exactly once.

The UPDATE is additionally guarded on the expected prior state (a compare–and–swap), and the test suite runs concurrent approvals in real threads to prove it rather than asserting it in prose.

Gap-free, append-only audit

Request numbers and audit sequence numbers come from a counter row locked in the same transaction as the record that consumes them. An AUTO_INCREMENT would have been simpler and wrong: it is non–transactional and leaks its value on rollback, which produces gaps — and a gap in a number quoted on safety paperwork is a question somebody has to answer in an audit.

Decision and audit rows are never updated or deleted, and each carries a per–request sequence that is unique in the database. A removed row is therefore detectable; the request page shows that check running.

Section 508 is a build gate, not a review note

The conformance target is Section 508 / WCAG 2.1 AA, and it is verified mechanically: an axe–core audit runs against every page of the running application and fails the build on any violation. Accessibility that is only checked by hand regresses the first week nobody has time to check it by hand.

What that buys, concretely:

  • A skip link that is the first thing in the tab order and visible when focused.
  • One error summary per form, focused on arrival, each item linking to the control it describes.
  • Status shown as text, never colour alone — every pill reads as words to a screen reader.
  • Tables with captions and scoped headers, so a row is announced with its request number.
  • Landmarks, a single h1, and no positive tabindex anywhere.

Stack

CFML on Lucee (the open–source CFML engine, so the demo can be hosted without a licence), MySQL, and vanilla JavaScript — no front–end framework, because nothing here needs one. Every query is parameterised with cfqueryparam.

There is a read–only JSON API over the same service layer. Legacy CFML modernisation usually starts by exposing the data the old screens are sitting on, so the service layer returns structures and the two front ends — HTML and JSON — are thin.