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).
Grade — blocker (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.
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
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-fe → ebit-api → prisma: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
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
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
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)
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