Skip to content

feat(partners): wire the RPO/MSP application funnel end-to-end#241

Merged
thecelestialmismatch merged 3 commits into
mainfrom
claude/complete-implementation-standard-ipql5k
Jul 22, 2026
Merged

feat(partners): wire the RPO/MSP application funnel end-to-end#241
thecelestialmismatch merged 3 commits into
mainfrom
claude/complete-implementation-standard-ipql5k

Conversation

@thecelestialmismatch

Copy link
Copy Markdown
Owner

Description

The RPO/MSP application backend — POST /api/partners/applypartner_applications insert + founder alert + branded welcome email, plus migration 005 — has existed and been tested for months, but no UI ever called it. Every CTA on /partners and /partners/kit pointed at the generic /contact form, so the Stage-1 channel #1 funnel never ran: no RPO landed in partner_applications, no founder alert fired, no welcome email sent. The classic "capability with no caller" dangling thread (tasks/lessons.md, 2026-07-04).

This ships the missing caller and closes the loop:

  • app/partners/apply/PartnerApplyForm.tsx — honest-fetch application form. Payload maps 1:1 to the route's zod schema (name, company, email, partnerType, numeric clientCount, message). Shows success only on res.ok && data.success; degrades to a direct, monitored inbox (contact@houndshield.com) on any failure — never a fake success (the 2026-07-12 lead-shredder pattern).
  • app/partners/apply/page.tsx — SEO'd application page (canonical + OG, sitemap entry), offer recap ($299 wholesale · 14-day local · no exclusivity · local-only), and a "what happens next" strip mirroring the welcome email's two-business-day promise.
  • Repointed all three partner CTAs (/partners ×2, /partners/kit) from /contact/partners/apply.

Channel doctrine preserved: the form states the C3PAO exclusion (32 CFR Part 170 — assessors cannot refer tools to clients they assess). No fabricated metrics, no sub-$499 pricing, no second grid.

Fixes # (no tracked issue — dangling-thread cleanup surfaced during the OODA session)

Type of change

  • New feature (non-breaking change which adds functionality)
  • Documentation update

Jordan's Test Plan (CMMC Buyer — required before merge)

  • npm run build passes in compliance-firewall-agent/ (exit 0; /partners/apply prerenders static ○, /api/partners/apply wired ƒ)
  • No hardcoded secrets (API keys, license keys, passwords)
  • Local-only data boundary preserved — this is a marketing/lead surface; no prompt content or CUI touched
  • Compliance patterns untouched — proxy/patterns/ not modified
  • SPRS scoring logic unchanged
  • If Supabase referenced: partner_applications is a marketing lead table (name/company/email), never CUI

Verification

  • npm run build succeeds locally (exit 0)
  • Linter passes — eslint . = 0 errors; new files 0 warnings
  • Test suite passes — full suite 1497/1497 (+18 new)
  • tsc --noEmit = 0

New guards (+18):

  • PartnerApplyForm.test.tsx — validation, exact payload shape (numeric clientCount, omitted when blank), success-only-on-ok, honest fallback on both failure modes, C3PAO exclusion copy.
  • apply-funnel-contract.test.ts — source-level regression guard: the route has a caller, the page renders the form, no partner CTA falls back to /contact, page in sitemap, no-fake-success pattern holds.

Checklist

  • My code follows the style guidelines of this project (design-system tokens, honest-fetch form pattern mirrored from /contact)
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (docs/PARTNER-APPLICATION-FUNNEL.md)
  • No TypeScript any types added in compliance-critical code

🤖 Generated with Claude Code

https://claude.ai/code/session_019737b2ENNDFaA7gPyg5hJo


Generated by Claude Code

The application backend (POST /api/partners/apply → partner_applications
insert + founder alert + branded welcome email, migration 005) had existed
and been tested for months, but no UI ever called it: every /partners and
/partners/kit CTA pointed at the generic /contact form. So the Stage-1
channel #1 funnel never ran — no RPO landed in partner_applications, no
founder alert fired, no welcome email sent. The classic "capability with no
caller" dangling thread.

This ships the missing caller:

