# TFB v1.7.0 Acceptance Report

## Inventory outcome
- ALREADY_OK preserved: inline quiz options, result/CTA order, free-text fallback, admin workspace cleanup, campaign routing, export/import base, webhook/admin auth, htaccess, PDO reuse, compact logs.
- FIXED: RF1–RF33 items classified NEEDS_FIX in `TFB_SECONDARY_OPS_PHASE0_INVENTORY.md`.

## Root causes
- Global Telegram retries had no update_id table/middleware.
- Student callbacks had an injected callback repository but did not claim IDs.
- Admin cleanup happened before callback claim.
- Session uniqueness and Back/Answer were service-only and nontransactional.
- Secondary was a flat per-test list with no single-active transaction, categories, keyboard or multistage state.
- Start routing consulted default behavior before the global active-secondary override.
- Code safety backup depended on files channel and previously risked live config inclusion.
- ZIP validation lacked uncompressed caps; swap wrote live files directly; update failure had no automatic code rollback.
- Health executed migrations; pump/reminders/cache/retention lacked concurrency controls.

## Acceptance

### Secondary
S1 PASS · S2 PASS · S3 PASS · S4 PASS · S5 PASS · S6 PASS · S7 PASS · S8 PASS · S9 PASS · S10 PASS · S11 PASS · S12 PASS · S13 PASS · S14 PASS · S15 PASS

### Keyboard
K1 PASS · K2 PASS · K3 PASS · K4 PASS · K5 PASS

### Reliability
R1 PASS · R2 PASS · R3 PASS · R4 PASS · R5 PASS · R6 PASS · R7 PASS

### Ops
O1 PASS · O2 PASS · O3 PASS · O4 PASS · O5 PASS · O6 PASS · O7 PASS · O8 PASS · O9 PASS · O10 PASS · O11 PASS · O12 PASS · O13 PASS · O14 PASS

### Host pressure
H1 PASS · H2 PASS · H3 PASS · H4 PASS · H5 PASS · H6 PASS · H7 PASS · H8 PASS

### Regression core
G1 PASS · G2 PASS · G3 PASS · G4 PASS · G5 PASS · G6 PASS · G7 PASS

### Agent proof
P1 PASS · P2 PASS · P3 PASS · P4 PASS · P5 PASS

## Operational behavior
- Secondary: one active test, existing rows backfilled to category 1, one category per click, bounded page size/time, callback/update dedupe, no quiz completion writes.
- Update: local secret-free code backup first; optional Telegram copy; compressed/uncompressed checks; unique tmp; temp+rename; current Migrator; code rollback; terminal FA with `storage/logs/update.log`.
- Restore: safety DB backup; SQL danger denylist; chunked import; forward migration; safety reapply on failure.
- Retention: processed callbacks/updates 14 days; old logs/tmp sweep via locked pump.

## Minimal agent locks
1. A zero-width Telegram message is used only as the secondary ReplyKeyboard carrier because copied media cannot carry inline and reply keyboards simultaneously.
2. A category is delivered in bounded pages of 20; an oversized category gets «ادامه همین دسته» before category-next buttons.
3. Imported tests remain drafts with `secondary_enabled=0`; categories/items are retained.
4. Code safety backup is always local; Telegram upload is optional and non-blocking.
5. Expired operation locks are automatically broken on the next operation; active locks are refreshed at progress stages.

## Residual risks
- Shared-host file replacement cannot be perfectly atomic across every filesystem.
- Brief OPcache lag can occur after update.
- Telegram file_id values are not portable across bot tokens.
- Very large DB restores can still hit host execution time despite chunking.
- No backup encryption, package PKI, or destructive DB down-migration in this release.

## Persian smoke
1. یک secondary را روشن و تلاش برای روشن‌کردن دومی را بررسی کنید.
2. bare `/start`، لینک secondary و لینک تست عادی را تست کنید.
3. multistage OFF و ON، سه دسته و دکمه‌های بعدی را تست کنید.
4. دکمه‌های «استارت/راهنمایی/پشتیبانی» و حذف keyboard هنگام ورود quiz را تست کنید.
5. روی Start/Back/Next دوبار سریع بزنید؛ محتوا یا session نباید تکرار شود.
6. update را یک‌بار با files-channel غیرفعال اجرا کنید.
7. ZIP خراب را ارسال کنید؛ FAIL باید مسیر `storage/logs/update.log` بدهد.
8. backup/restore قدیمی را اجرا و health را بررسی کنید: schema_ok=true, pending=0.
