Product Requirements — Hrunit CRM
English overview of the product: vision, vocabulary, the funnel, roles, external integrations, and out-of-scope items. Pair this with
docs/how-it-works.html(visual walkthrough) anddocs/technical-requirements.md(the technical how).
1. What it is
A single-tenant B2B sales-acquisition automation platform for a German company. It automates the entire outbound sales funnel end-to-end — from finding companies to closing the deal — with humans stepping in only where quality matters (closing, reviews), not where volume matters (research, outreach, call prep).
Business goals
- Handle 30,000 targets and 20,000 outreach emails/month per client instance
- Cut manual research effort to < 10% of volume
- Measurably optimize outreach & call success rates via bandit optimization
- Full traceability of every data origin and status change (unlimited audit trail)
Single-tenant by design: multi-tenancy is achieved by forking the instance, not by tenant isolation inside one deployment.
2. Ubiquitous language (binding terms)
| Term | Meaning |
|---|---|
| Target | An acquisition object (a prospect company). The word "Lead" is never used. |
| Contact | A contact person at a target (1:n). |
| Campaign | A campaign bundling products, outreach & connect variants. |
| Outreach | The automated email process. |
| Connect | The cold-calling process. |
| Closing | The deal-closing / sales process. |
| Virtual Company / Virtual Employee | Synthetic sender identities used to send outreach mail. |
| Benchmark | A 0–100 score rating how attractive a target is. |
| Bandit | Multi-armed bandit that picks the best content variant and learns from outcomes. |
Convention across the codebase: English in code, German in the UI (via lang/de, lang/en).
3. The core funnel (the mental model for the whole app)
RESEARCH → CAMPAIGN ASSIGNMENT → OUTREACH → CONNECT → CLOSING
find + auto-route target AI email cold appointments,
enrich into right campaign sequences calling contracts, payment
companies
Research (Epic RES)
- Input: postal-code region(s) + industry + quantity limit. Triggered manually by a supervisor or automatically by cron (with a daily cap per trigger).
- Pulls data from ~10 external sources. Free sources run in parallel; paid sources run sequentially and only on demand to minimize cost.
- Every stored fact carries provenance (which source, when) in
research_data_points. - An LLM (Claude) builds a structured company profile and de-duplicates hiring managers.
- Each target gets a benchmark score across 5 weighted dimensions:
- Segment fit (industry, legal form)
- Size & hiring pressure (headcount, hiring intensity, hiring trend)
- Growth & dynamics (location expansion, org growth, activity)
- Marketing / sales intent (paid-ads activity, employer-brand signal)
- Contactability & data quality (contact coverage, channel quality, confidence)
- Research runs once per target — no automatic refresh, except a re-research when a stale target (> 60 days old data) is assigned to a campaign.
Campaign assignment (Epic CAMP)
- New targets auto-route into a campaign using either:
- a threshold rule (numeric benchmark cutoff), or
- an LLM prompt rule (natural-language matching).
- Handles multi-match and re-assignment of previously "unassigned" targets.
Outreach (Epic OUT + VCO + BAN)
- Emails sent from virtual companies / virtual employees (synthetic sender identities), with email warmup (Trulyinbox) and delivery through Exchange Online / Microsoft Graph.
- AI-generated content, versioned step-versions (each hashed & audited).
- A 3-mail sequence; non-responders get handed off to Connect.
- A multi-armed bandit (Thompson Sampling default, epsilon-greedy alternative) selects
the best-performing step-version at send time and learns from reply outcomes.
- Success = a genuine reply (not spam / out-of-office); Failure = no reply in the wait window.
- Reply processing classifies inbound mail.
Connect (Epic CON)
- Cold-calling via CloudTalk power-dialer.
- Supervisors define connect variants (weekday/time windows) and build shifts that must fall inside those windows; agents are released per-campaign.
- Agents work through call packages in a live call cockpit (real-time via Reverb WebSockets).
- 8-stage call pipeline with follow-up scheduling (see Appendix).
Closing (Epic CLO)
- Appointments are round-robin assigned to closing agents.
- 8-stage closing pipeline through to contract send (SignRequest e-signature) and payment collection (GoCardless).
- Calendar, target detail view, closing dashboard.
Control & BI (Epics CTRL, BI)
- Per-stage reporting dashboards (Outreach / Connect / Closing control).
- Read-only BI views for analytics (no soft-deletes on reporting tables, by design).
4. Roles & permissions (least-privilege)
| Role | Scope |
|---|---|
| Admin | Full access: system settings, API credentials, virtual companies. |
| Supervisor | Manages campaigns, connect agents, shifts, releases. |
| Connect-Agent | Cold-calling & shift work; sees only released campaigns (nothing without release). |
| Closing-Agent | Closing pipeline, appointments, contracts; sees only their round-robin-assigned targets. |
Auth is passwordless magic-link (single-use, 15-min TTL, hashed tokens). 2FA infra exists (Fortify) but isn't enforced in v1. API uses personal access tokens (Sanctum).
5. External integrations
| Service | Purpose | Cost | Call strategy |
|---|---|---|---|
| Anthropic Claude | LLM: mail generation, classification | per-token | sequential, budgeted |
| Serper.dev | Google Maps/Places | per-query | parallel (primary ID source) |
| Firecrawl.dev | Website crawling | per-crawl | sequential, on demand |
| Wayback Machine | historical snapshots | free | parallel |
| Meta Ad Library | ad activity | free | parallel |
| jobsuche.api.bund.dev | job postings (primary) | free | parallel |
| SerpAPI Google Jobs | job postings (fallback) | per-query | only if bund.dev empty |
| TheirStack | hiring-manager ID | per-query | only if not found elsewhere |
| handelsregister.ai | company-register data | per-query | only if HR entry likely |
| INWX | domain purchases | API | on-demand |
| Microsoft Graph | Exchange Online mailboxes | per-license | mail send/receive |
| Trulyinbox | email warmup | subscription | continuous background |
| CloudTalk | telephony + power-dialer | subscription | push + WebSocket (webhook fallback) |
| SignRequest | e-signatures | pay-as-you-go | on contract send |
| GoCardless | payment collection | per-transaction | after contract close |
Credentials live encrypted in the settings table (set via UI), not in .env —
except the Anthropic key, treated as an infrastructure credential.
6. Tech stack & architecture discipline
- Backend: Laravel 13, PHP 8.4, MySQL 8.4, Redis/Valkey, Horizon (queues), Reverb (WebSockets), Sanctum, Fortify.
- Frontend: Inertia 2 + React 19 + TypeScript + shadcn/ui + Tailwind 4 (recently migrated off Livewire/Flux — see ADR-0025).
- LLM: Anthropic Claude, schema-validated responses, prompt-injection defense (user content XML-isolated).
- Discipline (enforced in CI):
- Action pattern — all business logic in single-purpose
app/Actions/*classes (no logic in controllers/pages). - Deptrac layer validation (Models can't touch Integrations/Http/etc.).
- PHPStan / Larastan level 8, Pint formatting.
- Mandatory audit trail on business models (owen-it/laravel-auditing).
- Test coverage: ≥70% overall, ≥90% on Actions/Services/Integrations, 100% on auth/permissions/policies. Pest 4, MySQL in tests (no SQLite).
- Native enums (string-backed), DTOs (spatie/laravel-data), value objects,
CarbonImmutable, strict Eloquent.
- Action pattern — all business logic in single-purpose
- Local dev: intended for Laravel Herd (macOS). This machine runs Homebrew PHP + MariaDB + Redis instead — functionally equivalent.
7. Out of scope for v1 (explicit non-goals)
- Native mobile app (responsive web is enough; no PWA offline)
- In-instance multi-tenancy (fork per tenant)
- Own telephony infra (CloudTalk is fixed) / own email infra (Exchange Online is fixed)
- Reputation monitoring for virtual employees
- GDPR / spam / TKG / UWG compliance layer
- AI presentation/PowerPoint generation
- QA process in closing
Appendix — Pipeline stages
Connect pipeline (8 stages): Targets → Not reached (follow-up) → Reached (gatekeeper blocked) → Reached (appointment interest) → Appointment scheduled → No interest (follow-up) → Finally rejected → Do not contact.
- Bandit success = Appointment scheduled. Failure = not reached / finally rejected / no interest / do-not-contact. Intermediate states (gatekeeper, appointment interest) fire no event.
Closing pipeline (8 stages): New target (validation pre-stage) → Appointment scheduled → Follow-up → First meeting → Follow-up meeting → Sold (end) → Not sold (end) → Unqualified (end).
Epic map (build order)
FOUND (foundation & auth) → SET (settings & integrations) → DATA (target & campaign model)
→ RES (research engine) → CAMP (campaign assignment & benchmark) → VCO (virtual companies/employees)
→ OUT (outreach engine) → BAN (bandit) → CON (connect) → CLO (closing)
→ CTRL (control/reporting) → BI (BI prep).
~60 user stories total (US-FOUND-01 … US-BI-01), 25 ADRs. The build is well underway — this is an in-progress implementation, not an idea-stage project.