- app/partners/apply/PartnerApplyForm.tsx — honest-fetch application form.
  Payload maps 1:1 to the route's zod schema (name, company, email,
  partnerType, numeric clientCount, message). Shows success only on
  res.ok && data.success; degrades to a direct, monitored inbox on any
  failure — never a fake success (the 2026-07-12 lead-shredder pattern).
- app/partners/apply/page.tsx — SEO'd application page (canonical + OG,
  sitemap entry), offer recap, and a "what happens next" strip mirroring
  the welcome email's two-business-day promise.
- Repointed all three partner CTAs (/partners x2, /partners/kit) from
  /contact to /partners/apply.

Channel doctrine preserved: the form states the C3PAO exclusion
(32 CFR Part 170 — assessors cannot refer tools to clients they assess).

Guards: +18 tests. PartnerApplyForm.test.tsx (validation, exact payload
shape, success-only-on-ok, honest fallback on both failure modes, C3PAO
copy) and apply-funnel-contract.test.ts (regression guard: the route has a
caller, no partner CTA falls back to /contact, page in sitemap, no-fake-
success pattern holds).

tsc 0 · lint 0 (new files) · full suite 1497/1497 · build clean.
Docs: docs/PARTNER-APPLICATION-FUNNEL.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019737b2ENNDFaA7gPyg5hJo
@vercel

vercel Bot commented Jul 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
compliance-firewall-agent Ready Ready Preview, Comment Jul 22, 2026 9:47pm

@supabase

supabase Bot commented Jul 22, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project qifynzuyrdxmxlumpsrq because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

The Proxy Build & Test job was red on main (predates this PR's funnel work,
which touches no proxy files). Root cause: dependabot bumped better-sqlite3
12 → 13 (#232); v13's native binding requires Node >=22, but the proxy CI
job pinned Node 20, so `npm ci` warned EBADENGINE and vitest's worker forks
crashed on import ("Worker exited unexpectedly") — 0 tests ran.

Fix: set the proxy job's node-version to 22 and correct proxy/package.json
`engines.node` to `>=22.0.0` so the declared engine matches the dependency's
actual requirement (was lying at >=20). Validated locally on Node v22.22.2:
proxy tsc 0 · tests 61/61 · bench p99 1.049ms (<10ms contract) · build 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019737b2ENNDFaA7gPyg5hJo

Copy link
Copy Markdown
Owner Author

Proxy Build & Test went red on the first commit, but the cause was pre-existing on main, not this PR — the funnel work touches no files under proxy/.

Root cause: dependabot's better-sqlite3 12 → 13 bump (#232) landed on main; v13's native binding requires Node ≥22, but the proxy CI job pinned Node 20, so npm ci warned EBADENGINE and vitest's worker forks crashed on import ("Worker exited unexpectedly") — 0 tests ran.

Since it was blocking this PR from reaching all-green, I fixed it here (7019c47): bumped the proxy CI job to Node 22 and corrected proxy/package.json engines.node to >=22.0.0 so the declared engine matches the dependency's real requirement. Validated locally on Node v22.22.2 — proxy tsc 0 · tests 61/61 · bench p99 1.049 ms (<10 ms contract) · build 0. This also un-reds the same check on main.


Generated by Claude Code

Continuity update: mark the funnel build gate green, note the PR #241 draft +
Vercel preview, and log the pre-existing Proxy Build & Test fix so the next
session starts accurate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019737b2ENNDFaA7gPyg5hJo
@thecelestialmismatch
thecelestialmismatch marked this pull request as ready for review July 22, 2026 21:46
@thecelestialmismatch
thecelestialmismatch merged commit 002c97d into main Jul 22, 2026
11 checks passed
thecelestialmismatch pushed a commit that referenced this pull request Jul 22, 2026
Retrospective continuity note (todo log only): PR #241 merged to main as
squash 002c97d — the RPO/MSP application funnel is live on houndshield.com,
and the proxy Node-22 fix flips main's CI red→green (had been failing since
the better-sqlite3@13 bump #232). Updates the "next action" line to reviewing
partner_applications. No code change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019737b2ENNDFaA7gPyg5hJo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants