Skip to main content

Admin Controls

Audience: Management, support, engineering (super-admin operators) · Where in app: Admin → Identity (super-admin only) · Plan availability: All plans (graph gated by active subscription)

The Identity Graph is super-admin owned. Customers don't see configuration knobs by default — the graph runs invisibly behind the AI's context. There are two levels of control: global defaults that apply to every tenant, and per-company overrides that replace them for one tenant. A separate subscription gate disables the graph for lapsed tenants regardless of config.

What it does

  • Lets super-admins set the global verification policy, which context sections appear, list caps, the custom intro, inbound-call verification, and form capture.
  • Lets super-admins override any of those for a single tenant.
  • Provides admin screens to browse Persons/Profiles/Form Submissions, inspect a session's assembled context, run maintenance sweeps, and work the CRM reconcile queue.
  • Gates the whole graph on an active subscription at runtime.

How it works

Global defaults — IdentityGraphDefaultsModel

A singleton document (key: 'default') in the identity_graph_defaults collection, edited under Admin → Identity → Config.

FieldWhatDefault (code)
enabledMaster switch for the graph platform-widetrue
enabled_sections[]Which sections appear in the AI prompt (identity, suspected_identity, enrichment, company_contacts, engagement, current_session, recent_pages, past_conversations, behavioral_signals, crm_state, bookings, form_responses, extracted_facts). Empty array = the default set (ALL_SECTIONS), which excludes company_contacts — the Apollo colleague list is opt-in only.[] (default set)
custom_introFree-form paragraph prepended to the AI prompt's identity block''
max_recent_pagesCap on recent pages5
max_past_conversationsCap on past conversations5
max_extracted_factsCap on extracted facts15
verification_policypermissive / moderate / strict / regulatedstrict
accept_inbound_call_verificationCaller-ID matches phone → instant verifytrue
capture_website_formsRun the form-intercept script on tenant sitestrue
updated_byLast admin to edit

Until the singleton is first saved, the service falls back to these same defaults (IdentityGraphConfigService.FALLBACK_DEFAULTS). Defaults are cached 60s — edits take up to a minute to propagate.

Per-company override

companies.identity_graph_allowed: bool // super-admin gate: may this tenant use the graph at all?
companies.identity_graph_use_custom_config: bool // true = use the override below instead of global defaults
companies.identity_graph_config: {
enabled, enabled_sections, custom_intro,
max_recent_pages, max_past_conversations, max_extracted_facts,
verification_policy, accept_inbound_call_verification, capture_website_forms
}

When use_custom_config is false (the default), the global defaults apply. When true, the override is merged over the defaults — fields missing from the override fall back to the global value, so a partial override is safe.

Subscription gate — IdentityGraphSubscriptionGateService

Independent of policy; a runtime check on every read/write path:

  • Tenant has an active, non-expired subscription → graph context assembled.
  • Trial-expired / cancelled → context not assembled (AI sees only the current session).
  • Cached 60s per company. Fail-open: if the subscription lookup itself errors, the gate returns available so a flaky read doesn't silently drop context for a paying customer.

Configuration & options

Admin screens (super-admin)

ScreenWhatBackend
Identity → ConfigEdit global defaultsGET/PUT /admin/identity/config/defaults
Identity → Config Form (per-company)Per-company override editorPUT /admin/identity/config/company/:id
Identity → PersonsBrowse global Persons (de-identified summary, searchable)GET /admin/identity/persons
Identity → Person DetailOne Person's full view + merge toolsGET /admin/identity/persons/:id
Identity → PersonProfilesFilter by company; view per-tenant slicesGET /admin/identity/person-profiles
Identity → Form SubmissionsAudit log of captured forms (filter by type/source/company)GET /admin/identity/form-submissions
Identity → Reconcile ConflictsReview queue: first-party identity vs a real GHL contact we declined to overwriteGET/POST /admin/identity/reconcile-conflicts*
Identity → MaintenanceCleanup / normalize / name-moderation / IP-signal backfill / trim-session-events (resumable, NDJSON progress) / retry poisoned Apollo domains (cleanup-apollo-records) / unlink enrichment identities / backfill chat human-message flag sweeps — dry-run first, background mode + pollingPOST /admin/identity/maintenance/*
Identity → Session DetailOne session's trust state, fingerprint + verified-signal display, suspected-identity markersfrontend/src/views/admin/identity/SessionDetail.vue
Session markdown previewInspect the assembled context for one sessionGET /admin/identity/sessions/:id/markdown-preview

Frontend repository: frontend/src/repositories/admin/identity.js; views under frontend/src/views/admin/identity/.

Default new-tenant posture

When a new company is created:

  • identity_graph_allowed: true (assuming the plan supports it)
  • identity_graph_use_custom_config: false → inherits global defaults
  • Default policy: strict (≥80 score threshold) + direct triggers
  • All sections enabled (empty enabled_sections)
  • Form capture on

Disabling per tenant

  • Disable entirely: identity_graph_allowed = false
  • Disable for ToS reasons: identity_graph_config.enabled = false with use_custom_config = true
  • Disable form intercept only: identity_graph_config.capture_website_forms = false
  • Maximum strictness (regulated): verification_policy = 'regulated' + accept_inbound_call_verification = false

Customer-side visibility

By default customer admins see nothing about the graph in their UI — it runs invisibly. A customer-facing Settings → Identity Graph screen exists and can be exposed for transparency (sections enabled, recent activity) if super-admin chooses; it is not on by default.

Behaviors & edge cases

  • Changes apply to future sessions only. Already-assembled context isn't recomputed; enabled_sections changes affect the next conversation, not historical ones.
  • 60s caches. Both the config defaults and the subscription gate cache for 60s — a freshly-cancelled tenant may briefly still get context, and a config edit may take up to a minute to show.
  • Override is a whole-config switch. use_custom_config replaces the config wholesale (with merge-over-defaults for missing fields); there's no per-field "inherit vs override" toggle in the data model.
  • Reconcile queue. When a first-party identity conflicts with a real (non-enrichment) GHL contact, the system flags it (reconcile_conflict_open) instead of overwriting; an admin overwrites, dismisses (optionally unlinking), or it auto-relinks if GHL's no-duplicate rule kicks in. All audited in identity_events[].
  • Maintenance sweeps are dry-run-first and resumable. trim-session-events streams NDJSON progress so a long apply doesn't hit the ingress idle timeout.

Plan & limits

All plans, gated by active subscription. Config is operational, not a paid tier. (Whether any plan tier restricts which sections/policies are allowed: verify with product.)

Technical implementation

  • Models: IdentityGraphDefaultsModel (identity_graph_defaults singleton), companies.identity_graph_* fields.
  • Services: IdentityGraphConfigService.getEffectiveConfig() (defaults overlaid with override, 60s cache), IdentityGraphSubscriptionGateService.isAvailable() (60s, fail-open).
  • Routes: backend/app/routes/adminIdentityRoutes.js (passport-gated), controller AdminIdentityController.
  • Frontend: frontend/src/repositories/admin/identity.js, views in frontend/src/views/admin/identity/.

See Identity Graph (subsystem) for the resolution chain and how config feeds it.

What Nox can tell you

  • Current policy + which company-specific overrides exist
  • Whether a specific tenant is gated by the subscription check
  • Section enablement
  • Recent identity events (verifications, conflicts, merges)

Nox can't change settings — super-admin edits directly.