frameworkveteran-firm-directory-build-plan-v2 · v11099:anthropic-cowork-vetdir12026-08-12served from databaseAll documents

FedM8 Veteran-Representative Directory - Build Plan v2 (low-risk configuration)

FedM8 Veteran ↔ Representative Directory — build plan v2

Slug: fedm8 · Lane: gated · Supersedes: build plan v1 · Date: 2026-08-12 Mandate change: v1 was scoped for viability. v2 is scoped for minimum litigation risk.

BLUF

A disabled veteran comes to FedM8, sees every VA-accredited representative who can help with their claim, is told first that free help exists, compares them on a Google star rating and a FedM8 rating written by other verified veterans, picks one by name, and contacts that one directly. Accredited attorneys and claims agents can pay a flat monthly fee to appear in a labeled Sponsored block on search results.

Four things from v1 are removed, not deferred. Each removal closes a specific litigation theory rather than mitigating it.

RemovedWhyAuthority
Unaccredited claim consultantsRemoves the state-AG theories that arise from who we list and promote. It does not remove UDAP exposure for FedM8's own conduct, which no listing policy can. The accredited roster is close to the whole market anyway38 CFR 14.629; TX AG v. VA Claims Insider ($6.8M, Jan 2026); AZ AG v. VetLink (~$2M, May 2026)
Pay-per-leadRetention-adjacent pricing is felony-adjacent in TX/LA and disciplinary everywhereTex. Penal §38.12; La. R.S. 37:219; NJ ACPE Op. 741
The lead inbox / any intake routingThis was the decisive finding. Routing a consumer's inquiry to a subset of attorneys is a referral, and California's new §6156.5 gives any person a claim for $5,000–$100,000 per violation plus feesCal. B&P §6155, §6156.5 (SB 37, Ch. 645, Stats. 2025); Jackson v. LegalMatch (2019) 42 Cal.App.5th 760
Sponsored ads on a non-paying professional's profile pageIllinois IRPA carries a $1,000 statutory minimum per violation plus fees; × a class of listed attorneys is existential. Vrdolyak blessed the practice, but Avvo and Whitepages both paid to settle adjacent claims765 ILCS 1075; Cal. Civ. Code §3344; Lukis v. Whitepages ($4M+ settlement)

What is added: a full consumer-health-data compliance layer, a person-first data model that deletes the hardest engineering problem in v1, and bound insurance before launch.


1. The single most important design decision

Never route a veteran's inquiry. In California, "the act of referring is complete when [the site] routes a potential client to attorneys who match the geographic location and area of practice" (Jackson, and the court expressly rejected any screening or judgment requirement). A lead inbox that takes a description of the veteran's situation and delivers it to the firms that pay us is, on that holding, operating an unregistered lawyer referral service. Since SB 37 that is not merely a regulatory problem — it is a private cause of action with a $5,000 floor and a $100,000 ceiling per violation, plus attorney's fees.

§6156.5, operative text (B&P, added by SB 37, Ch. 645, Stats. 2025): a violation of §6155 gives rise to an action by any person for statutory damages of not less than $5,000 and not more than $100,000 per violation, or three times actual damages, plus attorney's fees and injunctive relief, independent of any agency action. There is no construing case law.

Honesty about the authority. Jackson footnote 7 distinguishes a site that sends consumers "to all lawyers who share a particular geographic location and expertise, as a phonebook or telephone directory might" from one routing them to "a subset of attorneys." That is dicta in a footnote, not a safe harbor, and Texas Ethics Op. 573 binds Texas lawyers rather than platforms. Together they describe the conservative architecture below; they do not guarantee it wins. This is why a written California opinion is a Phase 5 gate (§8), not a generic pre-launch review — and the specific question counsel must answer is whether a paid Sponsored block responsive to a geography-plus-practice-area query is itself "routing to a subset," which is the residual risk this design does not fully eliminate.

