Welcome back. You now have two foundational artifacts for the product: a tenant lifecycle and a configurable ICP policy. The lifecycle tells you where a client and its data move through the system; the ICP defines how a tenant describes good-fit accounts without hard-coding one industry’s sales motion.
This lesson turns those ideas into a buildable MVP contract. You will write testable acceptance criteria for every essential stage of the growth workflow: tenant setup, onboarding, lead intake, research, qualification, outreach, CRM handoff, operational visibility, and export or offboarding. The aim is not to prescribe FastAPI endpoints or database tables yet. It is to make product behavior precise enough that you can later implement, test, review, and demonstrate it.
Acceptance criteria are the contract for “working”
A user story captures a user’s goal and its value:
As a growth operator, I want to qualify imported prospects against my tenant’s ICP so that I can prioritize accounts that deserve outreach.
Acceptance criteria define the conditions under which that story is genuinely complete. They turn “qualify prospects” from a vague feature label into observable behavior with a pass or fail result.
| Artifact | Answers | Example |
|---|---|---|
| User story | Who needs what, and why? | An operator wants to qualify prospects to prioritize outreach. |
| Acceptance criterion | What must be true for it to work? | A confirmed ICP exclusion disqualifies the prospect and prevents outreach generation. |
| Automated test | How will software verify the criterion? | A test creates an excluded prospect, invokes qualification, and checks its final state. |
| Definition of Done | What quality bar applies to all completed work? | Tests pass, documentation is updated, and the increment meets its criteria. |
For this product, good criteria must be:
- Observable: a user, API consumer, or test can see the outcome.
- Binary: the result is either satisfied or not satisfied.
- Specific about scope: it names the relevant tenant, user role, record, and workflow state.
- Independent: it includes its own setup rather than relying on another test having run.
- Outcome-oriented: it says what the system must do, not whether you used a particular React component, FastAPI route, or Claude prompt.
- Safe by default: failure, missing evidence, missing authorization, or a blocked contact must lead to an explicit safe outcome.
For example, this is not testable enough:
“The system imports leads quickly and prevents bad data.”
It leaves “quickly,” “bad,” and “prevents” undefined.
This is testable:
Given an owner in organization “Northstar” uploads an Airtable import containing one valid domain and one malformed domain, when the import is processed, then the valid prospect is created in Northstar’s workspace, the malformed row is rejected with a visible reason, and no prospect is created in another organization.
The first statement describes an aspiration. The second supplies a fixture, action, observable result, and an important tenant-isolation boundary.
Watch “Cucumber BDD Best Practices” from The-Ohayo-Dev for a concise explanation of the Given/When/Then structure. Treat it as a writing discipline for product specifications, not as a requirement to adopt Cucumber immediately.
Watch scenario structure. Focus on the distinction between a Given precondition, a When action, and a Then assertion. Notice why an action placed after a Then makes a scenario harder to understand and automate.
A useful shorthand is:
- Given establishes an independently reproducible starting state.
- When expresses one meaningful user or system action.
- Then verifies a result that matters to the business.
- And adds another condition of the same kind when it remains clear.
Begin with the workflow, not a list of screens
Before drafting scenarios, map the significant things that happen in the product. For a growth command center, this is especially useful because several actions are asynchronous: an import may queue work, enrichment may produce incomplete evidence, and a CRM handoff may need to be retried safely.
The basic flow is:
| Growth stage | Meaningful command | Observable outcome to specify |
|---|---|---|
| Tenant provisioning | Provision a client workspace | Tenant boundary and owner access exist |
| Workspace onboarding | Submit configuration | Workspace is ready, or clearly incomplete |
| Prospect intake | Import prospects | Valid records are accepted; invalid records are explained |
| Research and enrichment | Request enrichment | Evidence-backed data is saved, or review is required |
| Qualification | Evaluate against ICP | Prospect is qualified, disqualified, or routed to review |
| Outreach preparation | Generate and approve a draft | A permitted draft is ready; a blocked contact cannot proceed |
| CRM handoff and activation | Route an approved prospect | Correct pipeline state is reflected without duplicates |
| Command-center monitoring | View pipeline and runs | Tenant sees only its records, statuses, and actionable failures |
| Export and offboarding | Request export or close workspace | Export is controlled; closed tenants cannot run work |
The wording in the last column is deliberate. “The background worker runs” is an implementation detail. “The operator sees a completed run with the created prospect IDs and rejected-row reasons” is a product outcome.
The Story–Rule–Example technique is a reliable bridge between a broad product intent and executable acceptance scenarios.

