to navigate
to select
esc to close
Core Concepts Intermediate

Constituents & CRM

Understand constituents, the shared login layer, role edges, consent, and the staff CRM added by the constituent identity layer

Overview

A constituent is the durable record of a person as known to one account — a donor, member, volunteer, event attendee, or newsletter subscriber. It is not a staff User and not a generic collection entry. Every role a person plays (attendee, member, donor, subscriber, volunteer) is a separate role-edge record layered onto one constituent, never a separate person table.

Constituents power the CRM screens under Content → Constituents and the public-facing member portal at /portal. They are account-specific: the same person interacting with two different Airogel sites gets two independent constituent records.

Shared identity vs. account CRM

Constituent identity is split into two layers:

  • Platform layer (shared across every account): Principal, verified email/phone/OAuth identifiers, sessions, and short-lived auth challenges and grants. This layer stores almost no profile data and is not tenant-scoped.
  • Account layer (tenant-scoped): Constituent, asserted or claimed contact identifiers, append-only consent, households, relationships, custom blueprint values, and role edges. Every row belongs to one account.

A constituent's principal_id is nullable — imported contacts and form submissions can exist as constituents long before anyone logs in. Only a verified platform identifier can authenticate or automatically claim a record; an asserted identifier (e.g. an email typed into a form) is never treated as proof of identity on its own.

Logging in: “Login with Airogel”

Constituents authenticate through a shared central auth origin rather than a per-account password. The account portal sends a signed handoff to the central auth host, which verifies the person by email magic link, SMS one-time code, Google, or Apple, then returns a short-lived, single-use authorization code bound to that account and callback URL.

After authentication the platform resolves the account record in order:

  1. Return the constituent already linked to this principal, if one exists.
  2. Match the principal's verified email/phone against existing account identifiers and claim that constituent.
  3. If nothing matches, apply the account's provisioning policy (see below).

Provisioning policy

Each account controls what happens for a first-time login with no matching record via the Constituents settings screen:

  • Open self-signup — a new constituent is created automatically.
  • Claim or approval only — nothing is created; the person sees a request-access screen instead.

New sites created from the starter template ship with open self-signup enabled and a Members navigation item pointing at /portal.

Role edges

Everything a constituent does is a separate edge record pointing back at the constituent, so one person can hold several roles without duplicate profiles:

  • Registrations — event attendance, optionally tied to a specific ticket (see Events & Registrations).
  • Memberships — status: pending, active, lapsed, canceled.
  • Donations — amount and date.
  • Subscriptions — newsletter/calendar follow, keyed by topic (distinct from billing subscriptions).
  • Volunteers — status: active, inactive.
  • Households — group constituents together (e.g. a family) via household memberships.

Consent

Consent is recorded as channel × purpose × state × timestamp, with optional proof of opt-in, and is append-only — a new row is written for every change rather than flipping a boolean. Direct update or delete is blocked at the model layer; only merges and account erasure can move or remove consent rows.

Staff CRM

The /content/constituents area supports:

  • Search and profile editing, including asserted contact identifiers
  • Consent recording and activity history
  • CSV import (admin-only, row-transactional; skips rows whose identifiers already exist)
  • Duplicate detection and merge review

Merging two records is transactional: role edges, identifiers, consent, relationships, households, and custom field values move to the kept record; the kept record wins on conflicting scalar/custom-field/primary-identifier/avatar values; the merged-away record becomes an archived tombstone that redirects to the survivor. Merges between two records that are each linked to a different principal are refused.

Form ingestion

Any form can be configured to fold its submissions into the constituent layer in addition to writing its normal collection entry. Enable Constituent ingestion on the form and map the email, phone, given name, and family name fields; optionally record consent from a checkbox field. An existing identifier match folds the submission into the known person; otherwise a new prospect constituent is created. Submitted contact values are stored as asserted identifiers — submitting a form does not verify anyone's identity.

Starter sites ship with constituent ingestion already enabled on the default newsletter, contact, and event signup forms.

What's not exposed over MCP

Constituent and CRM data is intentionally not available through the MCP tool set or the public REST API — it contains personal data and consent records that should only be managed through the audited staff CRM UI or the constituent's own self-service portal. Events, tickets, and published content remain available through MCP as usual.