FEUDFIX — PRE-IMPLEMENTATION AUDIT

Read-only audit. No files were modified, created, or deleted. No prompts, UI, security settings, or email behavior were changed.


PART 1 — APPLICATION ARCHITECTURE

Frontend: React 18 + Vite, Tailwind CSS, shadcn/ui, React Router. Single-page app; pages in src/pages/, components in src/components/. Realtime via Base44 entity subscriptions. Voice intake via Web Speech API.

Backend: Base44 BaaS. Server logic lives in two layers:

  • Backend functions (base44/functions/*/entry.ts) — Deno/edge handlers invoked over HTTP. Used for email send/receive, escalation letters, case persistence that bypasses RLS, scheduled tasks, admin tooling.
  • Shared modules (base44/shared/*.ts) — imported by functions (SendGrid mail, letter HTML, SSRF guard, US state parsing, fuzzy search, ranking engine).

Database: Base44 managed document store (MongoDB-style). Every entity is a JSON schema in base44/entities/*.jsonc. No external database. Queries use the SDK (base44.entities.X.filter/list/get/create/update/delete). updateMany/bulkUpdate/deleteMany support MongoDB-style operators.

File/document storage: Core.UploadFile (platform storage at media.base44.com / static.wixstatic.com). Core.UploadPrivateFile + CreateFileSignedUrl exist but are not used for case evidence — all case evidence goes to public UploadFile storage (see Part 3).

Authentication: Base44 platform auth (AuthProvider, base44.auth). Email/password, Google OAuth, OTP verification, password reset — all boilerplate pages at standard paths. Sessions/tokens owned by the platform; the app never touches credentials.

Authorization model: Row-Level Security (RLS) declared per entity in .jsonc. Roles: admin, agent, beta_tester, user (default). Ownership pattern uses created_by_id + a mutable owner_user_id field (because created_by_id is immutable and anonymous filings have a platform placeholder). See Part 2.

Email provider: SendGrid (Mail Send API + Inbound Parse). Secrets: SENDGRID_API_KEY, MAIL_DOMAIN, INBOUND_WEBHOOK_SECRET. Outbound mail in base44/shared/sendGridMail.ts. Inbound via receiveInboundEmail webhook. Click/open tracking disabled.

AI providers/models (all via Core.InvokeLLM):

  • gpt_5_mini — free pre-login mini-analysis (runMiniAnalysis).
  • gemini_3_flash — intake triage/clarify, company dispute-strategy research, similar-cases web search, document extraction from URLs, admin "read document" flow.
  • gemini_3_1_pro (premiumModel()) — full case analysis (reanalyzeCase), the single most expensive call.
  • Default/automatic — escalation letters, demand letters, multi-company extraction, product-model validation/trouble reports, recent-model lookups.
  • File vision supported on gemini_3_1_pro and default; web search (add_context_from_internet) only on gemini_3_flash/gemini_3_1_pro.

Web-search provider: Google web search is bundled into InvokeLLM via add_context_from_internet (Gemini models). No separate search API. fetchPageContent/validateUrl functions fetch arbitrary URLs server-side (with an SSRF guard).

Third-party APIs: Stripe (Payment Links, client-side redirect — no server-side webhook or payment record), SendGrid, Base44 AI/integrations, Unsplash (stock images). No Lob/PostGrid (physical mail). No CRM/connector integrations authorized.

Scheduled/background processes (workflows in base44/workflows/):

  • Daily: Resolved Case Detection, Intelligence Index Refresh, Action Due Reminders, Idle Case Reminders, Case Digest Reminders, New Info Reminders, Company Refresh, Resolved Evidence Cleanup.
  • Weekly: Orphan Document Scrub.
  • Quarterly: Ranking Reports, Escalation Agency Refresh.

Caching: Company.similar_cases_cache (30-day TTL), Company.suggestions (30-day TTL), Case.free_analysis / Case.ai_analysis (cache-on-case), client localStorage for the per-case unlock flag.

Analytics: SessionEvent entity (page views, clicks, errors — admin-only read), IntakeSession (funnel aborts/completions — admin-only read), base44.analytics.track (custom events, minimal).

Payment systems: Stripe via Payment Links stored on Service.stripe_link / ServiceTier.stripe_link. Checkout redirects the browser to Stripe; on return, a localStorage flag unlocks the case. No server-side payment verification, no webhook.


PART 2 — USER AND CASE DATA ISOLATION

RLS summary (verified from entity schemas):

  • Case — read/update/delete: created_by_id OR owner_user_id OR admin OR agent. Agents can read and update every customer's case, not just assigned ones. Create is open (anonymous filing by design).
  • CaseDocument — read/update/delete: created_by_id OR owner_user_id OR admin. Owner-scoped.
  • Correspondence — read/update: created_by_id OR owner_user_id OR admin. Delete adds beta_tester.
  • Customer — read/update/delete: created_by_id OR data.user_id OR admin OR agent. Agents can read and edit every customer profile.
  • TimeEntry — read: created_by_id OR owner_user_id OR admin OR agent. Agents see all time entries.
  • Company — read is null (public to any authenticated user). Update: admin/beta_tester, or agent where agent_number matches.
  • CompanyDocument — read is null (public to any authenticated user).
  • EscalationAgency, Service, ServiceTier, AppSetting, RankingReport, ResolvedCaseSummary — read null (public). Writes admin-only.
  • SessionEvent, IntakeSession — read admin-only.
  • ChangeLog, FeatureRoadmap, PromptTemplate — read public or admin; write admin/beta_tester.

IDOR analysis:

  1. getCase function (MEDIUM RISK). Reads via the service role and returns the full case if the caller is the owner or the case is "unclaimed" (!owner_user_id and created_by_id is anonymous). Consequence: any authenticated user who guesses or obtains an unclaimed case's ID can read its full description (which may contain PII) and its analysis. Mitigation: per-case share token, time-box unclaimed readability, or restrict to the same IP/session that created the case.

  2. saveCaseAnalysis (MEDIUM RISK). Same unclaimed-or-owner pattern. A non-owner could write analysis fields onto an unclaimed case. Field allowlist limits damage; window still exists.

  3. sendCorrespondence (GOOD). Checks isCaseOwner, verifies each attachment belongs to the case, restricts attachment URLs to platform hosts + SSRF guard. Strongest of the service-role functions.

  4. escalateCase (GOOD). isCaseOwner check; rejects resolved cases.

  5. Agent over-read (MEDIUM RISK). Case and Customer read RLS grants agent unrestricted access to all customers and cases, not just assigned ones. Agents see case metadata + customer PII (name/address/phone/email), though correspondence is not agent-readable. If agents are untrusted or multi-tenant, this leaks PII. Recommend assignment-scoping.

  6. Company/CompanyDocument public reads (LOW). Public-facing materials; acceptable.

  7. Client-side entitlement (MEDIUM). The per-case paywall is a localStorage flag. reanalyzeCase and the mini-analysis call InvokeLLM directly from the browser. A non-entitled user can bypass the paywall and burn credits. Recommend moving the full analysis behind a backend function with server-side entitlement checks.


PART 3 — DOCUMENT SECURITY

Storage location: All case evidence is uploaded via Core.UploadFile and stored as file_url on CaseDocument. Host: media.base44.com / static.wixstatic.com.

Public vs private: UploadFile storage is publicly accessible by URL. Anyone with the URL can download the file without authentication. UploadPrivateFile + signed URLs exist in the platform but are not used for case evidence. This is the most significant document-security weakness: receipts, contracts, and correspondence are publicly retrievable if a link leaks.

Authorization enforcement: The CaseDocument record is RLS-protected, but the file bytes are not — the storage URL is the access control. Once someone has the URL, the bytes are public.

Direct URL access: Yes — works without auth (confirmed by the SSRF/host allowlist in sendCorrespondence).

Scanning/validation: None. No virus scan, no MIME sniff, no content validation. CaseDocumentUploader accepts any file. No type/size filter in code.

Sent to AI providers: Yes. reanalyzeCase passes file_urls to InvokeLLM (Gemini 3.1 Pro, vision). ExtractDataFromUploadedFile sends the URL to the platform extractor. Evidence documents (potentially containing PII, financial info, IDs) go to third-party AI providers.

Retained by AI providers: Governed by the vendor's policy, not by FeudFix. Should be disclosed in a privacy policy.

Deletion: CaseDocument.delete removes the record but does not delete the file from storage. The deleteResolvedCaseEvidence workflow deletes records 30 days post-resolution; file bytes likely persist.

Weaknesses summary:

  1. Evidence on public storage (anyone with the URL can download).
  2. No file type/size validation or scanning.
  3. Deletion does not remove file bytes.
  4. PII documents sent to AI providers with no user disclosure.
  5. Private-file option unused despite platform support.

PART 4 — EMAIL ARCHITECTURE

  • Address creation: Each case gets a virtual inbox case-{case_number}@{MAIL_DOMAIN}, created lazily on first send. Case.virtual_email stores it.
  • Outgoing: sendCorrespondence → SendGrid Mail Send API. from: virtualEmail, fromName: 'FeudFix', HTML via letterToHtml. Click/open tracking disabled. Attachments fetched as base64.
  • Incoming: SendGrid Inbound Parse posts to receiveInboundEmail?secret=.... Validates secret, parses multipart, looks up case by virtual_email, creates inbound Correspondence (with owner_user_id backfilled), forwards a notification to the customer, triggers detectResolvedCases.
  • Inbound attachments: Attachment names recorded in raw_headers; binaries/content NOT stored. Inbound attachments are lost.
  • Storage: All correspondence in the Correspondence entity. No separate email store.
  • AI processing of email contents: Inbound replies are fed to the LLM on re-analysis. Email contents ARE sent to the AI provider.
  • Exact sent message: Correspondence.content is the letter text; rendered HTML is regenerated from text + template (not separately stored).

State distinguishability:

  • Correspondence.status: draft / sent / received / failed.
  • direction: outbound / inbound.
  • in_timeline: whether an outbound letter shows in the timeline.
  • Limitation: no "customer-edited" vs "AI-original" flag, and no explicit "approved" state separate from "sent". Editing a draft overwrites content with no version history. The AI's original draft is overwritten on edit; no audit trail of AI-produced vs customer-changed text. A sent record means the customer approved and sent it.

Automatic sending without approval:

  • Demand letters: draft, manual send. ✅ No auto-send.
  • Escalation letters: draft, manual send. ✅ No auto-send.
  • Freeform replies: customer-written, manual send. ✅
  • detectResolvedCases: emails the customer (not the company). ✅
  • Conclusion: the system does NOT automatically send AI-generated dispute correspondence to companies without explicit customer approval. Correct and safe.

PART 5 — EMAIL IDENTITY AND TRANSPARENCY

What the recipient currently sees:

  • Sender name: FeudFix (hardcoded in all outbound).
  • Sender email: case-{number}@mail.feudfix.com.
  • Reply-to: defaults to From (virtual inbox). Company sees only FeudFix as the sender identity.
  • Body: AI-drafted letter, signed by the customer's name inside the body, wrapped in a branded FeudFix HTML template with a FEUDFIX wordmark header and a footer reading "Sent via FeudFix — your consumer dispute resolution platform."
  • FeudFix identity: prominent. Customer identity: only inside the letter body, not the email envelope.

Could this mislead a recipient? Yes, plausibly. The envelope From name is FeudFix, the domain is FeudFix's, branding dominates. A company could believe FeudFix is the author/sender rather than a conduit, and — because the letter is formal and cites policy — could mistake FeudFix for a law firm acting on the customer's behalf. Nothing in the email says "authored by the customer, sent through FeudFix" or "FeudFix is not a law firm."

Safer implementation (recommended):

  • Set from.name to the customer's name (or "{Name} via FeudFix").
  • Add a prominent in-body disclaimer: FeudFix is not a law firm and sends on the customer's behalf.
  • Keep reply_to on the virtual inbox.

This is a transparency/accuracy issue, not a security vulnerability.


PART 6 — AI ARCHITECTURE

Every AI call:

| Function | Model | Purpose | Web? | Docs? | Prior case info? | Stored? | Auto-sent? | |---|---|---|---|---|---|---|---| | Intake triage/extract/clarify (3 parallel) | flash-class | Title, company, product, clarifying Qs, triage gate | No | No | No | Ephemeral | No | | Multi-company extraction | default | Extract company names | No | No | No | No | No | | Product model validation / trouble reports | default/flash | Validate model, known issues | Yes | No | No | On form/CompanyDocument | No | | Company dispute-strategy research | gemini_3_flash + web | Reusable strategy report | Yes | No | Yes (cached) | Company.suggestions | No | | Similar-cases web search | gemini_3_flash + web | Find complaints/reviews/news | Yes | No | No | Company.similar_cases_cache | No | | Policy download/extract | gemini_3_flash + web / ExtractData | Pull policy text | Yes | Yes | No | CompanyDocument.content | No | | Full case analysis (reanalyzeCase) | gemini_3_1_pro | Structured analysis | No | Yes (file_urls) | Yes | Case.ai_analysis | No | | Free mini-analysis (runMiniAnalysis) | gpt_5_mini | Preview report | No | No | Yes (cached) | Case.free_analysis | No | | Demand letter | default | Draft letter | No | No | Yes (analysis) | Correspondence (draft) | No (manual) | | Escalation letter | default | Draft escalation letter | No | No | Yes | Correspondence (draft) | No (manual) | | Resolution detection (detectResolvedCases) | default | Detect likely resolution | No | No | Yes | Case.resolution_check | No (emails customer) |

AI behaviors that could produce risky claims:

  1. Resolution probability (0-100%) is LLM-generated, not empirical. resolution_probability is described as "based on cited policy strength and evidence" but is an LLM estimate shown directly to the customer. Risk: unsupported numerical probability of resolution. The Intelligence Index (intel_resolution_rate) is empirical but sample-size-gated; the per-case probability is not.
  2. Escalation letter prompt presupposes "established policy violations." The LLM may assert the company violated the law even when facts only show a dispute. Risk: unsupported legal conclusions.
  3. Demand-letter prompt is well-constrained (no inventing facts, cooperative tone). Lower risk.
  4. Case-analysis prompt separates facts from analysis and cites documents — good. But facts confidence is LLM self-assessed; "high" could still be a hallucination.
  5. Dispute-strategy prompt guards against allegation-as-fact (VERIFIED/STRONG/MODERATE/WEAK). Good but LLM-enforced, not verified.
  6. Hallucinated policies: when no company documents are on file, the prompt says "rely on general reasoning" — web-sourced strategy could bleed in as company policy. Moderate risk.
  7. "Guaranteed to win": prompt forbids claiming guaranteed outcomes, but resolution_probability as a number still implies precision.

No prompts were modified.


PART 7 — CURRENT INTAKE PROCESS

Process (AI-driven conversational chat):

  1. Opening: "Tell me, in your own words, what happened." (Free text; min-words gate.)
  2. On send (3 parallel LLM calls): intake extraction (title, company, product, location), clarifying questions (up to 4), triage gate (supported/unsupported).
  3. Clarifying Q&A loop: up to 4 questions one at a time. Year-clarification and future-date checks enforced deterministically.
  4. Desired resolution timeframe: "When would you like this resolved by?"
  5. Product model step: if a physical product detected, ask for model, validate, search known trouble reports.
  6. Finish: → submit() analysis chain.

Information collected: what happened, company, product/service + model, purchase date (if mentioned), desired resolution (only via clarifying Q), desired timeframe, clarifying answers. Evidence uploads happen later on the case page, not in intake.

NOT explicitly collected:

  • Dollar amount / approximate value — not asked.
  • Whether the customer already contacted the company — only via clarifying Q priority 3, not guaranteed.
  • Current status / duration — not explicitly asked.
  • Documentation available — only via clarifying Q, no structured question.

When FeudFix begins consuming paid resources:

  • First chat message: 3 LLM calls immediately (cheap model).
  • On submit: company extraction LLM, web search for candidates, web fetch + LLM for policy documents, web-enabled LLM for dispute-strategy research (expensive), web-enabled LLM for similar-cases search — all before the customer pays or sees the full analysis. The full reanalyzeCase (gemini_3_1_pro) is on-demand and paywalled, but the intake research is not.

Cost-prevention opportunities (not implemented):

  • No Case Opportunity Score or triage to skip research for low-value cases.
  • For a brand-new company, full web research runs at intake unconditionally.
  • The intake research chain is not rate-limited per case.
  • A two-stage intake (Part 16A) would let cheap cases skip expensive web research.

PART 8 — CURRENT CASE ANALYSIS

Workflow: CaseAnalysisLoader shows "Analyze my case" (or auto-runs if paid). reanalyzeCase builds RAG context from policy docs (version-selected by purchase date), uploaded evidence (file_urls to vision model), the "Cases & complaints" feed, full correspondence history, resolved-case summaries, and the dispute-strategy report. Calls InvokeLLM with gemini_3_1_pro and a JSON schema, applies a deterministic desired-resolution-time penalty, persists to Case.ai_analysis.

Output separation:

  1. Customer's accountdescription + clarifying Q&A in the prompt; output summary reflects it. ✅
  2. Documented factsfacts[] with text/confidence/citation. ✅
  3. Company policiescompanyContext; cited in facts and relevant_policy_citations. ✅
  4. Third-party information → similar cases / dispute strategy; surfaces in outcome_prediction. ⚠️ Not cleanly separated.
  5. Similar complaints → "Cases & complaints" feed as similarContext. ⚠️ Background only, not a distinct output section.
  6. FeudFix analysisanalysis field. ✅
  7. Recommended next stepsrecommended_actions[] + action_timelines[] + improvement_actions[] + immediate_next_step. ✅

Source citations: facts[].citation and relevant_policy_citations carry labels, but no structured source object (URL, title, date accessed, source type) — citations are free-text strings. Source URLs not retained on facts. retrieved_sources is a flat string of doc titles.

Allegation vs fact: Prompt separates FACTS from ANALYSIS, but customer allegations in description are not explicitly flagged as "unverified allegations" in the output schema; they feed analysis and summary. Moderate risk of treating customer claims as established.

Probability of resolution: resolution_probability (0-100) is generated and shown. It is an LLM estimate, adjusted by a deterministic time penalty. Not statistically grounded unless the Intelligence Index has sufficient sample (and even then the per-case number is LLM-synthesized). Main "unsupported percentage" risk.


PART 9 — COMPANY RESEARCH

  • Trigger: At intake for each confirmed company; on admin refresh; on scheduled Daily Company Refresh; on priorityCaseRefresh. Reused if cache <30 days old.
  • Sources: Web via InvokeLLM with add_context_from_internet (Google search inside Gemini). fetchPageContent for direct fetch. validateUrl for link checks.
  • Caching: Company.suggestions + suggestions_updated (30-day TTL); Company.similar_cases_cache + similar_cases_updated (30-day); CompanyDocument records persist policy text.
  • Policy identification: refreshCompanyPolicies downloads likely policy pages, LLM-extracts text, stores as CompanyDocument with document_type, effective_date, priority_tier.
  • Similar complaints: web search returns typed items with source_url, date, region, article_text, company_confident flag. Cached to Company.similar_cases_cache.
  • Resolutions: ResolvedCaseSummary records (created on case resolution) aggregated into the Intelligence Index — empirical, sample-size-gated.
  • Source URLs: preserved on similar-cases items and CompanyDocument.source_url. Access dates: downloaded_date / verified_date / last_updated. Not a structured per-claim source object.
  • Research updatability: Yes — admin refresh, scheduled refresh, cache-miss re-run.
  • Allegation-as-fact risk: Prompt explicitly guards against it; company_confident flag filters mismatches. But the final report is LLM-synthesized and could still present a complaint pattern as company behavior. Moderate residual risk.

PART 10 — CASE TIMELINE AND AUDITABILITY

Records present:

  • Case creation ✅ (Case.created_date)
  • Intake ⚠️ (IntakeSession record, not shown in the case timeline)
  • Documents ✅ (CaseDocument in evidence drawer)
  • Research ⚠️ (not explicitly timestamped in the timeline)
  • AI analysis ✅ (Case.analyzed_date; re-analysis bumps notes_edit_count)
  • Draft emails ✅ (Correspondence draft records)
  • Customer edits: ⚠️ No. Editing a draft overwrites content with no version history.
  • Customer approval: ⚠️ Inferred from status: 'sent' — no separate "approved" event/timestamp beyond sent_date.
  • Sent emails ✅ (sent + sent_date + external_message_id)
  • Received emails ✅ (inbound + received_date)
  • Case changes ✅ (updated_date, status transitions, no per-field history)
  • Case closure ✅ (resolved_date, resolution_method, resolution_notes)

Editability/deletability: Correspondence records can be updated and deleted by the owner/admin. in_timeline can be toggled. Timeline entries are not immutable — an owner can edit or remove a sent letter's content or delete the record. Case and TrackedAction also editable/deletable.

Admin audit log: No dedicated administrative audit log. SessionEvent tracks client-side page views/clicks, not admin data-access or mutations. ChangeLog is a manually-posted release log. No append-only record of admin viewing/editing customer cases, documents, or emails. These records are all mutable.


PART 11 — DATA RETENTION AND DELETION

| Data | Retention | |---|---| | User accounts | Indefinite until platform account deletion (no in-app self-serve deletion) | | Cases | Indefinite (owner/admin/agent can delete) | | Case documents | Indefinite record; file bytes on public storage persist after record deletion | | Emails (Correspondence) | Indefinite | | Attachments (inbound) | Not stored at all (names only) | | AI conversations | Ephemeral | | AI reports | Indefinite on Case.ai_analysis/free_analysis, Company.suggestions | | Research | 30-day TTL for refresh, not auto-purged | | Company data | Indefinite | | Logs | SessionEvent indefinite (admin can delete); no log rotation |

User capabilities:

  • Delete documents: ✅ (but file bytes persist)
  • Delete cases: ✅
  • Close cases: ✅
  • Delete account: ❌ No self-serve account deletion in-app (Base44 support)
  • Request deletion of their information: ❌ No in-app flow

Actual removal: Deleting a CaseDocument removes the DB record but does not remove the file from media.base44.com — no delete call wired. Deleting a case does not cascade-delete correspondence/documents/time entries. No purge of data sent to AI providers (not under FeudFix's control).


PART 12 — PRIVACY AND SENSITIVE DATA

Collected/stored:

  • Customer full_name, address, phone, email.
  • Case description — free text, may contain anything (names, account numbers, transaction details, dates, incident narratives).
  • Uploaded evidence — any file: receipts, contracts, bills, bank statements, insurance docs, medical bills, ID photos, screenshots. No type restriction.
  • Correspondence content (outbound + inbound).
  • Case.purchase_date, product_or_service, desired_resolution.
  • User email, role, agent_number.

Warnings to users not to submit unnecessary sensitive info: No. Intake and uploader do not warn customers to avoid SSNs, medical records, financial credentials, government IDs, etc. Uploader label is simply "Click to upload evidence & contracts."

Sensitive info sent to third-party AI/search providers: Yes, broadly.

  • Case.description and clarifying answers → LLM at intake.
  • Uploaded evidence file_urls → Gemini 3.1 Pro (vision) during full analysis; → ExtractDataFromUploadedFile during intake.
  • Inbound company replies → LLM during re-analysis.
  • Company dispute-strategy research sends company name + complaint description to web-enabled Gemini.

Data flow: Customer enters complaint → browser → Base44 SDK → LLM provider. Customer uploads file → browser → UploadFile (public storage) → LLM provider (file_urls). Inbound email → SendGrid → webhook → Correspondence → LLM on re-analysis. No redaction/PII-scrubbing before LLM calls.

Risk: Customers may upload documents containing SSNs, medical info, or financial account numbers; these are stored on public storage and sent to AI providers with no warning, no redaction, and no privacy policy disclosure.


PART 13 — ADMINISTRATIVE SECURITY

  • Who can access customer cases: admin (all), agent (all — not assignment-scoped), and the case owner. beta_tester is not granted case read but can delete correspondence and edit companies/prompts.
  • Who can access uploaded documents: case owner, admin. Agents cannot read CaseDocument but can read Customer PII.
  • Who can access emails (Correspondence): case owner, admin. Agents cannot. Good separation.
  • MFA: Not enforced by the app. Admin accounts have no app-level MFA requirement.
  • Admin action logging: No. No record of which admin viewed or edited which case/customer/document/email. SessionEvent records client-side page views/clicks, not admin data-access or mutations. ChangeLog is a release-notes log, not an access audit.
  • Role-based access: Yes — RLS by role. But the agent role is over-broad (all cases, all customers).
  • All admins see all customer data: Yes. No admin segmentation.

Unnecessary privileges:

  • Agents reading all customers (PII) and all cases — should be assignment-scoped.
  • beta_tester able to delete correspondence and edit companies/prompts — broad for a testing role.
  • Admin ability to read full correspondence content — necessary for support but unlogged.

PART 14 — CURRENT ANALYTICS

Tracked today:

  • Landing-page visits ✅ (SessionEvent page_view on /)
  • Intake starts ✅ (IntakeSession status started)
  • Intake completions ✅ (IntakeSession status created + abort categories)
  • Account creation ❌ (not explicitly tracked)
  • Document uploads ❌ (no dedicated event; inferable from CaseDocument)
  • Full analysis run ⚠️ (inferable from Case.analyzed_date; no explicit event)
  • Report completion ✅ (inferable from Case.ai_analysis)
  • Email drafting ⚠️ (inferable from Correspondence drafts)
  • Email approval ❌ (no distinct "approved" event; only sent_date)
  • Email sending ✅ (Correspondence sent + sent_date)
  • Case resolution ✅ (resolved_date, resolution_method, ResolvedCaseSummary)
  • Payment ❌ (no server-side payment record; only a localStorage flag and Stripe redirect — actual purchase completion not captured in-app)
  • User abandonment ✅ (IntakeSession abort categories: free_limit_reached, triage_unsupported, company_not_found, user_aborted_back, user_abandoned_case, intake_error, auth_required_drop)

Unavailable commercial-validation metrics:

  • Actual purchase (no server-side payment confirmation — Stripe webhook not wired).
  • Baseline intended action (what the customer planned before analysis).
  • Post-analysis change in intended action.
  • Advocate time saved (TimeEntry exists but no before/after comparison).
  • "Did FeudFix find something the customer didn't know" / "did it change the plan" — no survey instrument.
  • Willingness-to-pay signal beyond checkout click.

PART 15 — COMMERCIAL VALIDATION REQUIREMENTS

What exists:

  • Intake completion ✅, case qualification ✅, document upload ✅ (record-level), full analysis ✅ (record-level), case outcome ✅ (ResolvedCaseSummary), abandonment ✅.
  • Advocate time tracking ✅ (TimeEntry with billable rate/duration).

What needs to be added for the 6 commercial questions:

  1. Did FeudFix find something useful the customer didn't know? → post-analysis micro-survey ("Did you learn something new? Y/N" + free text). Not present.
  2. Did FeudFix change what the customer planned to do? → baseline-intended-action capture at intake + post-analysis follow-up. Not present.
  3. Did FeudFix save an advocate time?TimeEntry exists, but no advocate-reported time-saved estimate. Needs a single field per case.
  4. Did FeudFix contribute to a better outcome? → post-resolution rating from the customer. Not present.
  5. Would the customer pay? → post-resolution willingness-to-pay prompt. Not present.
  6. Would an advocate pay? → advocate sentiment capture. Not present.

Minimum additions for the test: a lightweight post-analysis survey (2-3 questions) and a post-resolution survey (2-3 questions), stored on the Case or a small SurveyResponse entity; plus a server-side payment record (Stripe webhook) so "actual purchase" is real.


PART 16 — REQUIRED FUTURE CHANGES (HOW, NOT IMPLEMENTED)

A. Two-stage intake: Add a lightweight intake that collects what-happened, company, desired outcome, approximate dollar amount, already-contacted, current status, duration, documentation available, desired resolution — before the existing chat. Compute an internal Case Opportunity Score from a deterministic function of (dollar amount, documentation, already-contacted, category). Do not show it as success probability. Route: low-score → mini-analysis only; high-score → full research chain. Complexity: Medium. Base44-implementable: Yes.

B. Resource levels (1/2/3): Map the Opportunity Score to a level gating which AI/web steps run. Level 1 = mini-analysis only. Level 2 = mini + cached company intel. Level 3 = full research + gemini_3_1_pro. Complexity: Medium. Base44-implementable: Yes.

C. Remove resolution probability: Either remove resolution_probability from the displayed schema, or replace it with the empirical Intelligence Index intel_resolution_rate (with confidence) and a plain-language estimate ("low/moderate/high"). Complexity: Low. Base44-implementable: Yes.

D. Case report structure: Reorganize the analysis output schema into explicit sections: Customer Account, Documented Facts, Company Information, Similar Complaints, FeudFix Analysis, Possible Next Steps, Missing Documentation. Complexity: Medium. Base44-implementable: Yes.

E. Source attribution: Add a sources[] array to the analysis schema and CompanyDocument: { url, title, source_type, date_accessed, relevant_info }. Persist date_accessed at fetch time. Cite sources by index. Complexity: Medium. Base44-implementable: Yes.

F. Customer approval before sending: Already implemented (manual send). Gap: no explicit "approved" state/timestamp; approval is implicit in status: 'sent'. Strengthen: add approved_at/approved_by on send, and keep an immutable original AI draft (version it, don't overwrite). Complexity: Low–Medium. Base44-implementable: Yes.

G. Transparent case email: Change from.name to the customer's name (or "{Name} via FeudFix"), add a prominent in-body disclaimer that FeudFix is not a law firm and sends on the customer's behalf, keep reply_to on the virtual inbox. Complexity: Low. Base44-implementable: Yes.

H. Audit log: Create an AuditEvent entity (append-only via RLS). Log: case viewed by non-owner admin, case edited, document read, correspondence sent, admin role change, escalation. Log from backend functions. True append-only not natively supported by Base44 RLS (admins could update/delete), so "protected" rather than cryptographically immutable. Complexity: Medium. Base44-implementable: Yes (with caveat).

I. Security hardening:

  • Move case evidence to UploadPrivateFile + signed URLs (expire). Base44-implementable: Yes.
  • Server-side entitlement check before the full analysis (backend function). Base44-implementable: Yes.
  • Scope agent reads to assigned cases/customers (add assignment field + RLS rule). Base44-implementable: Yes.
  • Close getCase/saveCaseAnalysis unclaimed-case IDOR (share token or session binding). Base44-implementable: Yes.
  • Admin MFA — platform-level, not app-controllable. Base44-implementable: No.
  • Data encryption — platform-managed at rest. Base44-implementable: No.
  • Secure deletion — wire file-blob deletion on CaseDocument delete. Base44-implementable: Partially.

J. Commercial analytics: Add post-analysis + post-resolution micro-surveys, wire a Stripe webhook to a backend function recording a Purchase entity, add advocate-time-saved and willingness-to-pay fields. Complexity: Medium. Base44-implementable: Yes.


PART 17 — PRIORITIZATION

| # | Requirement | Current state | Risk/problem | Recommended change | Base44? | Complexity | Commercial importance | Security importance | Timing | |---|---|---|---|---|---|---|---|---|---| | 1 | Server-side payment record | localStorage flag only; Stripe redirect, no webhook | "Actual purchase" not verifiable; paywall bypassable | Wire Stripe webhook → Purchase entity; gate entitlement on it | Yes | Medium | Critical | High | Before testing | | 2 | Server-side entitlement gate on full analysis | reanalyzeCase calls LLM from browser; paywall is localStorage | Non-paying users can burn the most expensive credits | Move full analysis behind a backend function with entitlement check | Yes | Low | Critical | High | Before testing | | 3 | Email identity transparency | from.name = "FeudFix"; no disclaimer | Recipient may mistake FeudFix for a law firm / the author | Customer name as from.name + in-body disclaimer | Yes | Low | High | Medium | Before testing | | 4 | Private evidence storage | Public UploadFile URLs for receipts/contracts/PII | Anyone with the URL downloads evidence; links leak | Switch to UploadPrivateFile + signed URLs | Yes | Medium | Medium | Critical | Before testing | | 5 | Admin/agent MFA | None enforced | Admin account takeover exposes all customer data | Enforce at platform/account level | No | Low | Medium | Critical | Before testing | | 6 | Admin action audit log | None | No traceability of who accessed/edited what | AuditEvent entity, log from backend functions | Yes | Medium | Low | High | During testing | | 7 | Post-analysis + post-resolution surveys | None | Can't measure the 6 commercial questions | 2-3 question surveys on Case/SurveyResponse | Yes | Low | Critical | Low | Before testing |

What should I do next?

Not sure what to do next? Describe your dispute in plain words, add any receipts or messages you have, and follow the step-by-step plan FeudFix builds for you. Your case has its own email inbox — letters go out from it and company replies land in your timeline automatically.