← Portfolio Case Study

Studio Manager — when fixing one bug surfaces eleven more

Klient: Swiss services studio (recurring client) Czas: 1 working day (project 7 in a 3-month cycle)
Base44 Deno Deploy Webhooks Resend Compliance

Before

  • Compliance email did not fire for newly created profiles
  • Status field empty (null) — UI rendered it as "not visited"
  • 11 historical records with the same issue (client knew of 4)
  • End-to-end tests via the platform AI agent gave false negatives

After

  • 5 promised scope items delivered + 50% additional discovery scope
  • 11 historical records surfaced for case-by-case review
  • Auto-default + dedicated UI section for unset statuses
  • 2 platform bugs fixed/escalated + testing methodology changed

Context: project 7 in a 3-month cycle

The client operates a services studio in Switzerland. The management system is built on a low-code platform (Base44) plus custom webhooks on Deno Deploy. We've been working together for three months — the relationship started with one small fix (a broken Telegram integration) and grew incrementally into seven discrete fixed-price projects.

Earlier phases: bot pairing, payout system hardening (atomic operations), 3-tier RBAC, a second cloned system for a second location, a separate notification bot, a backend refactor of payout logic from browser to server. This case study is phase 7 — the compliance email integration.

The recurring pattern: UI states that look like answers but aren't. This bug was a textbook case.

The problem

The client reported it precisely: a recently deactivated worker with a 90-day permit hadn't generated the expected compliance email to the external office. In the panel her status looked like "not visited" — the prerequisite for the email. In reality, the field was empty (null), and the automation only fired on an explicit "not_visited" string.

Honest framing: this was a gap in my own implementation from two weeks earlier. I designed for the explicit "not_visited" path and didn't consider the field could be empty in practice — which it was for every newly created profile, until someone clicked a button in the panel. I absorbed the fix into the original project's price as warranty.

Diagnosis

The bug was an iceberg. The first promised scope had 5 points. After deploying the first change (a UI section for profiles with empty status), the panel itself rendered 11 historical records with the same problem. The client knew of 4. The system found 14.

Along the way, additional findings:

  • 3 previously unknown new profiles created in the days before the bug surfaced — same empty-status, same problem.
  • Platform bug: the is_empty operator did not match null, only empty strings. The first auto-default automation never fired in testing.
  • UI classifier bug: an inherited fallback (return 'not_visited') masked empty fields as "no" — the same mechanism that hid the original bug.
  • One discovery worth its weight in gold: end-to-end testing via the platform's AI agent (server-role) does not trigger entity automations. Only user-context operations do. This explained several earlier confusing test results and changed my testing methodology going forward.

Solution

1. Email function filter

Rewritten filter accepts null and empty string as "not visited" — provided the permit is 90-day. Two truth states: explicit and implicit.

2. Auto-default on new profiles

Automation initializes the status field to "not_visited" at profile creation for any 90-day permit. The field is never empty "by accident" again.

3. New UI section

Dedicated panel section for profiles with empty status, with a distinct color. The client sees what the system doesn't know, not just what it does know. Fix at the visual layer plus a fix to the classifier in the panel code.

4. Historical data migration

14 identified records surfaced for the client's case-by-case manual review — not auto-resolved. The client decides what happens with each one.

5. End-to-end test through the real path

Test executed through the UI like a real user (created a test profile, deactivated, verified compliance email arrived). Pass.

Result

The client paid the original project's price. They received:

  • 5 promised deliverables, all working
  • 3 previously unknown profiles correctly initialized as a side effect of due diligence
  • 11 historical records made visible for case-by-case review (not auto-resolved — their call)
  • 2 platform-level bugs found and either worked around or escalated to platform AI
  • A UI classifier fix outside explicit scope but necessary for the new section to mean anything

Actual time spent: roughly 2.5x the estimate for the original 5 points. Some of that was warranty on my prior implementation. The rest was discovery — items not on the agreed list, but without which the list would mean nothing.

Takeaways

Five lessons I'm carrying into every future fixed-price contract:

  1. UI states that look like answers but aren't are a foundational data-quality risk. The fix requires changes at three layers: data model (initialize on create), UI classifier (distinguish empty from "no"), visual presentation (a distinct section). One layer alone is not enough.
  2. End-to-end means end-to-end — through the same execution path real users take. Half a day wasted on tests that ran through a channel that didn't trigger automations.
  3. A discovery rider on every fixed-price contract. Analysis always understates scope, because data-quality issues only surface once the system starts looking for them. Future contracts will include: "if analysis surfaces additional records or systemic issues beyond the list, they will be quoted separately".
  4. Warranty is warranty — name it. Absorbing rework into the original price is a deliberate choice, not a silent scope expansion. Communicate it clearly.
  5. Client correspondence is the source of truth. Every business rule in this project traced back to a specific quote from the client's messages — sometimes from two months back. Don't guess where you can check.

Three months of working with this client is the most valuable asset of this engagement. This project is one example where I chose to absorb additional cost in exchange for a clean delivery and continued relationship. I'd make the same choice again — but next time I'll communicate the trade-off more clearly.

Have a similar problem?

Describe it to AI — it gathers technical context, Artur delivers a quote in 48h.

Start diagnostics