Skip to content

Acceptance Criteria

Objective, testable criteria for each phase in Phased Rollout. Each criterion has:

  • How to measure — a concrete query, command, or test that produces a yes/no answer.
  • Sign-off — who owns saying "this is met" (customer-pm, customer-sre, customer-eng-lead, customer-compliance, ebit-delivery, joint).
  • Gradeblocker (cannot proceed to next phase) or warning (proceed with documented risk acceptance).

Discipline: criteria phrased so the answer is observable on a system or in a document, not a feeling.

SLA/SLO numbers below come from ../business/nfr-sla.md — that doc is the source of truth. If a number here disagrees with nfr-sla.md, the canonical one wins; flag the discrepancy in a PR.


Phase 1 — Discovery

# Criterion How to measure Sign-off Grade
1.1 Gap analysis written for every subsystem in architecture.md §2 Document exists, every container has one of customer-pm blocker
1.2 Scope decision log signed Document signed by customer-pm and customer-compliance; one row per Phase-1 Activity §3 decision joint blocker
1.3 All long-lead vendor requests submitted Vendor request tracker shows zero rows in not-yet-asked; KYC, payments, captcha, email, license all requested or later customer-pm blocker
1.4 Provisional schedule with named owners Document exists; owner column populated for Phases 2–8 customer-pm warning
1.5 Decision: ebit-bj orphan disposition Decision log row; deprecate (recommended) or wire-up joint warning
1.6 Decision: RabbitMQ stub disposition Decision log row; rip or wire-fasttrack joint warning

Phase 2 — Local stack

# Criterion How to measure Sign-off Grade
2.1 All 16 services healthy in compose docker compose ps shows STATUS (healthy) for: ebit-db, ebit-redis-cache, ebit-redis-bot, ebit-rabbitmq, ebit-prisma-migrate (Exit 0), ebit-api, ebit-rt, ebit-bj, ebit-bo, ebit-speed-roulette, ebit-fe, ebit-admin-fe, otel-collector, jaeger, prometheus, loki, grafana customer-eng-lead blocker
2.2 Stack reaches steady state in < 10 minutes Cold docker compose up -d --build to all-healthy ≤ 10 min on a 16 GB workstation customer-eng-lead warning
2.3 Sign-in works on dropbet local@example.com / password reaches authenticated home at localhost:3000 customer-eng-lead blocker
2.4 Test bet placed and traced Place a dice bet via dropbet; locate the POST /casino/games/house/dice/bets root span in Jaeger; confirm at least 50 child spans (Prisma + Redis + BullMQ enqueue) customer-eng-lead blocker
2.5 Cross-service Playwright canary green cd tests-e2e && pnpm test exits 0 on at least one customer machine customer-eng-lead blocker
2.6 Each engineer has placed a bet locally Per-engineer attestation in the team wiki customer-eng-lead warning

Phase 3 — Stage environment

# Criterion How to measure Sign-off Grade
3.1 terraform apply succeeds Exit 0; terraform output returns grafana_url, jaeger_url, swagger_url, dropbet_url, admin_fe_url customer-sre blocker
3.2 terraform plan is empty after apply terraform plan immediately after apply prints No changes. Your infrastructure matches the configuration. customer-sre blocker
3.3 All 7 ECR repos populated aws ecr describe-images --repository-name ebit/<svc> returns ≥ 1 tagged image for each of api, rt, bj, bo, speed-roulette, ebit-fe, ebit-admin-fe customer-sre blocker
3.4 SUT public URL serves dropbet curl -k $(terraform output -raw dropbet_url) returns HTTP 200 with HTML containing the customer brand string customer-sre blocker
3.5 TLS green Browser visit shows valid certificate; no mixed-content warnings in DevTools customer-sre blocker
3.6 Trace visible end-to-end Sign in on stage dropbet_url, place a dice bet, find the root trace in stage Jaeger; trace contains spans from service_name=ebit-feebit-apiprisma:engine:db_query customer-sre blocker
3.7 Grafana ebit-perf-test dashboard populated Grafana dashboard ebit-perf-test shows ≥ 1 minute of data after the smoke bet customer-sre blocker
3.8 Doppler dev_stage audit clean Run doppler-perf-audit playbook against dev_stage; output diff committed and signed customer-sre blocker
3.9 CI/CD wired Merge to main (or chosen trunk) triggers image build, ECR push, SUT pull, compose up -d; observed end-to-end customer-sre warning
3.10 Zero 0.0.0.0/0 ingress rules in security groups aws ec2 describe-security-groups --group-ids ... shows zero rules with CidrIpv4=0.0.0.0/0 on inbound (egress is unrestricted by design) customer-sre blocker

