Topics / Engineering practice

A SOC 2 report and a pentest do not answer every product question.

Requirements-based verification fills that gap. Agree what the software must do, test how it can break that promise, and keep the results tied to the version checked.

A focused correctness audit is one way to start. Keep the scope small: one workflow your existing checks leave uncertain.

Start with one workflow. You do not need to share your repository on the first call.

Read the scope before reusing the conclusion.

SOC 2, penetration testing and business-logic verification overlap. The useful question is whether your existing work establishes the particular promise you need to rely on.

SOC 2

An examination of controls against the applicable Trust Services Criteria. Processing integrity can be part of the scope.

Ask: Does our report cover this system and processing objective? Which controls, period and exceptions apply?

Penetration testing

A scoped investigation of security weaknesses. It can include business-logic abuse, workflow bypasses and timing attacks.

Ask: Did the engagement exercise this rule, including the relevant roles, retries and failure paths?

Business-logic verification

Checks of explicit product promises against the implementation. For example, one successful payment must not produce two charges.

Ask: What ran, what state did it inspect, and what does that result establish for this revision?

A missing test is a gap to close, not a reason to discard an existing assessment. Reuse relevant evidence. Add the checks needed for the rule and its consequences. No single assessment establishes every possible application behavior.

Sources: AICPA’s SOC 2 reporting guide and OWASP Web Security Testing Guide v4.2: Business Logic Testing. Reviewed 9 October 2026.

The account is protected. The invoice is wrong.

Imagine a subscription upgrade that succeeds, times out before the response reaches the client, then runs again on retry. Authentication worked. Both requests were authorized. The customer still paid twice.

Illustrative billing requirement

A retry of the same accepted upgrade must return the original outcome without adding another charge.

The billing owner must define what identifies the same operation, how long retries are supported, and how a changed request is handled. These are product decisions, not facts to infer from whichever behavior the code currently has.

Turn that agreement into observations. A successful HTTP response is not enough; inspect charges, subscription state and the operation record.

  1. Retry after success

    Send the same operation again. Check that the original outcome returns and the charge count stays at one.

  2. Two requests at once

    Race identical operations. Check that concurrent execution cannot create a second charge or a conflicting subscription state.

  3. Timeout after payment

    Interrupt the path after the provider accepts payment. Retry and reconcile the recorded payment with the subscription update.

  4. Same key, different request

    Reuse an operation key with a different plan or amount. Check the agreed conflict response and that no new charge is created.

  5. Retry-window boundary

    Exercise just before, at and after the agreed expiry. Check that retention and cleanup match the promised retry behavior.

These are proposed checks for an illustrative workflow, not executed billing results. They do not cover every billing risk: proration, currency rounding, refunds and provider reconciliation need their own requirements.

Have a workflow like this? Bring the rule and the failure you worry about.

Scope a business-logic review ↗

What useful evidence looks like.

Here is a small example you can inspect and rerun. A reservation service must return the original reservation when the same key is retried before 24 elapsed hours. Changing key retention to 12 hours breaks that promise.

Executed teaching fixture · Python + SQLite

One configuration change. Two failing cases.

A · 24-hour retention
5 cases pass
B · 12-hour retention
3 pass, 2 fail
C · 24-hour retention restored
5 cases pass

At 12 and 23 hours, snapshot B creates a second reservation. The checks compare both reservation identity and count, so the returned response cannot hide the duplicate.

The limit: the author supplied the draft requirement and dependency mapping. This is not a customer result. It uses an injected clock and does not test concurrency, replicas or restarts. Passing snapshots remain unaccepted; the assembled packages lack traced per-requirement execution evidence.

Walk through the failure and repair ↗

Inspect the failing inputs and observations, the revisions and execution provenance, or the instructions to rerun the fixture. The fifth case checks expiry at exactly 24 hours, outside the promised retry window.

For findings in real projects, see the public evidence register. Each case has its own scope; the reservation example is a teaching fixture.

Find the gap in one workflow.

Pick a behavior with a costly failure: duplicate payments, a lost reservation, a cross-tenant read, or a migration that drops records. Fill this out with the person who owns the promise and the engineer who can run the checks.

BUSINESS-RULE EVIDENCE CHECKLIST

Workflow and owner:
Promise, source and who agreed it:
Inputs, boundaries and failure conditions:
State that must change:
State that must remain unchanged:
Existing SOC 2 / pentest / test evidence relevant to this rule:
Missing scenarios and the check for each:
Requirement version, code revision and configuration:
Observed result and a link to the execution:
Untested conditions or conflicting expectations:
Decision needed, owner and next action:
What change would require these checks to run again:

Download the plain-text checklist ↓ · No email required.

If the expected result is disputed, resolve the requirement first. If a result is missing, mark it missing. If the implementation changed after the run, check whether the evidence still applies. Filling the fields does not make the workflow verified.

For a deeper test plan, continue to requirements-based testing or change impact analysis.

Where Proof fits.

Proof connects requirements to code, hazards, checks and retained change records. That gives your team and coding agents a shared account of what must hold and which evidence supports it. Recovered intent still needs the right authority; current code is not automatically the specification.

A focused engagement starts with one component or recurring defect. We agree the behavior and scope, investigate the risky paths, run the relevant checks, and retain the results with their limitations. A finding should point to a violated promise and an inspectable observation. An unresolved product decision stays visible.

The next change should reuse that work: the requirement, regression check and reason behind it remain available, while affected evidence needs to be checked again. This complements your security testing and assurance program. It does not replace a SOC 2 examination or guarantee a clean audit.

Before you add another assessment.

Should I ask my pentester to cover this first?

Yes, if the concern is business-logic abuse within their expertise and scope. Agree the rules, roles, concurrency and workflow cases explicitly. Use engineering verification for the broader set of product promises and for keeping relevant checks current as the code changes.

We already have unit tests. What would be different?

Start by inspecting them. A test can pass because it repeats an implementation assumption or checks only the response. The useful addition is an expected result grounded in an agreed rule, exercised through the relevant implementation path, with the resulting state checked too.

Do we need formal verification for every rule?

No. Use concrete scenarios, boundary checks, property tests or concurrency tests where they establish the claim you need. Formal methods can help with suitable high-consequence properties, but the model, assumptions and connection to the running code still matter.

Can this work without a complete requirements document?

Start with one workflow and its owner. Recover candidate intent from contracts, tickets, support cases and code; resolve disagreements before using it as the expected result. You do not have to model the whole product to investigate one important promise.

Try it on your software

Bring a business rule your current checks leave uncertain.

Tell us what should happen, what could go wrong, and what you already test. We will discuss whether a focused Proof engagement fits and what evidence the first scope should produce.

The first call is a scoping conversation. Your repository stays closed. Code access, confidentiality and the work itself are agreed separately.

Keep your controls, pentest and development process. Scope a behavior audit around one consequential rule, such as billing or authorization. If you also want the fix implemented, include that work through the factory.

See a sample scope and the evidence you keep →