The architecture:

  1. Open enrollment. Every VA-accredited representative in a state appears. No caps, no

panels, no waitlists, no exclusivity, no territory limits. Paying only changes placement in a labeled block, never who is shown.

  1. Search returns all matching representatives, each named, with firm and office city.
  2. The veteran picks a named person first. Contact is a form on that person's profile

that delivers only to that person. There is no site-wide intake questionnaire, no "describe your situation and we'll find someone," no fan-out, no matching.

  1. No recommendation vocabulary anywhere — no "best," "top," "matched," "screened,"

"vetted," "recommended," "pre-qualified," or satisfaction guarantee.

Corollaries: the lead table from v1 is deleted from the schema. Contact-form content is delivered and not retained beyond a transient delivery record (timestamp, firm id, no message body). We never learn what the veteran's claim is about from a contact form.

Florida is a checklist, not an exclusion. On the plain text of Bar Rule 4-7.22(b)(3), "publishing in any media a listing of lawyers or law firms together in one place" makes every directory a qualifying provider. So: file the annual report naming participating lawyers, display each lawyer's bona fide office city at the point of connection, list at least four lawyers from four different firms, no fee-splitting, respond to bar counsel within 15 days, never imply Bar endorsement. Ohio requires registration under Gov.Bar R. XVI only if the site functions as a referral service — under §1 above it does not, and the file records why.


2. Who is listed

Only VA-accredited representatives, drawn from the VA OGC roster:

KindListedMay subscribeNotes
VSO representative / recognized VSOyes, freenoCannot charge fees at all (38 CFR 14.636(b)). Shown first, always.
Accredited attorneyyes, freeyesSubject to state bar advertising rules
Accredited claims agentyes, freeyesNot a lawyer — outside §6155, still inside UDAP
Anyone elsenot listedRemoves the entire claim-shark exposure surface

Fee rules are stated on every profile of a fee-charging representative, in plain language, at the point the veteran is deciding: fees may be charged only for work after VA issues an initial decision; 20% of past-due benefits is presumed reasonable and over 33⅓% is presumed unreasonable; the fee agreement must be in writing and filed with VA.

A persistent module above the Sponsored block on every search: "You can get this help for free." — DAV, VFW, American Legion, state veterans agencies, with a direct link. This is both the correct answer for most veterans and the strongest evidence that the site is not a funnel.

Trademark discipline in that module. Organization names are used in plain text as nominative fact, linking to each organization's own site. No VSO logos, seals, or marks are reproduced, and a standing line states that these organizations are not affiliated with, and do not endorse, FedM8. Reproducing the marks of DAV, VFW or the American Legion beside a paid product invites a false-endorsement claim under Lanham Act §43(a) that no amount of disclaimer text reliably cures — and the American Legion's name is additionally protected by its federal charter. VSOs are listed as a public service, cannot subscribe, and may request suppression on the same terms as anyone else.

No claim of VA endorsement, ever. Accreditation is stated as a fact with its roster date; VA's own guidance is linked; the site never suggests VA approves of FedM8 or of any listee.


