Acceptance criteria written just before closeout are already late
Acceptance criteria are not a requirements list drafted at the final review meeting. What counts as done has to be settled before the work, and that standard then judges the tests and the closeout. Defining customer acceptance criteria as clearly as possible before work begins, and using them as the basis for acceptance tests, is the common guidance across work-tracking tooling.[6]
Acceptance criteria need at least six elements: which features, systems, environments, and data are in scope; what result counts as complete; which of test results, logs, repositories, documents, and configuration records will be submitted; who re-checks in which environment; who decides READY, READY WITH CONDITIONS, and HOLD; and under what conditions an incomplete item may remain.
Without that structure, the review meeting becomes the place where "it mostly seems to work" collides with "we finished development".
Why split functional acceptance from operational acceptance?
The two gates are related, but they do not answer the same question.
The UK government's service readiness guidance likewise separates user acceptance testing, integration testing, and non-functional testing from operational acceptance testing. It also asks for tested recovery plans, open defects, security issues, data migration, and the named operational owner after handover.[7]
A finished functional review does not finish the operational one. Conversely, receiving every operational document does not pass the functional gate if a core feature misses the agreed criteria.
- Functional acceptance gate
- The functional gate confirms that the agreed requirements were built — core flows, allow and deny by role, calculations and data changes, external integrations, non-functional criteria, and the open defects and excluded scope.
- Operational acceptance gate
- The operational gate confirms that the receiving organization can control the system without the supplier — source, build, deployment, accounts, data, recovery, security, monitoring, and the maintenance boundary.
Verification that supports a release decision — Verify critical journeys and connect observed results and remaining conditions to the release decision.
What does the acceptance matrix ask?
In the table below, F means functional acceptance, O means operational acceptance, and B means the item affects both gates. For each area, record what to agree, the required evidence, what the receiver runs, and the typical HOLD condition.
READY WITH CONDITIONS is used only when the risk scope, the interim workaround, the owner, and the deadline are all set. HOLD means the technical and operational handover is not being completed in the current state. What that verdict does to payment or legal ownership belongs to the contract and to legal review, and is out of scope here.
Area | Gate | What to agree | Required evidence | What the receiver runs | Typical HOLD condition |
|---|---|---|---|---|---|
| Requirements and acceptance criteria | F·B | Requirement ids, applied versions, completion conditions, and exclusions are fixed | Requirement list, acceptance test results, incomplete and exception list | Sample-trace core requirements to results and confirm the exception approver | Criteria were changed after the fact, or core requirements have no result |
| Source code | O | Application code, DB migrations, build and deploy scripts, config templates, and required IaC within the agreed scope are included | Final commit and tag, repository list, source archive hash, LFS and submodule list | Trace which commit produced the deployed production version | The production version differs from the delivered source, or core code is missing |
| Repository ownership | O | The receiving organization, not a personal account, controls the repository and org settings | Owning organization, admin list, teams and permissions, branch rules, webhook and deploy key list | Have the receiving owner change settings, permissions, and protection rules | Only the vendor's person or org owns it and the client is merely a collaborator |
| Build reproducibility | O | Artifacts can be rebuilt from the named source revision in a documented environment | Runtime and compiler versions, lockfile, base image, build command, logs, artifact hash or provenance | Build directly on a clean runner or new machine | It builds only on one developer's machine or from an unreachable private registry |
| Deployment procedure | O | The receiving organization can deploy to test and production with its own accounts | Pipeline definition, deployment runbook, environment list, config and secret reference model, health checks | Have the receiving team deploy to a non-production environment and check the result | Undocumented manual steps or a vendor account are required |
| Credential and account ownership | O | Accounts are held by the organization, no shared personal accounts. Permissions, recovery factors, MFA, and secret lifecycle are defined | Account and role inventory, recovery contacts, MFA status, secret rotation and revocation records | Sign in with your own accounts and rotate or revoke vendor access | Only the vendor controls the root admin or recovery email, or credential provenance is unknown |
| Domain, DNS, cloud accounts | O | The receiving organization controls registrant, billing entity, recovery contact, root admin, and renewal responsibility | Registrar, DNS zone, cloud account, billing, and support inventory | Confirm rights to change DNS, renew the domain, and open cloud support cases | The domain, root account, or billing account exists only in the vendor's name |
| Data export and migration | B | Scope, format, retention, and consistency checks for the data in scope are agreed | Data dictionary, schema, export and migration scripts, row count, sum, and hash verification results | Run an export and import on a sample or in an isolated environment | There is no complete export path, or counts, amounts, and relations cannot be verified after migration |
| Backup and restore | O | Not only backup creation but restoration to the agreed data point | Policy, storage location, recent success records, restore test report, measured duration | Restore a recent backup in an isolated environment and check the application | Only "backup succeeded" logs exist with no restore test, or the receiving team cannot reach the backups |
| Security findings | B | Verification scope, method, versions, and all open findings are disclosed | Security test report, secret scan, open findings, retest results, risk acceptor and deadline | Sample-check that disclosed findings match the current deployed version | Critical open issues lack impact, mitigation, and an owner, or secrets remain in the code |
| Dependencies and licences | O | Internal and external components needed to run, their access paths, and end-of-support status are known | Lockfile, SBOM, private package list, component version, hash, licence, and EOL data | Fetch, install, and build every dependency in a new environment | A required private package is unreachable, or nobody knows who maintains it |
| Monitoring | O | Operational state is visible and alerts reach someone who can act | Dashboards, alert rules, log access and retention, notification routes, runbooks | Fire a test alert and verify the receive, acknowledge, and act path | Operational visibility exists only in vendor accounts, or no one receives the alerts |
| Documentation | O | Documents match the final version and are specific enough to reproduce real work | Architecture, data flow, API, batch and cron, deployment, backup, incident, account inventory | Perform a build, a deployment, or a restore from the documents alone | Key steps live only as spoken knowledge, or the documents describe an older version |
| Known issues | F·B | All known defects, constraints, and technical debt are disclosed with their impact | Issue id, affected version, reproduction steps, severity, workaround, owner, target date | Reproduce sample issues and confirm current state and workaround | Issues affecting core business, security, or data are hidden, or have no owner |
| Warranty and maintenance boundary | O | Defects, change requests, operational work, and external outages are classified technically with intake and adjudication steps | Classification table, support channels, hours, evidence requirements, escalation, external vendor boundary | Check that both sides classify the same sample ticket the same way | After an incident, no organization owns intake, adjudication, or action |
| Operational owner | O | Responsible roles and deputies are named for system, source, cloud, data, security, and incident response | RACI or owner register, owners and deputies, access verification records | Have the actual owner take part in the first deployment, restore, and alert drill | Only an abstract team name exists, with no named person holding the actual rights |
Receiving the source code is not enough
Receiving a source archive and controlling the software are different things. You need to know which commit and tag produced the final production version, and you need to inherit the repository that still holds issues, pull requests, releases, and settings. On GitHub, transferring a repository lets the new owner manage not only the content but the issues, pull requests, releases, projects, and settings.[1] Webhooks, secrets, and deploy keys can stay attached too, so permissions and secrets need a separate audit after the move.
The repository must not depend on a single person either. GitHub recommends multiple owners per organization precisely because access can be lost if one owner becomes unreachable.[8] Read that not as one product's feature but as the operating principle that source control rights should not concentrate in an individual.
Projects that do not use GitHub face the same bar. Whatever the platform, the receiving organization has to directly control the repository, access rights, change history, protection policy, and package registry.
Not every project needs a bit-for-bit reproducible build
The strict definition of a reproducible build is that anyone, from the same source, build environment, and instructions, produces a bit-for-bit identical artifact. Confirming it needs the source revision, dependency versions, build flags, environment variables, and artifact hashes.[9]
But the minimum acceptance bar for every SI project need not be bit-for-bit identity. Splitting it into two levels by risk is more workable. The baseline is a rebuildable build: check out the delivered source revision in a clean environment, use pinned runtimes and dependencies, and produce a runnable artifact.
Systems with high security, regulatory, or supply chain risk add artifact hashes and build provenance. SLSA provides a build track and provenance verification structure that traces whether software was tampered with and which source produced it.[2] Whichever level you choose, "it built on the vendor developer's laptop" is not acceptance evidence. The receiving team has to rebuild it in its own environment.
Accept accounts as control, not as a password list
Collecting plaintext passwords in a handover document is not a good handover. Build an inventory of accounts and permissions first, and separate organization-held accounts from personal ones. Move secrets through an approved secret manager or a safe channel, and rotate or revoke every key and password the vendor knew once acceptance completes.
OWASP recommends managing secrets through a lifecycle of creation, rotation, revocation, and expiry, and revoking any secret that is no longer needed or may have been exposed.[3] Usage records and administrative actions must be auditable too.
These accounts are the ones most often missed: domain registrar and DNS; cloud, hosting, and database; CI/CD and package registries; external APIs such as email, SMS, payment, and maps; app stores and mobile signing; monitoring, logging, and security tools; backup storage and encryption keys; and SaaS billing and support accounts. Each needs an owner, an administrator, a billing entity, a recovery email, MFA, a renewal date, and a vendor access end date.
Take the restore result, not the backup file
A backup list or a "last backup succeeded" screen tells you nothing about recoverability. What acceptance needs is the result of an actual restore test.
Confirm at least seven things: which point in time was restored; into which environment; how long it took; whether the application started normally on the restored data; whether users, permissions, attachments, and external storage were included; what was used to verify consistency afterwards; and who owns the encryption keys and accounts the restore requires.
Operational acceptance asks for a restore test not to design a separate recovery architecture. It is to confirm that a backup already inside the deliverable actually works under the receiving organization's own rights and procedures. The UK government's service readiness review likewise treats workable, tested contingency, continuity, and rollback plans as items to confirm.[7]
A dependency list does not end at the build file
package.json, pom.xml, and requirements.txt are starting points. Real acceptance needs eight more pieces: exact components and versions; direct and transitive relationships; private packages and access rights; component hashes; applicable licences; end-of-support or deprecation status; the external SaaS and APIs production depends on; and who owns dependency replacement and updates.
Multi-nation joint SBOM guidance covers organizations that buy or operate software, not only those that build it. The minimum elements include component versions, dependency relationships, hashes, licences, and the SBOM tooling and version.[10]
An SBOM does not dissolve every security risk. But it gives a starting point for judging vulnerabilities, end of support, and licence impact, which is more than you have while not knowing what you run.
The goal of a security review is not a zero-vulnerability certificate
A security deliverable needs at least the tested version, scope, method, criteria, date, findings, and retest results. Open findings carry impact, mitigation, risk acceptor, owner, and a deadline.
OWASP ASVS can serve as the basis for verifying technical security controls in a web application and its runtime, and for defining procurement requirements.[11] NIST likewise directs acquirers to confirm not just a supplier's claim of having verified, but the verification results, configuration and implementation information, open vulnerabilities, and remediation.[4][12]
What matters is not the line saying a security check was done, but whether five questions can be answered: what was tested and what was not; which version and environment were tested; what remains open; what should block production right now; and who fixed it or accepted the risk, and when.
Operations connected from observation to improvement — Respond using service indicators and alerts, then connect change records and incident reviews to improvements.
Monitoring has to connect to accounts and to people
Receiving a dashboard URL is not accepting monitoring. The receiving organization needs access to logs and metrics, and alerts have to reach someone who will actually respond. Google SRE stresses that an alert should signal a user-visible problem, be urgent, and be actionable by its recipient.[5] Every paging alert must be actionable.
So it is worth firing one test alert during acceptance. Check that it arrives on the right channel, that the responder can find the runbook, and that they can sign in with the operational accounts they need. If the alert fires but nobody receives it, or the dashboard is visible only from vendor accounts, operational acceptance is not finished.
Leaving a known issue and hiding one are different
You do not have to fix every known issue before accepting. An issue with limited impact, a workaround, a named owner, and a deadline can be left under conditions.
Even so, a known issue needs at least seven pieces of information: the affected version and feature; reproduction steps; user, data, security, and operational impact; the interim workaround; the fix owner; the target date; and the effect on the acceptance verdict.
"To be improved later" is not a plan. Issues that can halt core business, bypass authorization, corrupt data, or block recovery must not be downgraded to leftover work.
Settle the technical classification before the legal one
The distinction below is not there to decide legal liability. It is the technical and operational classification that decides which desk a ticket goes to when an outage or a request arrives. Actual cost, responsibility, duration, and legal effect follow the contract and separate legal review.
When the two sides classify the same event differently, response never starts. While the vendor calls it additional development and the client calls it an existing defect, the outage stays. So the classification criteria, the required evidence, the first adjudicator, and the escalation path have to be set before acceptance.
Situation | Technical or operational classification | What to settle before acceptance |
|---|---|---|
| Agreed acceptance criteria and actual behaviour differ | Candidate defect | Reproduction evidence, severity, fix and retest procedure |
| A new feature or changed business rule is requested | Candidate change request | Impact analysis, approval, separate schedule and cost estimation |
| Incorrect operational data or configuration causes an outage | Candidate operations or data support | Configuration and data owner, and recovery responsibility |
| An external API or SaaS fails or changes its spec | External dependency incident | First responder, vendor contact, workaround and fallback scope |
| A runtime or library security patch or end of support | Candidate maintenance or upgrade work | Monitoring, update decision maker, regression verification responsibility |
In the acceptance meeting, rerunning beats demonstrating
Six steps work well in practice. First, fix the acceptance candidate: bundle the source tag, artifact version, database schema, deployment environment, and acceptance matrix version. Second, the vendor presents evidence first — functional results, build and deploy logs, account lists, data verification, restore tests, the security report, and known issues.
Third, the receiving team performs the same work again. It clones the repository with its own accounts, builds, and deploys to a non-production environment. Data export and import, backup restore, and a test alert are sampled too. Fourth, exceptions go into a separate register: for each missing item, record impact, workaround, owner, completion date, re-review method, and current verdict. Fifth, transfer account ownership: confirm the receiving owner and recovery factors, then reduce vendor access to what is needed and rotate or revoke secrets. Sixth, sign the functional and operational gates separately, so it is clear whether functions passed while operational acceptance is on HOLD, and which items are conditional.
A demonstration shows that the vendor can do it. The receiving team's rerun shows that the organization keeps running without the vendor. Those are different pieces of evidence.
When conditional acceptance works, and when to stop
Conditional acceptance is not permitted merely because some items are incomplete. Four things must all hold: the impact is bounded; a workaround keeps production running; a fix owner and deadline exist; and the incomplete item does not remove the receiving organization's independent ability to change, deploy, and recover.
Eight states, by contrast, are reasons to stop operational acceptance: the final production source and repository are not under your control; the receiving team cannot build in a clean environment; deployment or production access requires a vendor account; the domain, DNS, cloud root admin, and recovery factors were not handed over; whether a complete data export is possible is unknown; backups exist but no restore test does; critical security issues or hard-coded secrets have no owner; and no one receives production alerts or owns incident response.
What matters more than the number of documents is whether the receiving organization can own the system's next change and next incident.
The completion condition for software acceptance
Software acceptance is not the act of ticking every box on a feature list. The receiving organization has to be able to answer yes to one question: if the vendor stops participating tomorrow, can we describe the current state of this software, change the source, rebuild, deploy, migrate data, recover, and respond to security problems and incidents?
Answering that needs ownership, workable procedures, verification evidence, and clear operational owners — not more documents. Splitting the functional gate from the operational one is what finally makes it possible to say precisely what is finished and what still stands as risk.