Phase 4 — Integration

# Criterion How to measure Sign-off Grade
4.1 Test deposit credits balance Submit deposit via the configured payment provider sandbox; webhook hits https://{api-host}/payment/webhook/{provider}; GET /accounting/balances shows the credited amount customer-eng-lead blocker
4.2 Test withdrawal completes Submit withdraw; provider sandbox confirms; balance debited and transaction ledger row written customer-eng-lead blocker
4.3 KYC LEVEL_0 → LEVEL_1 transition Test user submits Sumsub flow; after manual sandbox review, admin endpoint GET /admin/user/<id> shows kycLevel=LEVEL_1 customer-compliance blocker
4.4 Production captcha key in place Sign-up from a fresh browser triggers a real captcha challenge (not the 'pass' bypass); on-success the user is created customer-eng-lead blocker
4.5 Test verification email delivered Sign-up triggers email; email lands in inbox (not spam); link activates the account customer-eng-lead blocker
4.6 Brand assets visible end-to-end Logo, palette, favicon match brand pack on dropbet stage customer-pm blocker
4.7 Locale strings rendered for every supported locale Switch locale via UI; landing page + sign-in + bet flow all render in the chosen locale; no missing-key fallbacks customer-pm warning
4.8 Feature-flag matrix matches the design Run GET /feature-flag/... for every flag; values match the agreed matrix customer-eng-lead warning
4.9 Game catalog matches scope GET /games/catalog returns exactly the games chosen in Phase 1; no out-of-scope titles visible to players customer-pm blocker

Phase 5 — Performance validation

