Skip to main content

Keystone — Why This Deserves to Be the First Real Topic

Status: Written 2026-08-19, from a conversation working through RoundTrip's Entra identity problems. Not a decision — seed material for the future cross-product Architect conversation, so the reasoning isn't lost between now and whenever that conversation actually happens.


The problem this started from​

RoundTrip has two real, currently-open tickets, both caused by the same underlying fact: Entra External ID isn't a standalone product, it's Entra ID wearing a consumer-facing hat — still fundamentally part of Microsoft's broader identity graph.

  • TRA-384 — registration fails outright if a prospect's email already has any Entra identity (a real M365 account under that address).
  • TRA-389 — even a completely fresh email fails differently: if the domain is verified anywhere on a real Microsoft tenant, Entra's home-realm discovery redirects the user to authenticate against their M365 instead of RoundTrip's own login.

Cross-tenant recognition is a genuine feature from Microsoft's perspective — seamless enterprise SSO. For a product whose whole point is a clean, isolated, per-tenant identity system, that same feature actively works against it.

Near-term fix, already planned, not blocked on anything below: finish the registration migration from InviteUserAsync (guest — the mechanism that collides and redirects) to CreateMemberUserAsync (local member account, the same mechanism team invites already use successfully). A local account inside RoundTrip's own roundtripapp.onmicrosoft.com tenant isn't a cross-tenant reference at all — it shouldn't trigger either bug. This was always the originally intended fix; it just never got finished. Worth proving this closes both tickets before treating anything below as necessary rather than merely nice-to-have.


The bigger question this raised: does Traxs One need its own identity layer?​

OpenIddict came back into the conversation — a self-hosted identity provider, evaluated once before, early on, and deliberately set aside.

Why setting it aside then was the right call, not just caution​

At that point, RoundTrip was the only real product. Building a shared identity system to serve a theoretical future platform, before knowing what Waypoint or Relay would actually need from auth, would have been solving a problem that didn't exist yet — premature abstraction, not foresight. Passing on it then was correct, not timid.

Why the calculus is different now​

Three real things changed, not just a mood:

  1. Waypoint is real and in active development. Relay is planned. This is no longer a hypothetical platform.
  2. RoundTrip has now hit real, lived consequences of not having product-agnostic identity — TRA-384/389 aren't architectural speculation anymore, they're bugs that cost real debugging hours.
  3. The cost math changes with the denominator. Self-hosting a full identity provider is genuinely too expensive for one product to carry alone. Amortized across an entire platform — three or four products sharing one identity layer instead of each reinventing it — the same cost looks completely different. OpenIddict was never the wrong tool; it was being evaluated against too narrow a scope.

The real cost, honestly — not just the appeal​

This isn't free, and worth naming plainly rather than only listing the upside:

  • A full identity-foundation migration on live systems — RoundTrip already has real customers, real billing, real registered tenants. JWT claim parsing, TenantScopingBehavior, the entire MSAL frontend flow are deeply Entra-shaped today.
  • Taking on security-critical responsibility currently owned by Microsoft — password resets, brute-force protection, session security, all currently just handled as a managed service. That's a real, meaningful shift in what a solo founder building evenings around a full-time job is on the hook for.
  • Centralizing risk, not just infrastructure. Today, if RoundTrip's auth has a problem, Waypoint is completely unaffected — they're independent. A shared Keystone becomes a single point of failure for the entire platform at once. Not a reason to avoid it — most successful multi-product platforms work exactly this way — but it raises the bar on what "done" means before other products actually depend on it. This needs to be built with real care, not the pace of a quick fix.

Where this actually leads​

  1. Fix RoundTrip's two tickets first, via the already-planned CreateMemberUserAsync migration — proves out (or disproves) whether the near-term problem needs anything bigger than what's already scoped.
  2. Bring Keystone to the Architect conversation as its first real topic, once that conversation actually exists — not because it's urgent, but because a decision this foundational deserves to be made with the whole platform in view, deliberately, rather than reasoned out in the middle of a bug fix.
  3. The original "chicken out" instinct and this new instinct are both right, for their own moments. The tool didn't change. What it's being asked to justify did — one product's convenience versus an entire platform's foundation. That's the actual argument worth carrying into that conversation, not just the conclusion.