> ## Documentation Index
> Fetch the complete documentation index at: https://docs.myfundingmachine.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Onboarding engine operator pulse

# Onboarding Engine — Operator Pulse integration

Last updated: 2026-07-20

The Onboarding Engine is an autonomous runtime (Hermes, `~/.hermes` on the mini —
**not** in this repo) that tracks operator health on GHL pipeline cards. This app
supplies its two health signals over a read-only HTTP endpoint. This doc records
the contract, the GHL surface the engine writes to, and the go-live state.

## Signals served by this app

```
GET https://brainy-crocodile-746.convex.site/agent/operator-pulse?locationId=<id>
Authorization: Bearer <AGENT_PULSE_TOKEN>
```

Response `200`: `{ "locationId": string, "lastLoginAt": number|null, "lastCreditPullAt": number|null }`
(`401` on missing/wrong token or when `AGENT_PULSE_TOKEN` is unset — fail closed; `400` on missing `locationId`.)

* **`lastLoginAt`** — `ghlInstallations.lastSeenAt`, stamped fire-and-forget on every
  operator app open by the login bootstrap routes (`app/api/auth/validate-sso`,
  `app/api/auth/location-session`) via `lib/operatorLastSeen.ts` →
  `internal.ghlInstallations.touchInstallationLastSeen`.
* **`lastCreditPullAt`** — newest `creditReportRequests.createdAt` per location
  (`by_location_createdAt` index, bounded `take(1)`).

Implementation: `convex/agentPulse.ts` + route registration in `convex/http.ts`.
Tests: `tests/agentOperatorPulse.test.ts` (auth matrix, payload shape),
`tests/operatorLastSeenStamp.test.ts` (login-route wiring).

`AGENT_PULSE_TOKEN` was generated and set on the prod Convex deployment
(`brainy-crocodile-746`) on 2026-07-14. Never commit it, and never print it to a
terminal or agent transcript (AGENTS.md Safety: printing/exposing secrets is
prohibited). To provision the engine, pipe it straight into `~/.hermes/.env`
without echoing the value (prod deploy key):

```sh theme={null}
printf 'ENGINE_PULSE_TOKEN=%s\n' "$(bunx convex env get AGENT_PULSE_TOKEN)" >> ~/.hermes/.env
```

Verify presence without exposing it: `grep -c '^ENGINE_PULSE_TOKEN=' ~/.hermes/.env`.

## GHL surface the engine writes to

Funding Machine agency, location `ReoQmuh4ooNuHeE5stlj` (this is a separate agency
from the Leadbuilt admin location, `GHL_ADMIN_LOCATION_ID` — don't confuse the two).

* Pipelines: `Onboarding` (`Pfnl7aNXOFvQxzjYvrjj`) and `Retention` (`M1qJVId6EtPGaXq0FGeG`).
* Opportunity custom fields (per-card):
  * `Last App Login` (`Vk5td7RYmFDis48mabBQ`, DATE) ← pulse `lastLoginAt`
  * `Last Credit Pull` (`7DtlDwTpCbIleN8FODEs`, DATE) ← pulse `lastCreditPullAt`
  * `Product Location ID` (`cokiropDHpj8atwrDrqF`, TEXT) — **mapping field**: the
    operator's app locationId the engine polls the pulse for. A card without it
    gets no login/credit data even in live mode.
  * `Slack Channel ID` (`ACD1FcIE6IfXaje1wnkH`, TEXT) — activates Slack-kick per card.

## Engine-side configuration (mini, `~/.hermes/.env`)

* `ENGINE_PULSE_URL=https://brainy-crocodile-746.convex.site`
* `ENGINE_PULSE_TOKEN=<AGENT_PULSE_TOKEN>` — set via the no-echo command above.
* `ENGINE_MODE=live` + `ENGINE_LIVE_ACTIONS=<allowlist>` — actions not on the
  allowlist stay dry-run. Internal-only go-live is `ENGINE_LIVE_ACTIONS=set_field`
  (GHL field writes live; engine-initiated emails / client-facing notifications
  stay suppressed until explicitly added). The allowlist only gates what the
  engine itself sends — it cannot suppress GHL's own automations. **Keep
  `move_stage` off the allowlist** until the stage-change workflows/automations
  on the Onboarding and Retention pipelines are audited: a stage move can trigger
  GHL workflows that send client-facing emails/SMS regardless of engine mode.
* GHL auth: a dedicated location-scoped Private Integration Token for
  `ReoQmuh4ooNuHeE5stlj` (confirmed in place 2026-07-20).

## Go-live checklist state (2026-07-20)

* [x] Convex functions + login stamping deployed and verified in prod (PR #1205;
  the post-merge deploy race was recovered manually on 2026-07-14).
* [x] `AGENT_PULSE_TOKEN` set on prod; endpoint verified fail-closed and serving data.
* [x] Login stamping confirmed at scale (125/155 installs stamped within the first week).
* [x] 5 engine dry-run TEST cards deleted from Onboarding/Retention pipelines.
* [x] Dedicated location-scoped PIT confirmed for the engine.
* [ ] Flip `ENGINE_MODE=live` + `ENGINE_LIVE_ACTIONS=set_field` on the mini.
* [ ] Audit the stage-change workflows/automations on the Onboarding and Retention
  pipelines (confirm none send client-facing messages, or explicitly gate them),
  then add `move_stage` to `ENGINE_LIVE_ACTIONS`.
* [ ] Fill `Product Location ID` (and `Slack Channel ID` where wanted) on the real cards.

Known data caveat: the Kevin Hill card (test account, opportunity
`TZHO5gDZuvsYZSkzo8EH`) carries a synthetic `Last App Login = 2026-07-20` written
manually while testing the pipe end-to-end; the location's `lastSeenAt` was stamped
via `ghlInstallations:touchInstallationLastSeen` rather than a real app open.