# Criterion How to measure Sign-off Grade
5.1 Stepped ramp completes through stage 4 (5,000 VUs) k6 reaches the end of stage 4 without auto-aborting per the thresholds in performance-testing.md §5 customer-sre blocker
5.2 OR every SLO breach has an owner If 5.1 fails, every breach row in the perf report has a non-empty owner field and a decision of re-baseline or optimization-ticket-# customer-sre blocker
5.3 Performance test report filled out Every {{TBD}} in performance-test-report.md replaced with a measurement or attribution customer-sre blocker
5.4 Auto-abort thresholds verified Test the auto-abort: synthetically inject a 2x-budget breach for 30s and confirm k6 aborts the stage as expected customer-sre warning
5.5 Dice-bet SLO decision documented Decision log row: re-baseline (SLO becomes 150 ms) or optimize (ticket # for PlaceBetService work) — see Risks #7 joint blocker
5.6 Postgres pool saturation observed and tuned If prisma:engine:db_query p95 climbed across services during ramp, customer SRE has tuned connection_limit and / or deployed PgBouncer; re-run shows the pattern resolved customer-sre warning
5.7 Queue stability holds bullmq_queue_jobs{state="wait"} does not sustain a positive slope over any 2-minute window during the test customer-sre blocker
5.8 No OOM kills dmesg and docker events clean for the test window customer-sre blocker

Phase 6 — UAT

# Criterion How to measure Sign-off Grade
6.1 UAT script executed end-to-end Customer QA log shows ≥ 1 pass for every script section (registration, auth, deposit, KYC, bet, withdraw, leaderboard, promo, admin tools) customer-pm blocker
6.2 Zero open P0 defects Defect tracker shows zero rows with priority=P0 AND status=open customer-pm blocker
6.3 Critical & High security findings resolved or accepted docs/security-register.md annotated; every Critical / High row has status=fixed or status=accepted-with-mitigation and a customer signature customer-compliance + customer-eng-lead blocker
6.4 Every runbook validated by support Each file in docs/runbooks/ walked through by customer support; gaps filed as new runbook tickets customer-pm warning
6.5 KYC reviewer training complete Customer compliance team has reviewed at least 5 sandbox submissions end-to-end customer-compliance warning
6.6 Email deliverability ≥ 95% mail-tester.com or equivalent shows a score ≥ 9/10 from the production sender domain customer-eng-lead blocker

Phase 7 — Pilot launch

# Criterion How to measure Sign-off Grade
7.1 Error rate < 0.1% sustained over 7 days PromQL: sum(rate(calls_total{status_code="STATUS_CODE_ERROR"}[1h])) / sum(rate(calls_total[1h])) < 0.001 for every hour over the pilot week customer-sre blocker
7.2 p95 sign-in < 150 ms PromQL: histogram_quantile(0.95, sum(rate(http_server_duration_milliseconds_bucket{http_route="/auth/sign-in"}[5m])) by (le)) < 150 over the pilot window customer-sre blocker
7.3 p95 bet-place per re-baselined SLO If Phase 5 chose re-baseline, dice-bet p95 < 150 ms; if optimize, dice-bet p95 < 100 ms after the ticket lands customer-sre blocker
7.4 Zero P0 incidents during pilot Customer incident log: zero priority=P0 rows during pilot window customer-sre blocker
7.5 On-call runbook validated At least one real or drilled incident handled per a runbook in docs/runbooks/; after-action shows the runbook was sufficient customer-sre blocker
7.6 Daily ops summary maintained One ops summary entry per day for the pilot duration customer-sre warning
7.7 Cohort gate works Users outside the cohort (geo or invite list) are blocked at the appropriate layer (feature flag, country 403, invite redirect) customer-eng-lead blocker
7.8 rt websocket per-instance capacity ≤ 80% If using single replica: in-process clientSockets size < expected single-instance budget. If multi-replica: sticky sessions or Redis adapter verified (Risks #9) customer-sre warning

Phase 8 — GA

# Criterion How to measure Sign-off Grade
8.1 Customer team has run an incident drill solo After-action report exists; Evospin was observer-only; runbooks referenced; escalation matrix exercised customer-sre blocker
8.2 Escalation matrix exercised end-to-end Test page reaches L1 → L2 → L3 in <5 min via the documented tooling customer-sre blocker
8.3 RCA template available Customer wiki carries an RCA template; first 24h of GA collects no incidents OR has at least one RCA started customer-sre warning
8.4 Vendor accounts re-keyed Doppler audit: zero secrets attributed to ebit-personal accounts; every Sumsub, payment, captcha, email, Sentry token is on a customer-owned identity customer-sre blocker
8.5 AWS account ownership transferred Customer holds root credentials, billing alerts, and Terraform state; Evospin roles removed customer-sre blocker
8.6 30-day review on calendar Calendar invite exists with the customer-pm, customer-sre, ebit-delivery; agenda attached joint warning
8.7 Loki retention configured Loki config has explicit retention period matching the data retention policy; verified via loki_chunk_store_index_entries_per_chunk (or equivalent) and a sample old-log query customer-sre blocker
8.8 All Phase-7 acceptance criteria still hold post-GA cohort opening Re-run 7.1–7.5 over the first 24h post-GA; pass customer-sre blocker
8.9 Doppler prd config audited Final audit pass against docs/audits/doppler-perf-audit.md; NODE_ENV=production, real captcha key, no debug-only flags customer-sre blocker

Sign-off mechanics

  • Every blocker must be signed (initial + date) by the named role before proceeding to the next phase.
  • Warnings do not block progression but must be entered into the customer's risk register with a remediation owner.
  • Sign-offs live in a single document the customer PM owns (typically a wiki page per phase).
  • Failed criteria are not silently retried — they trigger a re-plan or a renegotiated criterion.

For the final pre-launch verification sweep across phases, use Launch Checklist.