# Deploying the SCIM identity-sync bridge (PingCAP tenant)

L2 deployment wiring for `services/scim-bridge/` — the bridge that lets Helix
provision/deprovision NexusCRM users over standard SCIM 2.0 without any change
to NexusCRM core (it drives NexusCRM's public data API under a connected-app
RunAs identity). This directory holds the runbook + systemd unit; the service
code and its behavior contract live in `../../services/scim-bridge/README.md`.

## One-time NexusCRM setup (operator)
1. Create a least-privilege **RunAs user** (see the service README for the exact
   permission tier: ApiEnabled; Read+Create+Edit on User with field-level access
   to the mapped fields; read-only access to Profile and the eight listed
   Profile/PermissionSet grant objects used for zero-access verification; no
   delete; no password permissions).
2. Create a **confidential Connected App** (`client_credentials`, RunAs = that
   user, scopes covering `/services/data`) and note its `client_id` /
   `client_secret`. This is done in NexusCRM's admin UI, not seeded — a
   confidential app's secret must be hashed by the records engine, never written
   as tracked data.

## Deploy the bridge on the host
The bridge is a single self-contained stdlib file. Install it to a system
location owned by a dedicated service account (not run from an operator home
checkout, which a separate service user cannot traverse):

1. Create the service account: `useradd --system --user-group --no-create-home --shell /usr/sbin/nologin nexuscrm-scim-bridge` (`--user-group` creates the matching `nexuscrm-scim-bridge` group the unit's `Group=` requires).
2. Install the program:
   `install -D -o nexuscrm-scim-bridge -g nexuscrm-scim-bridge -m 0644 services/scim-bridge/scim_bridge.py /opt/nexuscrm-scim-bridge/scim_bridge.py`.
3. Install the config: `mkdir -p /etc/nexuscrm-scim-bridge`, copy
   `deployments/scim-bridge/scim-bridge.env.example` to
   `/etc/nexuscrm-scim-bridge/scim-bridge.env`, fill it in, then
   `chown nexuscrm-scim-bridge:nexuscrm-scim-bridge /etc/nexuscrm-scim-bridge/scim-bridge.env`
   and `chmod 0600 /etc/nexuscrm-scim-bridge/scim-bridge.env`.
   `BRIDGE_EXEMPT_EMAILS` must include the bootstrap admin named in
   `BRIDGE_BOOTSTRAP_ADMIN` or the service refuses to start. Keep
   `BRIDGE_DEFAULT_PROFILE_NAME=SCIM Zero Access`; any other value is rejected
   so Helix onboarding cannot grant business permissions.
4. Front the bridge with a **TLS-terminating proxy** (nginx/ALB). The bridge
   listener is plain HTTP and must never be exposed on a network directly; set
   `BRIDGE_TLS_TERMINATED=1` if you bind it beyond loopback.
5. Install the unit: copy `deployments/scim-bridge/nexuscrm-scim-bridge.service`
   to `/etc/systemd/system/`, then
   `systemctl daemon-reload && systemctl enable --now nexuscrm-scim-bridge`.
   (The unit reads `/opt/nexuscrm-scim-bridge` and `/etc/nexuscrm-scim-bridge`
   and writes only its `/var/lib/nexuscrm-scim-bridge` state dir, so
   `ProtectHome=true` / `ProtectSystem=strict` hold with no home access.)

## Point Helix at it
In Helix, add a **Generic SCIM 2.0** target:
- base URL `https://<bridge-public-host>/scim/v2`
- API token `<client_id>.<client_secret>` (the connected-app credential)

Helix now creates users (SSO-only), updates attributes/manager, and deactivates
leavers through NexusCRM's own API. Deprovision is a deactivation (NexusCRM
forbids User delete and revokes sessions on deactivation); the exemption list
and circuit breaker guard against mass-deactivation mistakes.

## Retirement
When the upstream L1 SCIM AppService lands
(NexusCRM `docs/design/scim-l1-rebuild.md`), re-point Helix at it and remove this
deployment; NexusCRM core was never modified, so there is nothing to unwind
there.
