HV Tech Stack Chapter 04 · Auth

Auth.

How residents log in. How staff log in. How the old roster moves over. Who sees what.

Contents

In this chapter

  1. i.Magic-link authenticationI
  2. ii.Provisioning and unit bindingII
  3. iii.Staff authenticationIII
  4. iv.Who sees whatIV

I.

Part One

Magic-link authentication

Residents skew 55 and older. Password fatigue is the top ticket at peer HOAs. The right tool is a passwordless magic link.

The flow

  1. Resident lands on /account or hits a gated URL.
  2. They enter their email.
  3. WordPress checks the email against wp_users.
  4. If matched, WordPress generates a one-time token, stores the hash, and sends the link through SendGrid or Mailgun.
  5. Resident clicks the link. WordPress validates the token, starts the session, and redirects to the destination.
  6. Token expires after 15 minutes or first use.

Plugin choice

The right plugin is Passwordless Login by Cozmoslabs (free) or Magic Login Pro (freemium). Both ship a clean magic-link flow. Both pair with ACF, BuddyPress, and WP Mail SMTP.

Gemini named "Solid Security" as a magic-link option. That name is a hardening plugin (formerly iThemes Security). It does not issue magic links. See Operations for the full correction list.

Mail delivery

Magic links fail silently if mail lands in spam. The system is not optional.

Throttling

ACF magic_link_last_sent on every user. WordPress blocks a second link within 60 seconds. Prevents flood attacks on a known address.

II.

Part Two

Provisioning and unit binding

Import from HOA-sites. Bind each resident to their units. Every logged-in resident sees only their own data.

HOA-sites export

The current platform holds the master list. The plan assumes CSV export. Confirm this with the HOA-sites vendor before the migration phase. The exact export format drives the importer.

Target shape for the importer:

ColumnMaps to
emailwp_users.user_email, hv_residents.login_email
first_namehv_residents.first_name
last_namehv_residents.last_name
unit_numberhv_units.unit_number via join
roleOwner, Co-owner, Tenant

Import tool

WP All Import handles the CSV-to-WordPress step. A Power Automate flow picks up the imported rows and creates matching Dataverse hv_residents rows.

  1. Import units into hv_units from the condo association roster.
  2. Import residents into hv_residents.
  3. Build hv_resident_units join rows from the CSV's unit references.
  4. Let HV-DV-Sync-ResidentRoster provision the WordPress users.
  5. Send a one-time "your account is ready, click to log in" email. First click is the first magic link.

New resident requests

No open registration. The /account/request form creates hv_access_requests. Office staff verifies against the community roster. On approval, Power Automate creates the hv_residents record. The downstream flow provisions the WordPress user.

Unit binding

Single-unit owner
wp_usermeta.dataverse_resident_id maps to hv_residents.resident_id. ACF associated_units holds one row. Work-order proxy, variance dashboard, and vehicle list all filter by that one unit.
Multi-unit owner
ACF associated_units holds N rows, one per unit. The proxy queries MaintainX for the array and merges results. Variance dashboard shows a unit selector. Forms default to the primary unit but allow a dropdown.
Tenant vs owner
hv_resident_units.role drives permissions. Tenants see work orders for their unit. They do not see variance history or vehicle records. ACF can_submit_variance checkbox on each row governs the front-end.

Contact info changes

The Request Pattern governs every change. Residents cannot mutate wp_users.user_email directly.

III.

Part Three

Staff authentication

Staff uses Entra ID. Three tiers. Four WordPress roles.

Three tiers

Builder tier (Premium)
Users: Nate plus a small circle. Access: Power Apps, Dataverse schema, Power Automate flow library, WordPress admin. License: Power Apps Premium plus Dataverse.
Approver tier (Standard)
Users: Carol, Sarah, other liaisons. Access: Teams Adaptive Cards for approvals; WordPress admin scoped to their hub. License: standard M365.
Read-only tier (Standard)
Users: broader staff, library volunteers. Access: Excel files on SharePoint; selected WordPress admin for their content niche. License: standard M365.

WordPress roles

RolePermissions
ResidentRead gated pages; submit forms; edit own profile within the Request Pattern
Content EditorEdit announcements, clubs, facilities, meetings for their hub
Data ManagerFull admin; Nate's role
PendingCan log in only to see the "account awaiting approval" page

Gated CPTs enforce role checks in template_redirect. Public CPTs render without auth.

Approvals without Power licenses

The cards-only flow is intentional. Carol and Sarah never open Power Apps. The service account holds the premium license and posts on their behalf. Microsoft's license model allows this for occasional use by a human approver.

Session and cookie rules

IV.

Part Four

Who sees what

Directory privacy, hard cases, and the full permission matrix on one page.

Directory privacy

The resident directory is opt-in per field. Default is everything hidden.

Staff see everything. Residents see only opted-in rows. The ACF directory_opt_in field cluster drives this.

Lost accounts and hard cases

Permission matrix

Surface Public Pending Resident Content Editor Data Manager
/yesyesyesyesyes
/buyers/yesyesyesyesyes
/residents/noawaiting approvalyesyesyes
/governance/mostly publicyesyesyesyes
/living-here/yesyesyesyesyes
/contact/yesyesyesyesyes
/wp-admin/nononoscopedfull
Power Appsnonononoyes (tier 1)
Teams cardsnononoyesyes
Excel on SharePointnononoreadread/write

Out of scope