Every consolidation deck in this market has the same slide: the enterprise browser and the SASE stack are converging, buy them together, one agent, one console, one policy. I lead the team that shipped exactly this merge, browser and gateway under Ulaa on a single policy plane, and the slide is not wrong about the destination. It is wrong about the work. The merge is sold as a packaging exercise. It is actually three contracts between two systems that grew up with different ideas of what a user is, what a policy means, and where traffic can be read. Skip the contracts and you have two products in one SKU, which is what a lot of the category quietly ships.
Contract 1: one identity object
The browser knows the user as a profile and a session: a signed-in identity, a person at a keyboard, group memberships resolved when the profile enrolled and refreshed when the browser feels like it. The gateway knows the user as claims on a tunnel: whatever the authentication handshake stapled onto the connection when it came up, valid until the token expires. These are two different objects that happen to share a display name.
The merge is making them one object. One identity that both enforcement points resolve from the same source, with groups that mean the same thing in both places and go stale at the same rate. This sounds trivial and it is most of the work. Take a policy that says contractors upload nothing. The browser evaluates "contractor" against the directory groups cached on the profile, the gateway evaluates it against the claims minted at tunnel setup, and a contractor converted to full-time that morning is a contractor on one path and an employee on the other, for hours, and neither log will tell you why the same person got two answers. Every policy that names a group inherits this skew until the plumbing underneath is fixed: one schema, one refresh discipline, one answer to the question of who this is. Nobody puts schema reconciliation on a slide. It is the merge.
Contract 2: same policy, same verdict
The invariant we ended up writing on the wall: same policy, same identity, same request, same verdict, regardless of which enforcement point saw it. Everything else in this section is just what it costs to keep that sentence true.
It costs a single policy schema, authored once, not a browser rule language and a gateway rule language with a sync job pretending they agree. It costs either one evaluation engine compiled into both sides, or two engines with a conformance suite between them that runs on every policy-language change, because two engines without that suite will drift, not might, will. And it costs a shared verdict vocabulary. Block, alert, and coach have to mean the same thing and render the same way whether the decision came from the page or the wire. A user who gets a branded coaching page in the browser and a bare connection reset from the gateway for the same violation has just been shown, more clearly than any datasheet could deny, that this is two products.
The frame that kept us honest here is old NIST vocabulary, not marketing: one policy decision point, many enforcement points. The browser is an enforcement point. The gateway is an enforcement point. Neither of them owns the policy, and the day one of them grows a private exception is the day the invariant on the wall stops being true.
Contract 3: put each check where the view is native
The browser sees plaintext for free. It sits inside the TLS boundary by construction, it sees the request before encryption and the response after decryption, per tab, with full user context attached: which profile, which site, which form field the bytes came from. The gateway has to earn that same view by terminating TLS in the middle, and the middle is getting worse to stand in. QUIC moves the transport out from under splice logic written for TCP, and encrypted client hello removes the one plaintext field that SNI-based policy was leaning on. The gateway is going progressively blind, not because anyone built it badly, but because the web is closing the hole it lived in.
So the honest architecture stops pretending one box inspects everything and places each check where the view is native.
| Control | Where the view is native |
|---|---|
| DLP on upload bytes | Either side, the browser just sees them earlier |
| Watermarks, copy and paste, screen-level rules | Browser only |
| Private app routing | Gateway only |
| Native apps, unmanaged devices, other browsers | Gateway only |
That last row is why the browser does not simply win the argument. The gateway covers everything that is not your browser, and on a real fleet that is a lot of traffic. The browser covers everything the wire can no longer show. The merge is worth doing precisely because neither view is sufficient alone, which is also why gluing the two products together at the installer solves nothing.
The one-agent test
Which brings me to the "one agent" line, because an installer is the easiest thing in this whole story to consolidate. An agent that unpacks a browser and a tunnel client side by side has consolidated the download page, not the enforcement. All three contracts can be unsigned behind a single icon in the system tray.
A buyer can check this in an hour, no vendor call required. Write one policy: block uploads of files containing a marker string to personal storage. Trigger it in the browser path, then trigger it from a native app so it travels the network path. Compare what the user saw in each case, and compare the two log records. If the messages differ, if the logs carry different field names or different identifiers for the same person, if one path says coach and the other says drop, the contracts were skipped and the SKU is doing the merging.
We spent the engineering months on the contracts, in roughly the order above, and the identity object took the longest by a wide margin. If you are building this merge, budget that way: schema first, conformance suite second, placement map third, installer last, it is the least of it. If you are buying it, run the hour-long test before the renewal, not after.