Create your own
Lesson illustration

Testable MVP Acceptance Criteria for Each Growth Workflow Stage

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.

ArtifactAnswersExample
User storyWho needs what, and why?An operator wants to qualify prospects to prioritize outreach.
Acceptance criterionWhat must be true for it to work?A confirmed ICP exclusion disqualifies the prospect and prevents outreach generation.
Automated testHow will software verify the criterion?A test creates an excluded prospect, invokes qualification, and checks its final state.
Definition of DoneWhat 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.

Cucumber BDD Best Practices

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 stageMeaningful commandObservable outcome to specify
Tenant provisioningProvision a client workspaceTenant boundary and owner access exist
Workspace onboardingSubmit configurationWorkspace is ready, or clearly incomplete
Prospect intakeImport prospectsValid records are accepted; invalid records are explained
Research and enrichmentRequest enrichmentEvidence-backed data is saved, or review is required
QualificationEvaluate against ICPProspect is qualified, disqualified, or routed to review
Outreach preparationGenerate and approve a draftA permitted draft is ready; a blocked contact cannot proceed
CRM handoff and activationRoute an approved prospectCorrect pipeline state is reflected without duplicates
Command-center monitoringView pipeline and runsTenant sees only its records, statuses, and actionable failures
Export and offboardingRequest export or close workspaceExport 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.

The diagram shows one user story at the top, several business rules beneath it, and concrete examples attached to each rule. Use this structure to turn a broad workflow capability into testable 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.

IDShared ruleWhy it matters
MVP-CROSS-01Every 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-02Every asynchronous run exposes a final status: completed, failed, blocked, or needs_review.Operators need to know whether action is needed.
MVP-CROSS-03A 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-04A contact cannot enter outreach when a tenant-configured suppression, consent, or frequency restriction blocks it.Compliance controls must beat growth automation.
MVP-CROSS-05A 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-06Retrying 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:

  • completed when sufficient approved evidence supports the output;
  • needs_review when evidence is missing or conflicting;
  • blocked when policy prohibits the action;
  • failed when 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:

StageScenario IDsLikely first validation method
Provisioning and onboardingMVP-PROV-01, MVP-ONB-01API and browser acceptance tests
Intake and researchMVP-INTAKE-01, MVP-RESEARCH-01API acceptance tests with deterministic fixtures
QualificationMVP-QUAL-01, MVP-QUAL-02Service-level acceptance tests
OutreachMVP-OUT-01, MVP-OUT-02API and approval-flow tests
CRM handoffMVP-CRM-01Connector contract test plus integration test
OperationsMVP-OPS-01Browser or API acceptance test
Exit lifecycleMVP-EXIT-01API 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:

  1. Does it name the actor and active tenant?
  2. Is its starting state reproducible without another scenario?
  3. Does the action represent a meaningful command, not a UI click sequence?
  4. Is each expected result observable?
  5. Does it describe what happens when data is missing, policy blocks the action, or the integration is retried?
  6. Does it avoid assuming an implementation technology?
  7. Can you identify whether it belongs primarily to an acceptance, security, connector, or manual test?
  8. 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