GoodLeap · 2026

Deleting five copies of the same auth code

Co-owned the payments-domain rollout of an org-wide move to scoped permissions — and argued the scope grammar back toward least privilege.

On request
5 → 1
auth implementationsConsolidated into one shared library.

The situation

An identity team was moving the organisation from individual permission claims to a single space-separated scope claim. Five payments services each carried their own near-copy of the authorization stack, so the migration was nominally five separate pieces of work.

Doing it five times would have meant five chances to diverge, at exactly the moment every service needed to agree about what a permission meant.

The constraints

  • Legacy claims had to keep working for the whole migration window. This was a dual-read migration, not a cutover.
  • Mapping a broad legacy claim straight onto a scope can silently over-permission, so the claim mapping had to be separable from the authorization change.
  • Other teams were shipping into these services throughout, including a product launch mid-migration.

The call

Consolidate the auth stack into the shared library first, so scope handling landed once and each service adopted it with a dependency bump. The alternative — five parallel implementations — was more total work and guaranteed drift.

Push back on the proposed scope grammar toward least privilege. I argued the base scope should be the restrictive one, with conditions widening it — secure by default rather than secure by remembering.

Hold the least-privilege change as a parked, open pull request rather than merging it early. It depended on scopes that did not exist yet; parking it visibly was more honest than deleting it and rediscovering the argument later.

Keep a no-op mapping change out of the deploy window during another team's launch, even though it could not have broken anything, because "it is safe" is a worse argument than "it can wait".

What happened

Scope support landed in the shared library and was adopted across the payments services, replacing five near-copies of the authorization stack with one.

The escalation to the identity team won revised org-wide guidance on the scope design.

What I'd do differently

I would raise the grammar question before the shared implementation was in review rather than during — an escalation is cheapest before the code that depends on it exists. Even so, it was a good trade against the alternative: every service quietly encoding its own reading of the rules.

Built with

TypeScript · NestJS · OAuth scopes · JWT