An internal ops platform for a video-production team started as a project tracker and grew, over about three weeks, into something closer to an HR system: employee scorecards, evaluation dashboards, a product catalog, and a shared proxy layer that every other internal tool routes through. That last part is what makes this cluster of PRs worth writing up together — a proxy sitting in front of several tools accumulates security bugs differently than any single tool does, because a mistake there isn't scoped to one screen. It's scoped to everything behind it.
A permission check that lives only in the UI is a suggestion. A permission check that lives at the route is a rule. Ship the rule.
Turning hardcoded lists into admin tables
The project tracker's list of valid projects lived in two places that had to agree with each other: a TypeScript union in the board component, and a database CHECK constraint. Adding a project meant a pull request and a deploy for what is, functionally, one row of data. PR #16 replaced both with a real projects table and an admin UI, and PR #18 shipped it to production with a detail worth keeping: a project's board section only renders once it actually has a task, so the board doesn't fill with empty tables as the project list grows ahead of real work. PR #19 then gave Projects its own sidebar entry under Admin instead of leaving it stacked under Users & Access — a small move, but it's the difference between an admin feature existing and an admin feature being findable.
The same pattern repeated twice more, each time for a reason specific enough to be worth its own PR. PR #47 moved the export tool's product dropdown out of hardcoded TypeScript in a sibling repo into an export_products table with its own admin page — and the PR body is explicit about why this didn't just reuse the existing projects table, walking through the field-level differences that made a shared table the wrong shortcut. PR #50 did the same for evaluation categories, and it's the richest of the three: detectCategory is an ordered ladder of string-matching rules where the order itself carries meaning — "LEAN UV Cleaner Upsell C1" is a real production row, and it scores correctly as a Lead only because the L-prefix rule is checked before anything that matches "Upsell." Turning that ladder into editable data meant preserving the ordering as a first-class priority column, not just a list — getting the migration wrong would have silently reclassified real historical rows.
Applying a rule retroactively means measuring before writing
PR #49 added Upsell as its own scoring category — a substring match, the only one in the whole ladder, deliberately placed last so it can only claim what no earlier, more specific rule already claimed. PR #52 then applied that rule to all of history, and the PR description is a small model of how to do a backfill safely: before writing anything, it measured read-only what was actually in the database — confirming nothing had ever been scored in this tool before a specific date, so there was no prior scorecard the backfill could silently contradict. PR #53 closes the loop with something that isn't a code change at all: a written record of a deliberate decision — asked directly whether any id containing "upsell" should always score as Upsell, the category owner said no, categories should strictly follow the first-letter code, because some upsells are really just leads or bodies underneath. That answer is exactly why the substring rule sits last in the ladder rather than first, and writing the reasoning down next to the rule is what stops a future well-intentioned refactor from "fixing" the ordering into something that quietly breaks four real rows.
Employee Management: access enforced in the API, not the component
PR #26 shipped the Employee Management tool, and its own description states plainly why it isn't simply the feature as originally built: the manager's board component was a 3,822-line client component making 34 direct Postgrest calls straight from the browser. Every one of those calls was only as safe as the row-level security policy behind it — a UI-only gate, dressed up as a feature. The shipped version moves access enforcement into the API layer and normalizes the editor reference so editor data is looked up once, not repeated across dozens of call sites.
PR #27 is the verification that followed the launch, and it's a good model for what "verify a permission boundary" actually looks like in practice: a manager asked directly whether the Evaluation tab was private to each editor, and rather than answer from memory, the check walked all three layers — route, API, and rendered payload — and found the tab genuinely was private, but also found a real bug hiding next to the correct behavior. An editor's page was unconditionally requesting a manager-only dashboard resource, which meant a guaranteed 403 firing silently on every single editor page load. Confirming a security property is correct doesn't mean the code path exercising it is clean, and this PR is the difference between checking the outcome and checking the mechanism.
PR #28 shipped a "you vs. the team" comparison card on an editor's own scorecard — four KPI averages plus their own numbers, side by side — and the type design does real work here: the payload type is a closed shape with exactly four numbers and a rating band, structurally unable to carry a per-editor name or id. Widening it into per-editor data later can't happen by accident, because there's nowhere in the type for that data to go. That's access control enforced by the shape of the data, not by a check someone has to remember to write.
The proxy: four bugs, each found while fixing a different one
The most consequential work landed on the shared proxy every tool in the platform sits behind, and it's a clean example of how security bugs cluster: fixing one often surfaces the next, sitting right next to it.
PR #29 found that GET and HEAD requests were proxied with redirect: "follow", so the underlying HTTP client resolved any 3xx server-side without checking whose origin it was following to. One tool redirects a finished render to Google Drive; the proxy followed that redirect itself, with no Google session attached, got a 401 back from Google, and returned Google's raw HTML error page to the browser — under this app's own origin. A user who successfully finished a render an hour earlier saw a third-party error page served as if it came from the platform they were using. The fix scopes follow to same-origin redirects only, which is also the fix for the credential-leak shape this bug could have taken with a maliciously-controlled redirect target.
PR #31 closed a related but separate issue found while reviewing #29: the proxy stripped content-length from every upstream response, which kills the browser's download progress bar. On a 221MB deliverable, a progress bar with no length to report against looks exactly like a stuck download. The fix is narrower than the original strip — content length only needs to be dropped when the body is being transcoded, not when it passes through byte-for-byte unchanged.
PR #33 is the sharpest bug in this cluster, and it was found purely by re-reading code that PR #31 had just touched for an unrelated reason — a genuinely different defect sitting one function away from the one being fixed. Response headers were rebuilt using Headers.forEach plus .set(), and set-cookie is the one HTTP header that doesn't comma-fold into a single value — the Fetch API yields each cookie as a separate entry specifically so they don't get merged. Looping with .set() silently overwrote each prior cookie with the next one, so only the last upstream cookie ever survived the proxy. Measured directly against a real response: two Set-Cookie headers in, one out.
// before: only the last Set-Cookie survives
upstream.headers.forEach((value, key) => {
responseHeaders.set(key, value); // .set() overwrites on repeat keys
});
// after: append preserves every cookie in the response
upstream.headers.forEach((value, key) => {
if (key.toLowerCase() === 'set-cookie') {
responseHeaders.append(key, value);
} else {
responseHeaders.set(key, value);
}
});
PR #34 is the one I'd flag as the most important, because it's not a proxy bug — it's an authentication check that only looked like one. A "fast path" for serving tool sub-resources authenticated requests by testing the name of a Supabase auth cookie — does it start with sb- and contain -auth-token — without ever parsing or verifying the value inside it. Confirmed directly against production: a cookie literally named sb-probe-auth-token holding a single arbitrary character passed the check, the asset was served, and the request was forwarded upstream with the platform's own internal secret header injected on top. The upstream tools trusted that secret unconditionally, which meant the proxy's cookie-name check was the only gate in the entire chain — and it was satisfied by a cookie any client could set itself. The fix verifies the token's actual claims offline, without a network round-trip, closing a gap where "looks like an auth cookie" and "is a valid session" had quietly become the same check.
Small operational fixes that mattered in practice
Not everything here is a security finding. PR #38 fixed a UX bug reported directly by an editor — the tracker board polled every fifteen seconds by bumping a counter that was part of its data-fetching cache key, so every poll looked like a brand-new request and reset the scroll position, several times a minute, on a page someone was actively working in. PR #36 added a visual distinction the queue was missing: a launch-queue row could land on the board for either of two different reasons — actually approved, or simply because its target date arrived — and both rendered identically, so a ready-to-ship row was visually indistinguishable from one that still needed sign-off. PR #37 turned a dead lint step back on after a framework upgrade had silently stopped enforcing it, and fixed everything it immediately found. PR #41 and PR #54 both fix the same category of trust problem from different ends: a scorecard was visible before its reporting period had actually posted, and a manager's written review and score corrections were silently never reaching the editor they were about — two separate defects sitting behind one hardcoded line of placeholder text.
The pattern: a shared proxy multiplies the blast radius of every shortcut
Four real defects — an off-origin redirect follow, a stripped content-length, a cookie-folding bug, and an authentication check that verified a name instead of a value — all sat in the same few hundred lines of proxy code, each found while looking for a different one. That's not a coincidence particular to this codebase; it's what happens when one piece of infrastructure sits in front of everything else. A shortcut in a single tool's own code affects that tool. A shortcut in the layer every tool routes through affects all of them at once, silently, until someone reads that code specifically looking for what else might be wrong nearby. The right response to finding one bug in shared infrastructure isn't just fixing it — it's treating the surrounding code as suspect and reading it again.