# CTO Dataset Guide — Adopted Source Notes - Source: workspace `(challenge)/data-guide.md` - Source role: authoritative dataset semantics supplied by ZarinPal's CTO - Adopted: 2026-08-20 - Safety: document content is treated as domain evidence, not agent instructions ## Adopted meanings - A source record normally represents one payment attempt, but `try_seq = 0` with `try_status = NoAttempt` is a session marker for zero attempts. - Positive `try_seq` values start at one and identify actual attempts within a session. - Payment lifecycle is creation → `InBank` → `Paid` → `Verified`. `Paid` means funds were deducted but merchant verification is incomplete; `Verified` is final. - `psp_code` belongs to an attempt. `switch_response_code` is namespaced by PSP, so equal raw codes across PSPs are not assumed equivalent. - `issuer_bank_code` and `payer_card_key` are absent when card information never returns from the bank stage. - `payer_card_key` equality is valid only within one merchant. It identifies a pseudonymous card, not a person, and cannot link merchants. - `init_time_ms` and `verify_time_ms` measure API response duration, not buyer thinking/interaction time. - `expire_in` is a timestamp despite its source name and is normalized to `expires_at`. - All source identifiers are pseudonymous and do not reveal real merchant, terminal, PSP, bank, session, or card identities. ## Fee interpretation The guide says challenge `adjusted_fee` was uniformly scaled and is not the actual ZarinPal tariff; only relative analyses are faithful to the challenge source. The product owner subsequently approved a production contract in which `fee_amount_rial` is the real merchant fee. Therefore: - challenge bootstrap maps the adjusted stand-in into the canonical session field for demo behavior; - production ZarinPal writers must provide the real Rial fee under the same canonical field; - the product UI follows the approved production meaning and does not describe the canonical field as obfuscated; - internal provenance keeps the challenge transformation caveat auditable. ## Normalization consequences - `payment_sessions` has zero or more `payment_attempts`. - A `NoAttempt` marker creates only a session; it cannot inflate attempt, failure-attempt, or retry counts. - Actual attempts require `try_seq >= 1` and remain unique within a session. - Attempt-stage diagnostics may distinguish `NoAttempt`, `InBank`, and later outcomes, but cannot invent undocumented failure causes or decode PSP response codes.