For example:
- Story: As a growth operator, I want the system to qualify a prospect so that I can focus effort on accounts matching the tenant’s ICP.
- Rule 1: A confirmed negative-ICP criterion always overrides positive fit signals.
- Rule 2: Missing required evidence produces
needs_review, not a qualified result. - Rule 3: A qualification result must be visible only inside the active tenant.
- Example for Rule 1: A prospect in an explicitly excluded industry has matching employee count and geography, but is still disqualified.
- Example for Rule 2: A prospect has no evidence for employee count, which is required by the tenant’s policy, so the system routes it to review.
Each example can become a scenario. The rule explains why it exists; the scenario makes it possible to prove that it works.
BDD with Event Mapping | Cucumber
Read “BDD with Event Mapping” from Cucumber. It connects a timeline of business events and commands to concrete examples and then to Given/When/Then scenarios—an especially useful method for your automation-heavy workflow.
In the opening discussion, read the Event Storming explanation. Then read the Example Mapping explanation. Finally, in the subsection “A Gherkin scenario is basically a micro-timeline,” read the event-to-scenario mapping. As you read, translate “events” into workflow outcomes such as prospect_import_completed or qualification_review_required; you do not need to decide their database representation yet.
Establish a small, safe MVP boundary
Your full product vision includes research, qualification, outreach, CRM workflows, content, reporting, and recommendations. The MVP criteria should establish a thin but complete vertical workflow, rather than claiming that every future automation capability is already autonomous.
For this blueprint, use the following MVP boundary:
In scope
- A platform operator can provision a tenant and assign an initial owner.
- A tenant owner can complete required onboarding configuration.
- An operator can import prospects from an approved source.
- The system can record research evidence and represent incomplete research safely.
- A prospect can be qualified, disqualified, or sent to review using the tenant’s ICP policy.
- The system can create an outreach draft, require approval, and block prohibited outreach.
- An approved prospect can be handed to the supported CRM workflow.
- Tenant users can inspect prospects, workflow states, and failures.
- A tenant can request export and be offboarded through a controlled process.
Explicitly out of scope for this first slice
- Autonomous, unreviewed message sending.
- Open-ended web crawling or use of unapproved sources.
- A universal scoring model for every industry.
- Autonomous growth recommendations.
- A large library of CRM and marketing integrations.
Those exclusions do not weaken the product. They prevent the MVP from quietly becoming an unsafe collection of assumptions. Human review is a valid and valuable MVP state.
Cross-cutting rules for every workflow stage
Do not repeat these in full under every user story. Put them in a shared “MVP workflow rules” section, then reference them by identifier.
| ID | Shared rule | Why it matters |
|---|---|---|
MVP-CROSS-01 | Every read, write, workflow run, and visible result is scoped to the active organization. | Tenant isolation is product behavior, not merely a database concern. |
MVP-CROSS-02 | Every asynchronous run exposes a final status: completed, failed, blocked, or needs_review. | Operators need to know whether action is needed. |
MVP-CROSS-03 | A failed or blocked step records a safe, actionable reason without exposing another tenant’s data or secret credentials. | Failure must be diagnosable without leaking sensitive data. |
MVP-CROSS-04 | A contact cannot enter outreach when a tenant-configured suppression, consent, or frequency restriction blocks it. | Compliance controls must beat growth automation. |
MVP-CROSS-05 | A confirmed exclusion overrides a positive ICP match. Missing required evidence does not become a positive match. | This preserves the green/yellow/red/unknown policy from the ICP design. |
MVP-CROSS-06 | Retrying the same externally visible handoff does not create a duplicate CRM object. | Retries are normal in distributed automation. |
These are intentionally product-level rules. In later modules, you will decide exactly how Supabase policies, worker idempotency keys, GoHighLevel connectors, audit logs, and Claude validation enforce them.
The MVP acceptance-criteria suite
The following scenarios are a strong first version of the acceptance contract. They use neutral business language and concrete outcomes. You can later automate some through browser or API tests, while others will need connector contract tests and manual acceptance checks.
@MVP-PROV-01 @provisioning
Scenario: A provisioned tenant owner enters only the assigned workspace
Given organization "Northstar" has been provisioned with owner "owner@northstar.test"
And "owner@northstar.test" has accepted the organization invitation
When the owner signs in and selects the active workspace
Then the active workspace is "Northstar"
And the owner can view Northstar workspace data
And the owner cannot view data belonging to another organization
@MVP-ONB-01 @onboarding
Scenario: Incomplete onboarding cannot activate growth workflows
Given the owner of "Northstar" has not configured a target region
When the owner attempts to mark the workspace ready for growth operations
Then the workspace remains not ready
And the missing field "target region" is identified to the owner
And no import, qualification, or outreach workflow can be activated
@MVP-INTAKE-01 @prospect-intake
Scenario: An import accepts valid prospects and explains rejected rows
Given an operator in "Northstar" has an approved import containing one valid domain and one malformed domain
When the operator starts the import
Then a prospect is created for the valid domain in Northstar
And the malformed row is rejected with a visible reason
And the import run records completed with accepted and rejected row counts
And no prospect is created outside Northstar
@MVP-RESEARCH-01 @enrichment
Scenario: Missing evidence routes a prospect to review rather than inventing attributes
Given prospect "Harbor Systems" belongs to "Northstar"
And the approved research sources contain no evidence for its employee count
When an operator requests enrichment for "Harbor Systems"
Then no employee count is stored as confirmed
And the prospect enrichment state is "needs_review"
And the run records that employee-count evidence was unavailable
@MVP-QUAL-01 @qualification
Scenario: A confirmed ICP exclusion disqualifies an otherwise attractive prospect
Given "Northstar" excludes the industry "consumer_retail"
And prospect "Harbor Systems" has confirmed industry "consumer_retail"
And the prospect meets Northstar employee-count and geography preferences
When an operator starts qualification for "Harbor Systems"
Then the prospect qualification state is "disqualified"
And the reason is "strategic_exclusion"
And the system does not create an outreach draft for the prospect
@MVP-QUAL-02 @qualification
Scenario: Missing required fit evidence requires human review
Given "Northstar" requires employee count for green ICP qualification
And prospect "Pine Labs" has no confirmed employee-count evidence
When an operator starts qualification for "Pine Labs"
Then the prospect qualification state is "needs_review"
And the result identifies employee count as the missing required evidence
And the prospect is not automatically routed to active outreach
@MVP-OUT-01 @outreach
Scenario: An approved and permitted prospect receives an outreach draft for review
Given prospect "Pine Labs" is qualified for "Northstar"
And its selected contact is not suppressed
And the tenant has an active approved outreach profile
When an operator requests an outreach draft
Then a draft is created in a reviewable state
And the draft identifies the prospect and tenant campaign context
And the draft cannot be activated until an authorized reviewer approves it
@MVP-OUT-02 @outreach
Scenario: A suppressed contact cannot enter an outreach workflow
Given prospect "Pine Labs" is qualified for "Northstar"
And its selected contact is suppressed from outreach
When an operator requests an outreach draft or activation
Then the outreach action is blocked
And the operator sees the suppression reason
And no message or campaign action is scheduled
@MVP-CRM-01 @crm-handoff
Scenario: Retrying a completed CRM handoff does not create duplicates
Given approved prospect "Pine Labs" has a completed CRM handoff for run "run-123"
And the handoff has recorded remote contact and opportunity identifiers
When the system retries handoff run "run-123"
Then the handoff remains completed
And the recorded remote identifiers remain unchanged
And no additional CRM contact or opportunity is created
@MVP-OPS-01 @command-center
Scenario: An owner sees actionable workflow status for the active tenant
Given "Northstar" has one completed import run and one failed CRM handoff
And another organization has workflow runs of its own
When the Northstar owner opens the command center
Then the owner sees only Northstar prospects and workflow runs
And the failed handoff shows its stage, safe error reason, and retry state
And the owner does not see the other organization's data
@MVP-EXIT-01 @export-offboarding
Scenario: Completed offboarding disables new growth operations
Given "Northstar" has completed its approved data export
When a platform operator completes offboarding for Northstar
Then new growth workflows cannot be started for Northstar
And tenant users cannot enter the Northstar workspace
And the offboarding action is recorded for operational review
A few design choices in these scenarios are worth noticing.
“Needs review” is a successful safe outcome
The enrichment and qualification scenarios do not treat missing information as a system failure. They verify that the system refuses to pretend it knows something it does not know.
That distinction will matter when you add Claude-powered research. A model returning a plausible employee count without evidence is not a successful enrichment. For your product, the correct result is often:
completedwhen sufficient approved evidence supports the output;needs_reviewwhen evidence is missing or conflicting;blockedwhen policy prohibits the action;failedwhen a technical dependency cannot complete after permitted retries.
Preventing action is an acceptance outcome
Many teams only write happy-path criteria: “a draft is created,” “a contact is synced,” or “a campaign runs.” But a multi-tenant growth platform is defined just as much by the actions it correctly declines to take.
The criteria above explicitly prove that the product:
- does not activate an incomplete workspace;
- does not turn unknown evidence into a green qualification;
- does not override an exclusion with a preference;
- does not send or schedule outreach for a suppressed contact;
- does not duplicate CRM records when work is retried;
- does not expose cross-tenant operational data;
- does not continue automation after offboarding.
These are the conditions most likely to prevent expensive operational mistakes later.
Keep scenarios declarative and implementation-neutral
A scenario should describe intent and business-visible results, rather than a sequence of UI clicks.
Overly imperative
Given I click the prospects tab
When I click the import button
And I choose the Airtable file picker
And I click submit
Then I see a green toast
Declarative
Given an operator in "Northstar" has an approved prospect import
When the operator starts the import
Then valid prospects are created in Northstar
And rejected rows show a reason
The declarative form survives a redesign from a modal to a drag-and-drop upload, or from a browser action to an API workflow. It also makes a better contract between you and Claude Code when you later ask it to implement a bounded feature.
One caution: declarative does not mean vague. “Then the import works” is too abstract. “Then rejected rows show a reason” is observable and specific.
Product Backlog Building Canvas
Read the acceptance-criteria and readiness sections of Martin Fowler’s “Product Backlog Building Canvas.” The article distinguishes a story from the checklist that proves it is complete, then shows how criteria support a practical definition of ready and done.
In “Filling out the user story,” read the acceptance-criteria explanation. Compare its ATM example with the scenarios above: each condition is independently verifiable. Then, in “Defining Ready and Done,” read the Definition of Ready discussion, followed by the PBI ready checklist. Use it to identify where a scenario still lacks fixtures, a policy decision, an expected result, or a known dependency.
Turn the scenarios into a working product artifact
Create this file now:
docs/product/mvp-acceptance-criteria.md
Structure it as follows:
# MVP Acceptance Criteria
## Product scope
- In scope
- Explicitly out of scope
- Supported import source and CRM connector for v1
## Shared workflow rules
- MVP-CROSS-01 through MVP-CROSS-06
## Workflow map
- Stage
- User or system command
- Expected business outcome
- Acceptance-criteria IDs
## Acceptance scenarios
- MVP-PROV-01
- MVP-ONB-01
- MVP-INTAKE-01
- MVP-RESEARCH-01
- MVP-QUAL-01
- MVP-QUAL-02
- MVP-OUT-01
- MVP-OUT-02
- MVP-CRM-01
- MVP-OPS-01
- MVP-EXIT-01
## Test approach
- Acceptance test candidates
- Connector contract test candidates
- Manual acceptance checks
- Security and tenant-isolation test candidates
## Open product decisions
- Supported import format for v1
- Initial CRM pipeline and stage mapping
- Required onboarding fields
- Default contact suppression behavior
- Who may approve outreach and offboarding
Add a small traceability table beneath the scenarios:
| Stage | Scenario IDs | Likely first validation method |
|---|---|---|
| Provisioning and onboarding | MVP-PROV-01, MVP-ONB-01 | API and browser acceptance tests |
| Intake and research | MVP-INTAKE-01, MVP-RESEARCH-01 | API acceptance tests with deterministic fixtures |
| Qualification | MVP-QUAL-01, MVP-QUAL-02 | Service-level acceptance tests |
| Outreach | MVP-OUT-01, MVP-OUT-02 | API and approval-flow tests |
| CRM handoff | MVP-CRM-01 | Connector contract test plus integration test |
| Operations | MVP-OPS-01 | Browser or API acceptance test |
| Exit lifecycle | MVP-EXIT-01 | API acceptance test and operational checklist |
For Claude-powered behavior, keep the acceptance criterion stable while making the test deterministic. In a test environment, a controlled model response or test double can return known evidence, conflicting evidence, or no evidence. The product requirement remains the same: evidence-backed data proceeds; insufficient evidence is visible and safe.
Before treating a scenario as ready for implementation, review it with this checklist:
- Does it name the actor and active tenant?
- Is its starting state reproducible without another scenario?
- Does the action represent a meaningful command, not a UI click sequence?
- Is each expected result observable?
- Does it describe what happens when data is missing, policy blocks the action, or the integration is retried?
- Does it avoid assuming an implementation technology?
- Can you identify whether it belongs primarily to an acceptance, security, connector, or manual test?
- Does it stay small enough to implement as one bounded feature increment?
If any answer is “no,” refine the rule or split the scenario. Do not solve ambiguity by telling the developer to “use best judgment”; make the product decision visible.
You now have a testable MVP contract for the complete growth workflow. The core pattern is consistent: establish a tenant-scoped state, perform a meaningful command, and verify an observable outcome—including the safe outcomes of review, blocking, failure, and idempotent retry.
Next, you will define the canonical entities behind these criteria and decide which system—Supabase, GoHighLevel, or Airtable—is the source of truth for each one.
Can't find a good explanation? Sign up and we'll make it for you
Sign up