عاملها، حاکمیت، حقوق و صورتحساب · فصل ۳ — Invoice، Subscription، Self-hosted و SaaS · 290
Billing Adapter و External Invoice/Payment References
agent را صرفاً automation میبیند و authority، memory، retry، cost و human escalation را صریح نمیکند. موضوع جاری: «Billing Adapter و External Invoice/Payment References». میتواند برای «Billing Adapter و External Invoice/Payment References» authority، memory/failure boundary و escalation/evidence را در یک agent محدود تعریف کند.
Billing Adapter & External Invoice/Payment References — en-US
خلاصهٔ درس
agent را صرفاً automation میبیند و authority، memory، retry، cost و human escalation را صریح نمیکند. موضوع جاری: «Billing Adapter و External Invoice/Payment References».
میتواند برای «Billing Adapter و External Invoice/Payment References» authority، memory/failure boundary و escalation/evidence را در یک agent محدود تعریف کند.
خروجی این درس
میتواند برای «Billing Adapter و External Invoice/Payment References» authority، memory/failure boundary و escalation/evidence را در یک agent محدود تعریف کند.
پیشنیازها
آبجکت Provider مدرک است، نه دفترکل محصول
یک سفارش SaaS داخل MAKNOW در وضعیت BILLING_PENDING است. Provider یک invoice میسازد، یک event پرداخت را دوبار تحویل میدهد و بعداً موفقیت پرداخت را اعلام میکند. یکی از eventهای قبلی با mapping قدیمی تفسیر شده است. اگر Adapter اجازه دهد status خارجی مستقیم روی business state داخلی نوشته شود، duplicate delivery، مهاجرت Provider، mapping قدیمی و failureهای ناقص پنهان میشوند. در این درس Billing Adapter Canonical-to-Provider Reference & Reconciliation Ledger v1 را میسازیم تا هویت و state داخلی، referenceهای خارجی، event evidence و reconciliation از هم جدا و قابل ممیزی بمانند.
مرز درس و مسیر تصمیم
AGN-012 مالک مرز Billing Adapter است: internal invoice/payment identity، external references، event dedupe، mapping version، amount/currency check، reconciliation و review. AGN-011 مربوط به exit/export/deletion و AGN-013 مربوط به subscription grace/retry/dunning است. مسیر درست از canonical IDهای داخلی و source-of-truth rule محلی شروع میشود؛ سپس reference خارجی، event، dedupe، status mapping نسخهدار، amount/currency و integrity mapping بررسی میشوند و فقط در پایان transition داخلی محدود یا REVIEW/HOLD ساخته میشود.
مدل ذهنی: چهار رکورد را یکی نکن
چهار مفهوم باید جدا بمانند: canonical business record، provider invoice reference، provider payment reference و event/reconciliation evidence. paid شدن invoice لزوماً توضیح نمیدهد MAKNOW چرا باید entitlement بدهد؛ Stripe حتی حالتهایی را مستند کرده که invoice بدون موفقشدن PaymentIntent مرتبط به paid میرسد. از طرف دیگر succeeded شدن PaymentIntent فقط پایان موفق payment flow در Provider را نشان میدهد؛ نه صحت mapping داخلی، currency، policy یا entitlement را.
پایه Ledger
Contract شامل ۲۰ بُعد قابلمشاهده است: billing_adapter_id, provider_id, internal_invoice_id, provider_invoice_id, internal_payment_id, provider_payment_ref, business_state, provider_invoice_status, provider_payment_status, event_id, idempotency_key, dedupe_state, mapping_version, amount_expected, amount_observed, currency, reconciliation_state, reconciliation_reason, manual_review_required, audit_ref. فیلدهای کمکی Lab هم shortcutها را قابلتست میکنند: API version، زمان event، mapping version جاری، target داخلی هر external ref، provider-neutral semantic، authority business state، replay/duplicate flags، currency مشاهدهشده، stale-event evidence، entitlement/refund/error reference و transfer recomputation. هیچ API key واقعی لازم نیست.
Reconciliation از کپیکردن Status قویتر است
مستندات فعلی Stripe چرخه invoice را با stateهایی مثل draft, open, paid, void, uncollectible توضیح میدهد و میگوید subscription در هر billing cycle invoice تولید میکند. همچنین PaymentIntent lifecycle شامل stateهایی مثل requires_payment_method, requires_action, processing, succeeded, canceled است. اینها FACT درباره Provider هستند. authority طراحی MAKNOW از جایی شروع میشود که Adapter میپرسد: آیا external reference هنوز به رکورد داخلی درست وصل است؟ event قبلاً پردازش شده؟ کدام mapping version status را تفسیر کرده؟ amount و currency برابرند؟ transition داخلی طبق policy مجاز است؟ پاسخ فقط با reconciliation rule نسخهدار قابل دفاع است.
Baseline: duplicate همراه با stale mapping evidence
INV-INT-1001 به provider invoice in_9001 و PAY-INT-1001 به provider payment pi_7001 وصل است. amount و currency برابرند. event موفقیت دوبار تحویل میشود؛ تحویل دوم باید DUPLICATE_IGNORED باشد و transition دوم اعمال نکند. در عین حال یک event قدیمی با MAP-STRIPE-v1 وجود دارد، درحالیکه mapping جاری MAP-STRIPE-v2 است؛ این مدرک قدیمی باید برای review حفظ شود. نتیجه محدود RECONCILIATION_REVIEW_REQUIRED است، نه success خودکار محصول.
Mutation: اگر provider_invoice_id به invoice داخلی دیگری map شود ولی reconciliation_state=MATCHED باقی بماند، evaluator باید HOLD_INVOICE_MAPPING_CONFLICT بدهد. اگر currency مشاهدهشده عوض شود ولی amount برابر بماند، HOLD_CURRENCY_MISMATCH لازم است. اگر mapping قدیمی مستقیم entitlement را فعال کند، نتیجه HOLD_STALE_MAPPING_ENTITLEMENT_SHORTCUT است.
Failure modeهای مهم
- Provider status = canonical authority: shortcut را رد کن.
- Replay تکراری با dedupe=NEW: delivery جدید business fact جدید نیست.
- Duplicate با state transition دوم: idempotency شکسته است.
- Provider invoice به internal invoice اشتباه وصل است: MATCHED ناممکن است.
- Provider payment به internal payment اشتباه وصل است: identity conflict.
- Amount یا currency mismatch زیر MATCHED پنهان شده: HOLD.
- Mapping قدیمی مثل mapping جاری استفاده شده: review/recompute لازم است.
- Provider status mapping verify نشده: label خارجی authority ندارد.
- Transfer mapping Provider اول را کپی میکند: بازسازی provider-neutral انجام نشده است.
- Audit یا reconciliation reason ناقص است: transition قابل بازسازی نیست.
Matched، Duplicate-Ignored، Review-Required یا Mismatch
event یکتای معتبر با mapping جاری و amount/currency برابر میتواند RECONCILIATION_MATCHED_REVIEW_READY شود. replay واقعی فقط زمانی DUPLICATE_IGNORED_REVIEW_READY است که transition دوم اعمال نشود. stale mapping، ambiguity یا status semantics نامشخص باید RECONCILIATION_REVIEW_REQUIRED بماند. conflict هویتی، amount یا currency باید HOLD شود. Adapter باید non-success state روشن را به overwrite خاموش ترجیح دهد.
پل برای فرد باتجربه: Migration، API Version و Out-of-band Payment
در migration بین Providerها coupling پنهان گران میشود. قاعدهی بدون نسخهی «paid یعنی paid» نساز. Provider A ممکن است invoice و payment lifecycle جدا داشته باشد و Provider B از statusهایی مثل SETTLED و CAPTURED استفاده کند. حتی در یک Provider، API version میتواند semantics را تغییر دهد. provider/API identity، mapping version و provider-neutral semantic interpretation را ثبت کن. همچنین paid invoice همیشه معادل succeeded PaymentIntent نیست؛ بنابراین invoice evidence و payment-flow evidence را یکی نکن.
تمرین هدایتشده و مستقل
Baseline را اجرا کن و توضیح بده چرا duplicate delivery نادیده گرفته میشود ولی stale mapping هنوز review evidence است. سپس invoice mapping، payment mapping، amount، currency و source-of-truth authority را یکییکی تغییر بده و اولین gate شکسته را نام ببر. یک replay معتبر بساز که بدون transition دوم dedupe شود. در پایان transfer Provider B را بدون استفاده از labelهای Stripe از نو بساز.
چه چیزهایی باید بازسازیپذیر باشند؟
Reviewer باید بتواند بگوید canonical internal invoice/payment کدام است، کدام external ref مشاهده شده، event/idempotency key چه بوده، duplicate بوده یا نه، کدام mapping version status را تفسیر کرده، amount/currency برابرند یا نه، چرا reconciliation به MATCHED/REVIEW_REQUIRED/MISMATCH رسیده، manual review لازم است یا نه و کدام audit record تصمیم را پشتیبانی میکند. جمله «Provider گفته paid» کافی نیست.
Transfer: Provider دیگر با Lifecycle متفاوت
Provider B invoice BILL-44 و payment CAP-88 میدهد و statusهای native آن SETTLED و CAPTURED هستند، نه paid و succeeded. mapping را با semanticهای provider-neutral از نو بساز، identity/amount/currency را verify کن، mapping version جدید بده و تصمیم داخلی را recompute کن. کپی baseline decision یا Stripe status map باید fail شود. با evidence کامل، fixture جدید میتواند به TRANSFER_RECONCILIATION_REVIEW_READY برسد.
Fact / Inference / Design و تازگی منابع
FACT: مستندات فعلی Stripe lifecycle invoice را توضیح میدهد و میگوید subscriptionها در هر billing cycle invoice تولید میکنند. FACT: مستندات فعلی Stripe lifecycle PaymentIntent را توضیح میدهد و در حال حاضر Checkout Sessions را برای اکثر integrationهای جدید توصیه میکند، درحالیکه PaymentIntent همچنان payment-flow object سطح پایینتر است. INFERENCE: جداسازی canonical business state از provider references، auditability dedupe/migration/reconciliation را بهتر میکند. DESIGN: source-of-truth، mapping version، reconciliation، entitlement effect و escalation متعلق به MAKNOW است.
Semantics Provider practice-evolving است؛ تا 2027-01-01 یا زودتر در صورت تغییر مهم API/lifecycle بازبینی شود.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
AGN-012-S1 retrieval
Explain why an external invoice/payment status cannot directly become MAKNOW canonical business state.
AGN-012-S2 application
Build the baseline reconciliation ledger with duplicate delivery and stale mapping evidence.
AGN-012-S3 diagnosis
Keep reconciliation_state=MATCHED while the provider invoice maps to another internal invoice.
AGN-012-S4 transfer
Rebuild the ledger for Provider B with SETTLED/CAPTURED semantics without copying Stripe mapping.
ملاکهای ارزیابی (rubric)
A sufficient submission preserves the AGN-012 boundary, completes all 20 evidence dimensions, keeps internal canonical identity/state separate from provider references, deduplicates replays without a second transition, verifies mapping version and reference integrity, reconciles amount/currency with typed states, preserves stale/ambiguous evidence for review, and recomputes the second-provider transfer from provider-neutral semantics. Provider-status overwrite, hidden mismatch, stale mapping entitlement shortcut, or copied baseline/provider mapping is insufficient.
منابع و تازگی
مطالعهٔ موارد (case studies)
فایلهای آزمایشگاه
در همین پوشه python -B run_checks.py را اجرا کنید. همه رکوردها synthetic هستند؛ هیچ Provider واقعی فراخوانی نمیشود، هیچ پرداخت/Refund/Entitlement تغییر نمیکند و هیچ credential تولیدی استفاده نمیشود.