Skip to main content

WiseAI Realtor — Integrations (v1: honest connections hub) Expected Output Spec

⛔ STATUS: DRAFT — NOT APPROVED. CLAUDE.md Rule #17 (HARD GATE) is NOT satisfied.

Stage-1 agent research. Do not build the customer-facing screen until the founder approves and confirms the open items in a Stage-2 interview.

Sourced from (read-only, 2026-07-01): information-architecture.md §G ("Connect — Integrations / APIs / Connectors": CRM, DDF/MLS, calendar, email/SMS, Zapier/webhooks, API keys), design-direction.md (card-grid pattern: logo, status pill, Connect/Manage), competitive-analysis.md (FUB's 250+ integrations as the long-run benchmark — explicitly NOT the v1 bar), settings/feeds/page.tsx (the EXISTING honesty precedent for exactly this situation — DDF is "board-registration-gated… connected BY the WiseAI Agency team… routes to WiseAI for setup — it never fakes a self-serve connect flow"), rbac.ts (integrations:crm:edit capability already defined, currently unused by any screen), and a repo-wide search that found zero CRM/Zapier/per-tenant-Calendar connector code anywhere in churchwiseai-web.


0. Scope — what this spec covers, and what it does NOT

This spec covers Integrations v1: a single hub screen at /realtor/app/integrations that replaces the bare RealtorStub with a card per category, each showing either a REAL status (DDF/MLS only, in v1) or an honest "not self-serve — here's what it takes / who to contact" state.

Does NOT cover: any actual OAuth flow (CRM, Calendar, Zapier); any working "Connect" button that creates a live external connection; API key issuance (no public partner API exists yet for a key to authenticate against — issuing keys with nothing to call would be a feature with no use, not an MVP); webhook subscriptions (no event bus/outbox exists to fire them from). All of the above are explicitly out of scope and shown as "Coming soon" / "Contact WiseAI" states, not disabled-but-implied-imminent buttons.

Build posture: Mirror settings/feeds/page.tsx's existing pattern, do not invent a new one. That screen already solved this exact problem for DDF (a real capability that isn't self-serve) — Integrations v1 generalizes the same honest-status-card approach to the other categories the founder has publicly described (settings/page.tsx's own nav description: "Connect your CRM (Follow Up Boss, IXACT, kvCORE), calendar, email/SMS, and Zapier — plus API keys"). This is a read-and-explain screen, not a new integration platform.


1. The screen this spec governs + what it reads

Layout: a card grid (per design-direction.md's pattern), one card per category:

Cardv1 status shownSource of truth
DDF & MLSREAL status (Connected/Not connected)local_businesses.metadata.ddf.authorized — same read settings/feeds/page.tsx already does; card links to /realtor/app/settings/feeds rather than duplicating the explanation
CRM (Follow Up Boss, IXACT, kvCORE)"Not available yet — tell your WiseAI contact which CRM you use and we'll scope a 2-way sync"none (no connector exists)
Calendar (Google)"Not self-serve yet — your WiseAI team can wire calendar sync for your showings; ask your contact"none (existing google-calendar.ts is a single system-level connection, not per-tenant OAuth — do not claim it as connectable per-account)
Email & SMSInformational only: "Email and SMS are already built into your Lead Alerts and follow-ups — nothing to connect." Links to /realtor/app/settings/notificationsexisting lead-alerts infra (no new work; this card exists so the category isn't a dead end when the founder's own settings copy promises it)
Zapier / Webhooks"Not available yet"none
API keys"Not available yet — no public API to key against"none

Each non-connected card is honest about WHY (board-gated, not-yet-built, no-per-tenant-OAuth) rather than a generic "Coming soon" — matching the level of specificity settings/feeds/page.tsx already sets as the bar.

Reads: local_businesses.metadata.ddf.authorized (existing column, read via the same account_id → business_id resolution every other /realtor/app/* screen uses). Writes: none in v1 — this is a read-only status/explainer screen. (A "Request this integration" mailto/contact link is allowed — it is not a write to the DB, just a mailto: or a link to the existing support contact pattern used elsewhere in the dashboard.)

Demo tenant: Terry & Sheri Real Estate (…0c01, slug terry-and-sheri).


2. The AI-Bridge / honesty anchor

  • Never fake a self-serve connection. A "Connect" button that doesn't actually connect anything is the exact anti-pattern settings/feeds/page.tsx was already built to avoid for DDF ("the 'Connect DDF' CTA used to dead-end on /settings… it never fakes a self-serve connect flow" — its own docstring). Every card in this spec either shows a real status or explains, specifically, what's missing and who to ask.
  • No invented integration count. If a marketing surface elsewhere claims "50+ integrations" or similar, this screen must not be used to justify that claim unless the integrations are real — Content Studio/Integrations parity with actual product truth is the same honesty bar as pricing/product claims (CLAUDE.md Rule #13).

3. Role-based visibility

BucketRolesScope
Brokerage / team managementbrokerage_owner, broker_admin, team_admin (granted integrations:crm:edit)Full hub; sees all cards + can use the "Request this integration" contact link
Agent / ISA / supporteveryone elseFail-closed RealtorStub (mirrors website/page.tsx's pattern) — Integrations is an account-level admin surface, not a per-agent one, consistent with settings/page.tsx gating this nav item behind integrations:crm:edit already

Uses the already-defined integrations:crm:edit capability in rbac.ts (currently defined but unused by any screen) — no new capability needed.


4. Expected outputs

4.1 — DDF & MLS card (the one real status)

Should see: "Connected" (green) if metadata.ddf.authorized is true, else "Not connected yet" (neutral, not alarming red — this is board-gated, not a failure); a "Manage" link to the existing /realtor/app/settings/feeds page (no duplicated explanation — that page already owns the full story).

Should NOT see: a fabricated "Connected" status when the flag is false or missing; a second, inconsistent explanation of DDF that could drift from settings/feeds/page.tsx's copy over time.

Success: an owner glancing at Integrations sees, correctly, whether their MLS feed is live — and is routed to the ONE real place to act on it.

4.2 — Not-yet-available categories (CRM, Calendar, Zapier/Webhooks, API keys)

Should see: a clearly-labelled, non-alarming "Not available yet" state per category with a one-line reason and, where the founder has a real intake path, a "Tell us what you need" contact link; no fake "Connect" button, toggle, or progress bar implying work is already underway unless it genuinely is.

Should NOT see: any button that appears actionable but does nothing on click, or that opens a form that silently no-ops (the exact class of bug PR #1091 fixed for QR campaigns — this spec exists partly to prevent a repeat of that failure mode in a brand-new surface).

Success: an agent who wants Follow Up Boss sync knows immediately it isn't built yet and how to ask for it — never wastes ten minutes clicking a dead button.

4.3 — Email & SMS card (informational redirect)

Should see: a short note that email/SMS lead alerts already work via Settings → Lead alerts, with a direct link there — this card exists so settings/page.tsx's own promised copy ("email/SMS") isn't a dead end, without duplicating or re-implementing the notifications screen.

Should NOT see: a second, competing SMS on/off toggle here that could drift from whatever settings/notifications actually controls.

Success: no confusion about where email/SMS settings actually live.


5. Empty / loading / error states

StateExpected output
DDF status unknown (missing metadata / table not provisioned)Card reads "Not connected yet" (the honest default), not an error — matches settings/feeds/page.tsx's existing fallback behavior.
LoadingCard-grid skeletons, not a spinner.
Role lacks integrations:crm:editFail-closed RealtorStub message naming the missing permission.

6. Carried-forward constraints (consistent across the batch)

  • No realtor pricing shown in-product; gate by role/capability only.
  • Honest status only — every card reflects real, verifiable state or an honest "not built" explanation; never a placeholder implying imminent availability without founder confirmation of a real timeline.
  • Do not duplicate another screen's source of truth — DDF status and email/SMS settings each have exactly one owning screen; Integrations links to them rather than re-reading/re-explaining independently.

7. Accessibility (AODA → WCAG 2.1 AA)

  • Card grid: real heading semantics per card; status conveyed by text, not color-pill alone.
  • Links/contact actions: labelled buttons/links, not icon-only.
  • Contrast ≥4.5:1; reduced-motion honored.

8. Acceptance checklist (QA runs on the deployed URL)

Behavioural verification on wiseaiagency.com (real host) against the demo tenant (…0c01); never "build passes". Sample at ≥2 timepoints.

test.fixme('DDF & MLS card reflects the REAL metadata.ddf.authorized value, not a hardcoded status', () => {});
test.fixme('DDF & MLS card "Manage" link routes to /realtor/app/settings/feeds, no duplicated explanation on this page', () => {});
test.fixme('CRM / Calendar / Zapier / API-key cards show an honest "not available yet" state with a specific reason, no button that no-ops on click', () => {});
test.fixme('Email & SMS card links to /realtor/app/settings/notifications, introduces no competing toggle', () => {});
test.fixme('a membership without integrations:crm:edit sees the fail-closed RealtorStub, not the hub', () => {});
test.fixme('loading state renders skeletons, not a spinner; DDF-unknown state reads "Not connected yet", never an error banner', () => {});

9. Guardrails for agents building against this spec

  • Rule #17 not satisfied — do not build until founder approval.
  • Do NOT build any OAuth flow, API key issuance, or webhook subscription system in v1 — none of the underlying infra exists (confirmed by repo-wide search); building UI in front of nonexistent infra is the same honesty violation this spec exists to prevent.
  • Reuse, do not duplicate: DDF status source (settings/feeds/page.tsx's read of metadata.ddf.authorized) and the lead-alerts settings screen own their domains; Integrations links out rather than re-reading/re-explaining.
  • integrations:crm:edit already exists in rbac.ts — do not invent a new capability string.
  • If code diverges, update the spec first (founder approval), then the code.

End of spec. STATUS: DRAFT — NOT APPROVED. Open items for Stage-2: (1) confirm the "Tell us what you need" contact link's destination (mailto to founder? a support form?); (2) confirm whether Calendar should be omitted entirely from v1 rather than shown as "not available" (founder may not want to advertise a category with zero near-term plan); (3) confirm this spec's read-only v1 scope is acceptable, or whether the founder wants API-key issuance pulled forward as a genuinely useful v1.1 once outbound webhooks/leads-export has a real consumer.