Case Study · Internal Automation
An automation that runs on data its architect never saw.
A schema-first daily personalization engine for a municipal employee directory. The architecture decisions that made it work — and what they unlock for any governance-sensitive automation problem.
The problem
Make every employee feel seen — at scale.
The Vice Mayor's office wanted to send personalized birthday greetings to every city employee, on the right day, in a tone that reflected each person's role and department. With thousands of employees, doing this manually meant either skipping people or losing an hour every morning to directory hunts. The ask was for an automation that would do the heavy lift while keeping the human signature in the loop.
The constraint
I was not allowed to see the employee list.
City Hall HR data is sensitive. Names, dates of birth, departments, role hierarchies — none of it could leave the municipality's perimeter, and none of it could be visible to an outside contractor. The standard consultancy approach — export the data, build on it locally, deliver — was off the table from day zero.
The list was also not static. People joined, left, transferred, and changed roles continuously. Any solution that depended on a snapshot would drift out of sync with reality the moment somebody got promoted on a Friday afternoon.
The approach
Schema as the only artifact that crosses the perimeter.
The whole engagement was solved by separating the structure of the directory from its contents. I designed the schema contract — column names, types, allowed values, the metadata fields the personalization logic would need — as a specification document. That spec was the only thing I needed to see. The directory itself stayed entirely inside the municipality.
The script was written against the schema, not against any rows. It asked questions in the abstract: "give me tomorrow's birthdays, return the columns the personalization engine declares as inputs." The script never logged, exported, or transformed live data beyond the moment of use, and even that lived only inside the same trusted environment where the data already was.
Deployment lived on an internal account the city already trusted. Triggers ran inside the platform's infrastructure under the client's identity. I did not have access to the list, the runtime, or the messages it produced. What I delivered was a spec and a script that, once installed, ran correctly against any directory satisfying the contract.
What's running now
Daily. Inside the perimeter. Without me.
The system runs every morning, generating personalized birthday drafts for the next day's celebrants. The Vice Mayor reviews, signs, and sends — which keeps the human touch where it matters. People who used to fall through the cracks of a multi-department organization now get acknowledged on the right day, in a tone that feels like it came from someone who actually knows them.
The architectural choice that made it possible — schema as the only thing that crosses outside — is what made it governance-defensible from day one. There was nothing for HR or legal to object to, because there was nothing to extract.
What's reusable
Three principles for any sensitive-data engagement.
- Schema-first delivery. Specify the contract the client's data must satisfy, build against the contract, never against rows. Ship something that runs correctly against any dataset matching the spec. The data never leaves the perimeter; the architect never sees it.
- Inside-the-perimeter deployment. Sit on internal accounts the client already trusts. Use the platforms they already use, so governance has nothing new to vet. The architect's role ends at handoff; the system runs under client identity.
- Soft-failure under churn. Treat every shape assumption as something the live data will eventually violate. Default to graceful degradation rather than hard failure. A daily-running automation that breaks on the first edge case is worse than one that gracefully ignores it.