عاملها، حاکمیت، حقوق و صورتحساب · فصل ۳ — Invoice، Subscription، Self-hosted و SaaS · 291
Subscription, Grace & Dunning
Design a bounded subscription state machine that separates contract/subscription state, invoice/payment collection state, grace policy, dunning/retry schedule, entitlement state and human escalation; classify retryable versus non-retryable evidence, cap attempts and grace windows, and make every access change traceable to explicit product policy rather than a provider status shortcut. میتواند برای «Subscription, Grace و Dunning» authority، memory/failure boundary و escalation/evidence را در یک agent محدود تعریف کند.
Lesson summary
Design a bounded subscription state machine that separates contract/subscription state, invoice/payment collection state, grace policy, dunning/retry schedule, entitlement state and human escalation; classify retryable versus non-retryable evidence, cap attempts and grace windows, and make every access change traceable to explicit product policy rather than a provider status shortcut.
میتواند برای «Subscription, Grace و Dunning» authority، memory/failure boundary و escalation/evidence را در یک agent محدود تعریف کند.
This lesson produces
میتواند برای «Subscription, Grace و Dunning» authority، memory/failure boundary و escalation/evidence را در یک agent محدود تعریف کند.
Who it is for
Foundation
Use a field map, one worked scenario and explicit state vocabulary before independent construction.
Repair
Identify the failed evidence dimension, use the smallest mutated fixture and rerun only the affected gate.
Experienced
Compress definitions; require trade-off defense, counterexample analysis and changed-context transfer.
Prerequisites
A payment failure is not an access-revocation instruction
A monthly subscription fails collection two hours before renewal. If the system collapses past_due or payment_failed directly into entitlement, it can revoke access too early, retry a non-retryable failure, or preserve grace indefinitely. This lesson builds Subscription Entitlement, Grace, Retry & Dunning State Machine v1 so subscription, invoice/payment, retry, dunning, grace, entitlement and escalation have separate states and authority.
Lesson boundary and decision route
AGN-013 owns recovery and entitlement policy after collection failure. AGN-012 owns external invoice/payment references and AGN-014 owns self-hosted release/support; those outcomes remain separate. Classify the failure first, close retry eligibility and attempt budget, compute the grace boundary, apply notification/dunning, and only then derive entitlement and customer action from product policy, not from a raw provider status.
Mental model: five state machines, not one
Keep Contract/Subscription, Collection, Retry/Dunning, Grace, and Entitlement distinct. invoice.payment_failed is collection evidence. attempt_count and next_payment_attempt can be retry evidence. None of these fields alone says whether access should be FULL, LIMITED, SUSPENDED or REVOKED. That requires a versioned grace/entitlement policy.
State-machine foundation fields
Identity starts with subscription_id and invoice_id. Collection uses payment_state and failure_class. Retry uses retry_eligible, attempt_count, next_attempt_at, and retry_policy_ref. Customer communication uses dunning_policy_ref and notification_state. Grace is bounded by grace_policy_ref, grace_started_at, and grace_expires_at. Access is explained by entitlement_state, entitlement_reason, and customer_action_required. recovery_state, policy_version, and audit_ref make the decision reconstructable.
Retryability, grace and entitlement answer different questions
Current Stripe documentation says hard-decline-like failures are not automatically retryable without a new payment method, while retry scheduling/telemetry can still exist. Therefore next_payment_attempt or a rising attempt_count must not be treated blindly as proof that a retry is currently executable or allowed. MAKNOW closes failure classification and local retry policy first, then computes grace and entitlement separately. Even a retryable failure does not automatically imply FULL access; the product policy can specify LIMITED access during grace.
Baseline: retryable failure inside a seven-day grace window
Subscription SUB-M-001 and invoice INV-1001 have a retryable failure. Policy permits three attempts and seven days of grace. Attempt one is recorded, the next attempt is in the future, the failure notice is sent, and entitlement is LIMITED while grace is active. The bounded result is RECOVERY_REVIEW_READY because retry eligibility, budget, grace boundary, entitlement reason and audit evidence all close—not because of a provider status.
Mutation: set the failure to NON_RETRYABLE while keeping retry_eligible=true and a future next_attempt_at. The evaluator must return HOLD_NONRETRYABLE_RETRY_CONFLICT. If grace has expired while entitlement remains FULL without a valid override, it must also hold.
Important failure modes
- Provider status = access policy:
past_duemust not directly set entitlement. - Non-retryable + retry scheduled: contradictory state.
- Unbounded attempts: recovery has no finite stop.
- Grace without an expiry: unauditable unless the explicit policy is NO_GRACE.
- Expired grace + stale access: entitlement must be recomputed.
- Duplicate failure after recovery: must not trigger new dunning.
- Manual override without owner/ref/expiry: exception lacks authority.
- Copying monthly behavior into annual/no-grace: transfer was not recomputed.
Retry, customer action, or grace exit
For a retryable failure with remaining budget, RETRY_SCHEDULED can become review-ready. A non-retryable failure disables retry and moves toward CUSTOMER_ACTION_REQUIRED. After grace expiry with payment still failed, entitlement must move according to policy and recovery can become EXHAUSTED or enter cancellation. None of these decisions is justified by vendor status alone.
Experienced bridge: event idempotency and policy versioning
If you already work with billing webhooks, focus on idempotency and policy versioning. A duplicate event after recovery must not send another notice or reopen dunning. Changes to retry/grace policy should apply according to the recorded policy_version and effective time. A state without audit evidence or policy identity cannot be explained later.
Guided and independent practice
Run the baseline and explain why LIMITED access during grace is separate from payment state. Then mutate the failure to non-retryable, expire grace, and exceed the attempt budget; name the exact blocker for each mutation. Independently mark recovery successful and inject a duplicate payment_failed event; new escalation must be suppressed.
What must be reconstructable?
A reviewer must see subscription/invoice identity, payment/failure state, retry eligibility and budget, next attempt, dunning/notification, grace start/end, entitlement reason, customer action, recovery state, policy version, and audit reference. If entitlement reduces to “because Stripe says past_due,” evidence is incomplete.
Transfer: annual, no grace, non-retryable
The second subscription is annual, has no grace period, and has a hard-decline-like failure requiring a new payment method. The monthly baseline is not an oracle. Recompute: disable retry, set next_attempt_at=NONE, require customer action, move entitlement to SUSPENDED under the no-grace policy, and compute cancellation/escalation from the new policy. A positive review state is allowed only when transfer evidence was actually recomputed.
Fact / Inference / Design and freshness
FACT: Stripe Billing documents retries and evidence such as invoice.payment_failed, attempt_count, and next_payment_attempt, and describes hard declines as not automatically retryable without a new payment method. FACT: Stripe presents retries, customer notifications, and automations/dunning as separate recovery capabilities. INFERENCE: separating recovery from entitlement prevents a transient provider failure from silently becoming an access-control decision. DESIGN: retry count, grace window, notification sequence, entitlement/cancellation, and manual-override authority remain MAKNOW product policy.
Provider behavior is practice-evolving and must be rechecked by 2027-01-01 or earlier on material semantic change.
Assessment
There is no answer key in this lesson pack; answer it yourself and mark honestly. "Needs review" sends the lesson to your review queue.
AGN-013-S1 retrieval
Explain why payment/provider status cannot directly define entitlement.
AGN-013-S2 application
Build the baseline state machine for the monthly retryable failure.
AGN-013-S3 diagnosis
Change failure_class to NON_RETRYABLE while retry_eligible remains true and next_attempt_at remains scheduled.
AGN-013-S4 transfer
Recompute annual/no-grace/hard-decline behavior without copying monthly behavior.
Assessment rubric
A sufficient submission preserves the lesson boundary, completes all required evidence dimensions, rejects provider-status shortcuts and contradictory retry/grace states, uses a bounded policy version/audit trail, and recomputes the transfer case without copying the baseline result. Any unsupported success state, infinite retry/grace behavior, or hidden manual exception is insufficient.
References & freshness
Case studies
Lab files
در همین پوشه python -B run_checks.py را اجرا کنید. همه رکوردها synthetic هستند؛ هیچ پرداخت، اشتراک، entitlement یا پیام مشتری واقعی تغییر نمیکند و هیچ credential تولیدی استفاده نمیشود.