Earth · Case study
Hangar OS
One platform for a 450-member innovation space.
1,382 commits · 175 database migrations · 934 tests · 4 audits
The ETH Hangar at Innovationspark Zürich used many separate tools. A paid booking tool with recurring fees managed the meeting rooms, and the doors had no displays. Microsoft Forms with Power Automate managed visitor registration. The other data lived in Excel files on Teams. Six student teams and the companies on campus share nine meeting rooms in three buildings.
In one summer, I replaced these tools with one platform. Members book rooms themselves. The database rejects each double booking. Team leads manage their own rosters. A host registers a guest without help from an admin. E-ink displays at the doors show the live room status. A member can book a room by email and can answer the invitation with the Outlook buttons. The result is one app for everybody on campus. It makes daily life at the Hangar easier.
Before launch, I ran four adversarial audits with independent AI agents. Then five scripted personas did each step of the launch email in a simulation. The simulation found two defects before a real user could find them. The platform monitors itself each hour. It sends an alert when it detects suspicious activity. When the monitor sends no signal, an external watchdog sends an alarm.
A handbook for non-technical operators is built into the platform. A runbook shows a technical successor how to operate and extend it.
Technical notes
- A Postgres exclusion constraint prevents double bookings, not application code. An end-to-end test sends two overlapping bookings to a real database branch. The database rejects the second booking.
- Magic-link sign-in fails at ETH because Microsoft Safe Links opens each link and uses the single-use token. The solution is a one-time code that the member types. The platform checks the member allowlist when the member enters the code. This design also prevents email enumeration.
- The German/English dictionary uses the German text as its key. A missing translation is a compile error. For an untranslated string, the platform shows the German text. I completed the retrofit in 37 commits, with no release freeze.