HV Tech Stack Chapter 02 · Data
Where each piece of data lives. Who owns it. How it moves. Every Dataverse table and every WordPress CPT by name.
I.
Part One
The hub is Dataverse. The spoke is WordPress. Data flows in lanes.
Dataverse is master. WordPress mirrors.
WordPress captures. Dataverse stores.
MaintainX is master for trade data. Dataverse mirrors work orders. WordPress never stores work orders; it reads scoped views through a server-side REST proxy.
Constant Contact holds the subscriber list. Dataverse holds the opt-in record. Power Automate writes to Constant Contact after Sarah approves.
II.
Part Two
Every table below is a Dataverse row type. Names follow a
hv_ prefix to keep them isolated inside the environment.
The master resident record. Every other operational table links here.
| Column | Type | Notes |
|---|---|---|
resident_id | GUID | primary key |
first_name | text | |
last_name | text | |
login_email | text | unique; syncs to wp_users.user_email |
secondary_emails | text (multi) | display only; never used for auth |
phone | text | |
status | choice | Active, Pending, Suspended, Moved-out |
created_on | datetime | |
approved_by | lookup to hv_staff |
The 2,580 dwellings. One row per unit.
| Column | Type | Notes |
|---|---|---|
unit_id | GUID | primary key |
unit_number | text | canonical display |
condo_association | choice | 1 through 24 |
model | text | one of 13 HV models |
status | choice | Owned, For Sale, Vacant, Rental |
The join table. Solves multi-unit owners.
| Column | Type | Notes |
|---|---|---|
link_id | GUID | primary key |
resident_id | lookup | |
unit_id | lookup | |
role | choice | Owner, Co-owner, Tenant, Authorized contact |
start_date | date | |
end_date | date | null if current |
Approved vehicles per unit. Drives barcode and gate access records.
| Column | Type | Notes |
|---|---|---|
vehicle_id | GUID | primary key |
unit_id | lookup | |
make | text | |
model | text | |
plate | text | |
barcode | text | |
status | choice | Active, Expired, Pending |
Snowbird and temporary mail-forwarding.
| Column | Type |
|---|---|
address_id | GUID (primary key) |
resident_id | lookup |
line1, line2, city, region, postal_code | text |
start_date, end_date | date |
File-of-life data. Opt-in per resident.
| Column | Type | Notes |
|---|---|---|
contact_id | GUID | primary key |
resident_id | lookup | |
name, relationship, phone | text | |
notes | text | medical allergies, access notes |
Governance queue. Carol approves from Teams.
| Column | Type | Notes |
|---|---|---|
request_id | GUID | primary key |
resident_id, unit_id | lookup | |
category | choice | Exterior, Landscape, Structural, Other |
description | text | |
attachments | file | |
status | choice | Submitted, In review, Approved, Denied, Withdrawn |
decision_notes | text | |
decided_by | lookup to hv_staff | |
submitted_on, decided_on | datetime |
Routes to Nate.
| Column | Type | Notes |
|---|---|---|
request_id | GUID | primary key |
resident_id, unit_id | lookup | |
charger_model, panel_location, notes | text | |
status | choice | Submitted, Site visit, Approved, Denied, Installed |
Annual or periodic. Bulk data.
| Column | Type |
|---|---|
survey_id | GUID (primary key) |
unit_id | lookup |
resident_ids | lookup (multi) |
primary_residence | bool |
season_start, season_end | date |
submitted_on | datetime |
Tracks newsletter consent before writing to Constant Contact.
| Column | Type | Notes |
|---|---|---|
optin_id | GUID | primary key |
resident_id | lookup | |
email | text | |
list_name | text | e.g., "e-Bulletin" |
status | choice | Requested, Approved, Synced, Unsubscribed |
approved_by | lookup to hv_staff |
Upstream edit requests. Appends or updates pending approval.
| Column | Type | Notes |
|---|---|---|
change_id | GUID | primary key |
resident_id | lookup | |
field | choice | login_email, phone, secondary_email, address |
old_value, new_value | text | |
status | choice | Pending, Approved, Denied, Auto-applied |
Public "Request Access" submissions.
| Column | Type | Notes |
|---|---|---|
request_id | GUID | primary key |
first_name, last_name, email, claimed_unit | text | |
status | choice | Submitted, Verified, Approved, Denied |
A thin mirror of MaintainX work orders. Dataverse caches them for reporting. WordPress still reads live from the REST proxy.
| Column | Type | Notes |
|---|---|---|
work_order_id | text | MaintainX ID (primary key) |
unit_id | lookup | |
title | text | |
status | choice | Open, In progress, On hold, Closed |
priority | choice | |
created_on, closed_on, last_synced | datetime |
Staff directory. Scopes who can approve what.
| Column | Type | Notes |
|---|---|---|
staff_id | GUID | primary key |
entra_object_id | text | ties to SSO |
name | text | |
role | choice | Data manager, Governance liaison, Comms, Ops, Library, Read-only |
tier | choice | 1, 2, 3 |
Every Power Automate run logs here. Used to break loops and to audit.
| Column | Type | Notes |
|---|---|---|
log_id | GUID | primary key |
flow_name | text | |
direction | choice | WP-to-DV, DV-to-WP, MaintainX-to-DV, DV-to-CC |
payload_hash | text | |
initiated_by | text | service account name |
status | choice | Success, Skipped (loop guard), Failed |
timestamp | datetime |
III.
Part Three
Each post type maps to a hub. Each field group maps to a post type, a user profile, or a taxonomy.
| CPT | Hub | Purpose | Public? |
|---|---|---|---|
announcement | Residents | Alerts, bulletin items | gated |
bulletin_pdf | Residents | Archived bulletins | gated |
form_submission | Residents | Form capture wrapper | gated |
facility | Living Here | One record per facility | public |
club | Living Here | One record per club | public |
activity | Living Here | Day trips, classes, events metadata | public |
board_meeting | Governance | Agenda, minutes, packet, video | public |
committee | Governance | Per-committee record | public |
condo | Governance | One record per condo association | public |
financial_doc | Governance | Audit, budget, statement | public |
buyer_page | Buyers | About, homes, floor plans, FAQ | public |
staff_contact | Contact | Directory entry | public |
Native page and post stay enabled for the editorial blog
and one-off static pages. Gutenberg disables on every CPT above.
Each group attaches to a CPT, to the user profile, or to a taxonomy.
associated_units (repeater or relationship),
secondary_emails (display only),
directory_opt_in (name, unit, phone, email checkboxes),
magic_link_last_sent (throttle guard),
dataverse_resident_id (sync key).
meeting_date, committee_of_record taxonomy,
agenda_pdf, minutes_pdf, packet_pdf,
video_url, last_updated.
charter_pdf, open_or_closed,
chair_contact, meetings (relationship to board_meeting).
hours (repeater of day/open/close), address,
reservation_form_id, photo_gallery, policies_pdf.
category taxonomy, meeting_day, meeting_time,
location (relationship to facility), contact, how_to_join.
association_number (1 to 24), board_members repeater,
minutes_archive repeater (date, pdf), last_updated.
doc_type (Audit, Budget, Statement, Insurance),
period (e.g. "2025-2026"), pdf, release_date.
alert_level (Routine, Urgent, Emergency),
expires_on, target_audience (All, Condo N, Committee).
form_type (maps to Dataverse request table),
payload_json, dataverse_id, submitted_by.
alert_type on announcementcommittee_type on committee and board_meetingfacility_category on facilityclub_category on clubfiscal_year on financial_docIV.
Part Four
The core shape of the relational model, and the source-of-truth calls that drive every flow.
The core shape:
hv_residents 1---* hv_resident_units *---1 hv_units
hv_residents 1---* hv_alternate_addresses
hv_residents 1---* hv_emergency_contacts
hv_residents 1---* hv_variance_requests *---1 hv_units
hv_residents 1---* hv_ev_charger_requests *---1 hv_units
hv_residents 1---* hv_email_optins
hv_residents 1---* hv_contact_change_requests
hv_units 1---* hv_vehicles
hv_units 1---* hv_work_orders (mirror of MaintainX)
hv_staff 1---* hv_variance_requests (via decided_by)
hv_staff 1---* hv_email_optins (via approved_by)
See Diagrams for the rendered ER picture.
| Data point | Master | Mirror | Notes |
|---|---|---|---|
| Resident name, email, phone | Dataverse | WordPress | Changes start as requests upstream |
| Unit assignments | Dataverse | WordPress user ACF | Multi-unit resolved here |
| Work orders | MaintainX | Dataverse, WordPress live-read | Never stored in WP MySQL |
| Variance status | Dataverse | WordPress (read-only dashboard) | |
| Newsletter subscribers | Constant Contact | Dataverse opt-in record | |
| Editorial content | WordPress | none | Announcements, clubs, facilities, meetings |
| Vehicles and barcodes | Dataverse | none (staff only) | |
| Emergency contacts | Dataverse | none (staff only) |
wp_users, wp_usermeta, wp_posts, wp_postmeta, and ACF tables.