# Enterprise Deployment (force-install + managed config)

Force-install via Google Workspace admin policy is the **primary B2B distribution
path** (target customers are on managed devices). Public Web Store install is
secondary.

## 1. Force-install the extension

In the Google Admin console (Devices → Chrome → Apps & extensions, or via policy):

- Add the extension by ID with **Force install**, or set `ExtensionInstallForcelist`
  / `ExtensionSettings.installation_mode = "force_installed"`.
- See [`enterprise-policy.example.json`](./enterprise-policy.example.json) for a complete
  example. Replace `EXTENSION_ID` with the published Web Store id (or your self-hosted
  CRX update URL).

## 2. Push managed configuration

The extension reads `chrome.storage.managed` (read-only, admin-set). Schema:
[`obep/extension/src/managed_schema.json`](../obep/extension/src/managed_schema.json).

| Key | Purpose |
|---|---|
| `relayUrl` | **Pins** the relay endpoint, so a compromised page can't redirect the extension to a rogue relay. |
| `tenantId` | Marks an org-managed install for this tenant and enables enterprise auto-pairing. |
| `allowedTenants` | Locks the install to exactly these tenant(s). A normally-installed extension can **never** auto-pair. |
| `unpairLock` | When true, end users cannot unpair org bindings from the side panel. |

Set these under `ExtensionSettings.<id>.managed_configuration` (see the example).

## 3. Enterprise auto-pairing flow

With managed config present, the extension enters auto-pair mode for the pinned
tenant(s):

1. The extension reads the managed config (relay endpoint + tenant), so no manual relay
   URL entry is needed.
2. When the user is logged into the customer's web app, the app posts a **short-lived,
   signed identity assertion** (`{ tenantId, userId }` signed by the tenant's private key)
   to the extension via the trusted-origin channel.
3. The extension forwards it (`pair { assertion }`); the relay verifies the signature
   against the tenant's **registered public key** and creates the `(tenantId, userId)`
   binding — no manual code entry, no prompt.

Guardrails (enforced):
- Auto-pair only when managed config confirms an org-policy install; `allowedTenants`
  pins which tenant(s) may pair (extension + relay both check).
- Identity assertions are signed and single-use/short-lived; a forged or replayed
  assertion is rejected.
- The side panel still lists all bindings; `unpairLock` controls whether end users may unpair.

## 4. Verify before approving

Your security team can audit the open `/obep` code and run the conformance suite against
the relay before rollout — see [SELF_HOSTING.md](./SELF_HOSTING.md) and
[SECURITY_MODEL.md](./SECURITY_MODEL.md). OpenErrand is just a relay that passes the open
conformance suite.