3. Data model — person-first (this deletes v1's hardest problem)

v1 modeled firm and tried to map the OGC roster onto it. The roster is per person, so v1 silently required fuzzy entity resolution across people → firms → Google Places. v2 inverts the model and the problem disappears.

representative      id, ogc_person_key, full_name, kind, va_accreditation_number,
                    first_accredited_on, roster_date, is_current, state_codes[],
                    org_name_as_rostered, status
                    -- one row per OGC roster row. No inference, no merging.

profile             representative_id, claimed_by, bio, languages[], remote_ok,
                    office_city, office_state, website, phone,
                    google_place_id,          -- supplied BY the claimer at claim time
                    place_id_verified_at, place_id_verified_by, place_verify_method,
                    charges_fees bool, fee_basis, max_pct,
                    fee_agreement_on_file bool, attested_at,
                    suppressed_at, suppressed_reason
                    -- everything here is self-supplied and labeled as such.
                    -- NO google_rating / review_count / review_text columns. Ever.
                    -- Google stars render ONLY when place_id_verified_at is set.

state_rule          state_code, listing_allowed, sponsorship_allowed,
                    requires_office_city_disclosure, requires_annual_bar_report,
                    referral_registration_required, notes, reviewed_by, reviewed_at
                    -- per-state rules are DATA, not prose. Florida's annual report,
                    -- Ohio's registration question and any future state law are rows.
                    -- ENFORCING, not advisory: listing_allowed=false removes the
                    -- representative from every search result and 404s the profile;
                    -- sponsorship_allowed=false blocks Stripe checkout for that state
                    -- at the API layer, not just in the UI. A state with no row is
                    -- treated as listing_allowed=false until reviewed — new state laws
                    -- fail closed. Tested in §9 Phase 1 and Phase 5.

veteran             id, auth_user_id, verification_level, verified_at, provider,
                    provider_subject_id, display_handle, state_code
                    -- NO SSN. NO DD-214. NO condition, body system or diagnosis field.

consent             veteran_id, purpose, granted_at, revoked_at, policy_version,
                    consent_text_hash, ip
                    -- purpose: chd_collect | chd_share (never bundled)

review              id, representative_id, veteran_id, rating_1_5, body,
                    engagement_attested_at, stage_tag, status, published_at,
                    moderation_reason, response, response_at
                    -- stage_tag is a closed vocabulary about PROCESS, not health:
                    -- initial_claim | supplemental | higher_level | board_appeal
                    -- Free text is the veteran's own words, never edited by us.

rating_daily        representative_id, day, n, mean, bayesian
contact_delivery    representative_id, delivered_at        -- no message body retained
subscription        representative_id, tier, stripe_subscription_id, status,
                    sponsored_states[]
audit_event         actor, entity, entity_id, action, before, after, at

Google matching is opt-in at claim time and verified before it renders. The representative supplies their own Google listing; FedM8 then confirms ownership by one of two methods — the claimer completes Google Business Profile verification and we match the verified owner, or an operator manually matches name plus street address and records the check. Until place_id_verified_at is set, no Google block renders at all. This closes a theory v2.0 left open: an unverified place_id means rendering a stranger's stars beside someone's name, which invites a Lanham Act §43(a) false-association claim from the real business owner.

No fuzzy matching, no wrong-business errors, no unclaimed profile carrying a stranger's ratings.

Unclaimed profiles are inventory, not advertising. On a profile no one has claimed there is no subscription CTA, no upsell, no "upgrade this listing," no ad slot, and no sponsored card — and the page carries noindex. Any listed representative may request free suppression of their profile, no reason required (suppressed_at). The published policy states that FedM8 will use reasonable efforts to act promptly and makes no commitment to a specific timeframe — a published promise with a stated deadline converts moderation into contract exposure under Barnes v. Yahoo!, which is exactly what §6.10 exists to avoid. The internal service target is one business day; it is an operational target, not a representation to the public. This substantially reduces the Lukis v. Whitepages theory, where using a person's profile as the free preview that sells a subscription was held to be the site's own advertising and outside Section 230.

RLS on every table; read and write policies must agree on scope (the NodeDough cross-household bug came from a mismatch). revoke truncate ... from anon, authenticated. The directory schema is not exposed to the Data API; the browser reaches curated public.dir_* views, which must be security_invoker — v1's verification tested the wrong layer.


4. Health data — the layer v1 did not have

The dataset is "this identified person is a veteran pursuing a disability claim." Under Washington's My Health My Data Act that is consumer health data via the inferred/proxy prong (RCW 19.373.010(8)(b)(xiii)), there is no small-business exemption, and violations are per se Consumer Protection Act violations — a private right of action, treble damages capped at $25,000, plus attorney's fees. Nevada SB 370 imposes near-identical duties with AG-only enforcement. HIPAA does not apply, which is the problem rather than the relief.

Built artifacts, all in Phase 0:

  1. Standalone consumer-health-data notice, separate from the general privacy policy,

linked prominently from the homepage, containing the enumerated elements (categories, sources, categories shared, named affiliates, purposes, rights, appeal, effective date).

  1. Two-step opt-in consent at account creation and again at review submission —

a consent to collect and a separate, distinct consent to share. Unbundled from the ToS. No pre-ticked boxes. Every grant logged with timestamp, policy version, the exact text shown, and IP.

  1. Self-serve deletion that cascades to backups (≤6 months WA, ≤2 years NV) and notifies

downstream recipients, who are contractually required to delete.

  1. Appeal process, written response within 45 days, AG contact information on denial.
  2. Retention schedule with an affirmative deletion clock.
  3. Processor contracts carrying the statutory pass-through terms.

Three standing prohibitions, which together remove the entire GoodRx / BetterHelp / Cerebral fact pattern:

also removes the signed-authorization regime under RCW 19.373.070 entirely.

page, review page, or representative profile. First-party, server-side telemetry only. The browser makes zero requests to any third-party origin, Google included. Google ratings are fetched server-side through a first-party proxy** on the FedM8 origin, which is what makes that statement and §6 simultaneously true. The proxy is subject to a structured-logging field denylist that drops rating, review count, review text and author fields before anything is written, and CI asserts the denylist is intact on every build — not once at Phase 2. Google's attribution and link-out requirements are satisfied by the rendered markup, which does not require a browser-to-Google request.

And one schema-level rule: the site never asks for a condition, diagnosis or body system. stage_tag records where the veteran is in the process, not what is wrong with them. A veteran may of course write whatever they wish in their own review; we do not solicit it, do not index it as a facet, and do not build a filter on it.


5. Identity — two levels, honestly labeled

LevelSourceBadgeCan review
identitySupabase authnoneno
veteranID.me OIDC, military scope"Verified veteran"yes
veteran_honorableVA VSHE service_history.read, OAuth ACG"Verified honorable discharge"yes

No commercial product verifies discharge characterization — ID.me's payload has no such attribute and SheerID states the limitation in writing. Only VA's VSHE API returns it, free, under the veteran's own OAuth consent, after a written application, a live demo, and 1–6 months of review against a standing delay notice. Until VSHE is approved, the words "honorable discharge" do not appear on the site.

No SSN is collected, which rules out the Veteran Confirmation API and its state SSN-statute exposure. No DD-214 upload, ever — a stored DD-214 is a notice-triggering breach in a large share of states. Biometrics stay inside the vendor, contractually and technically.

ID.me is on the critical path for Phase 3 as a contracting dependency, not a line item — start the commercial conversation during Phase 0.


6. Ratings, reviews, and what we say about them

Two ratings, side by side, never merged. Google's is live-fetched per render by place_id server-side through the first-party proxy described in §4, attributed with the Maps mark, in its own bordered container, linking to googleMapsUri, with the required ranking-factor disclosure — and only where place_id_verified_at is set. Nothing from Google is ever persisted: not in the database, not in a cache, not in a CDN object, and not in a log line, which the logging denylist enforces mechanically rather than by convention. FedM8's rating is a Bayesian mean over published reviews with n shown, suppressed below three reviews.

The FedM8 rating is published as an opinion, with its methodology on a public page and a standing statement that it is not influenced by payment. That is what protected Avvo's rating in Browne and Davis — the opinion doctrine, not Section 230.

Review integrity, built clause by clause to 16 CFR Part 465 (civil penalty $53,088 per violation, the 2025 level carried into 2026 by OMB M-26-11):

  1. Only veteran-level accounts may post; one review per representative per veteran.
  2. The reviewer attests to an actual engagement with a date.
  3. No incentive of any kind for a review.
  4. No insider reviews — staff, listee staff and immediate relatives blocked.
  5. **Moderation criteria published, sentiment-blind, applied identically to subscribers and

non-subscribers.** "Clearly false" is defined narrowly: contradicted by the OGC roster or by the reviewer's own attestation. Every action writes an audit_event with a reason.

  1. Subscription status never affects publication, ordering or visibility.
  2. Review text is never edited. Editing risks co-authorship and forfeits Section 230.
  3. Listees get one public response per review and may flag against the published criteria;

flagging never hides a review pending review.

  1. A reviewer appeal path, and a correction/takedown path for the named professional

covering factual errors about them.

  1. Moderation policies are written as discretionary, not promissory — a published promise

to remove something within a stated time converts moderation into contract exposure (Barnes v. Yahoo!).

  1. Verified-reviewer records are retained as evidence of truth and absence of malice.

7. Money

One product: a flat monthly subscription, priced per state, available to accredited attorneys and claims agents. It buys placement in a labeled Sponsored block on search results, plus logo, photos, a longer bio, and analytics.

It does not buy: a change in who appears, a change in any rating, any change to how reviews are ordered or surfaced, review moderation treatment, removal of competitors, or placement on another professional's profile page. (v2.0 listed "response surfacing" as a subscriber benefit, which contradicted the rule that subscription never affects review visibility. It is removed — every listee may respond, and responses render identically.)

per-outcome or success component, no per-lead pricing. This is the line that keeps the model out of Model Rule 5.4 fee-splitting and out of the runner/capper statutes.

individual professional's profile. No listee's name or photo ever appears inside an ad unit or in copy selling subscriptions.

behind a hover or a link.

not recommend, endorse, screen or vet anyone; the site is not a law firm and does not provide legal services; the site is not a bar-approved referral service.


8. Phases

PhaseDeliverableGate
0ToS · general privacy policy · standalone health-data notice · breach process · retention/deletion schedule · security headers · 301 between ai. and scan. · media/multimedia E&O bound, with the exclusions recorded · ID.me commercial conversation openednone to start. Exit condition: Phase 0 is not complete, and Phase 3 may not begin, until the three written processor pass-through confirmations (ID.me, Stripe, Supabase) under RCW 19.373.060 / NV SB 370 Sec. 29 are in hand. Phases 1–2 touch no consumer health data and may proceed in parallel. A processor that refuses is a blocker to name and escalate, not a paragraph to redraft
1directory schema + RLS + security_invoker views; OGC roster importer (Excel, Mon/Wed/Fri); seed accredited representatives; staleness rule; state_rule enforcement0
2/find + /rep/:id read-only; live Google ratings; free-VSO module; fee-rules explainer; ranking-methodology page; disclaimers1 + written Illinois IRPA and Florida Bar R. 4-7.22 opinions — exposure from publishing named professionals attaches the moment this phase is public, so the opinions precede it
3ID.me OIDC; two-step consent flow + consent log; review write; moderation console; appeal + correction paths; audit log0, 2 + written Washington MHMD opinion on whether this dataset and consent design satisfy RCW 19.373
4Profile claim flow; self-supplied Google place_id; listee responses; Florida annual-report export2
5Stripe flat-fee sponsorship; Sponsored block on search only4 + written California opinion on whether a paid block responsive to a geo+practice-area query is "routing to a subset" under §6155/§6156.5
6VA VSHE integration; veteran_honorable badgeVA approval, 1–6 months

Estimate. Phases 0–5 are roughly 8–11 focused sessions, up from v1's optimistic 4–6. The increase is honest, not scope creep: Phase 0 grew a compliance package, Phase 3 grew a consent-logging subsystem, and v1's estimate omitted entity resolution — which v2 removes entirely by modeling per person.

Seeding. The OGC roster is the complete accredited universe, free, refreshed Monday, Wednesday and Friday. The veteran side is useful on day one, before anyone subscribes. That is the cold-start answer. Nothing is bulk-seeded that is not on the roster.

Staleness rule. Every badge shows its roster date. If the importer has not succeeded in 7 days the badge downgrades to "accreditation last confirmed <date>." If a person leaves the roster the profile is unpublished within one refresh cycle and the reviews are archived.

9. Verification per phase

Gate evidence, all phases. Before any gated phase ships, assert that its gating opinion exists as a named, dated document — Illinois IRPA and Florida 4-7.22 before Phase 2, Washington MHMD before Phase 3, California §6155/§6156.5 before Phase 5 — and record the document reference in the phase's status. An opinion that is "being sought" is not evidence.

and record which claim types it excludes; assert the three processor pass-through confirmations exist as signed documents, named and dated.

both denials and the positive cases; confirm every dir_* view is security_invoker; assert a representative in a state with listing_allowed=false (and one with no state_rule row at all) is absent from search and 404s on profile.

any cache object, in the CDN response headers, or in request logs — an end-to-end grep, not a schema grep — plus a CI assertion on every build** that the proxy's logging denylist still drops rating, review-count, review-text and author fields. Assert that a profile with place_id_verified_at null renders no Google block. Screenshot the Maps attribution and the visual separation.

automated scan proving zero requests to any third-party origin — Google included, since the rating is proxied server-side — on authenticated pages, review pages and profiles.

slot, and carries noindex; test the suppression path end to end.

in 16 CFR §465.1(c); automated assertion that no sponsored unit renders on a profile page; assert Stripe checkout is refused at the API layer for a state with sponsorship_allowed=false.

in Phases 2, 3 and 5 — this is confirmation that what shipped matches what was opined on, not a first look. A first look at launch would be too late: the Illinois and Florida exposure attaches at Phase 2, and the Washington exposure at Phase 3.

10. What this plan does not claim

It does not claim zero litigation risk. A site that publishes star ratings of named professionals will receive demand letters; several will come from attorneys, who write them cheaply. What the design does is make each theory expensive to plead and cheap to defeat: Section 230 for user reviews, the opinion doctrine for our rating, verified-reviewer records as evidence, a documented correction path, free suppression on request, and bound media E&O.

Two defenses are weaker than they look, and the plan says so rather than relying on them.

Anti-SLAPP covers 38 states plus D.C. and the UPEPA jurisdictions — but several federal circuits (including the 2nd, 5th and 11th) hold state anti-SLAPP statutes inapplicable in federal court, and a class action under Illinois IRPA or California §6156.5 is exactly the kind of case that lands there. Assume no fee-shifting for the cases that matter most.

Media/multimedia E&O at roughly $1,500–$4,000 a year for $1M/$2M limits covers defamation, privacy and misappropriation. It typically excludes statutory penalties, unfair-competition claims and intentional statutory violations — which is to say it likely does not cover IRPA statutory damages, an MHMD/CPA claim, or a §6156.5 action. Buy it anyway; do not treat it as the answer to the three largest exposures. Confirm the exclusions with the broker in Phase 0 and record what is actually covered.

Two authorities this plan leans on are young and unconstrued: California §6156.5 (2026) has no case law, and MHMD has no published merits ruling — so the statement in §4 that our dataset "is consumer health data" is the conservative reading of the statutory text, not a holding. If either is later read narrowly, this design will have been stricter than it needed to be. That is the correct error to make under the stated mandate.

11. Directive and ops compliance

This plan is executed under hi.jbnx.io (v35 at time of writing; re-fetch every session).

per phase. The claim opens exactly one billable session; status updates that same receipt; release stops the clock. No second billable per claim, no post-hoc billing, no parallel call to the bill API.

with the usage line and token-health band attached to both the chat reply and the status.

auto-merge to production; ship refuses branch=production on this repo.

with project_slug: "fedm8" so it is filed under the project and listed on the project page. No new files under public/framework/.

form. One Actions check per change; a named hard blocker plus status and release is a valid end state; deploy-verification loops are not.