> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useduro.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How Duro Scores

> The five judged dimensions, each weighted, mapped to exactly where Duro earns it in the system.

This page is for the judges. The rubric has five weighted dimensions; each section below links straight to the chapter and the code-level behaviour that earns it.

| Dimension                     | Weight | Where Duro earns it                                                                                                      |
| ----------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------ |
| **Problem Relevance**         | 20%    | [The thesis](/the-thesis) — recovery-first billing for salary-backed debit cards                                         |
| **Technical Execution**       | 25%    | [The billing engine](/billing/renewal-engine) + [recovery engine](/billing/dunning)                                      |
| **Security & Reliability**    | 20%    | [Security model](/security/security-model) + [multi-tenancy](/architecture/multi-tenancy)                                |
| **Product UX & Clarity**      | 15%    | [API ergonomics](/api-reference/introduction) + [appearance](/platform/appearance) + [portal](/identity/customer-portal) |
| **Payment Integration Depth** | 20%    | [Rails & the gateway abstraction](/billing/payday-and-rails)                                                             |

***

## Problem Relevance · 20%

Duro is aimed at a real, expensive, local problem most platforms ignore: **involuntary churn**. A renewal fails because a salary-backed debit card is empty on the wrong day — the customer wanted to stay, but the money didn't move. It's 20–40% of all churn, and worse where cards are debit and salaries land once a month.

The entire product is organised around recovering that money: a payday-aware retry engine, rail-switching, a live "money at risk → recovered" ledger as the merchant's hero metric. This isn't a feature bolted onto a billing CRUD — recovery *is* the thesis. [Read it →](/the-thesis)

## Technical Execution · 25% — the heaviest weight

The depth is in the engine, and it's real, not a stub.

<CardGroup cols={2}>
  <Card title="A genuine billing loop" icon="rotate-right" href="/billing/renewal-engine">
    A 60-second scanner finds due subscriptions; `BillingService.renew` invoices, charges, advances the period, handles trial-to-active, `maxCycles`, scheduled plan changes, and cancel-at-period-end — with month-end date clamping.
  </Card>

  <Card title="An explicit state machine" icon="diagram-project" href="/billing/subscription-lifecycle">
    Nine states, a transition table, illegal transitions that throw. The table is also the source of truth for webhook event names, so state and events can't drift.
  </Card>

  <Card title="A real worker topology" icon="gears" href="/platform/queues-and-workers">
    Five BullMQ queues, four repeatable scanners, one consistent scan→enqueue→process pattern, dedup by job id, graceful shutdown.
  </Card>

  <Card title="A typed, OOP monorepo" icon="code" href="/architecture/overview">
    `strict` TypeScript, no `any`, no free functions in business logic, exact version pins — and an integration suite that runs the whole money loop against real Postgres on every push.
  </Card>
</CardGroup>

## Security & Reliability · 20%

Isolation **by construction**, plus the results of a deliberate adversarial audit.

* **Tenant isolation that can't be forgotten** — `test` and `live` are separate Postgres schemas, not a `mode` column. Every repository is tenant-scoped at construction; idempotency keys are per-tenant. [→](/architecture/multi-tenancy)
* **Real findings, fixed** — a HIGH-severity webhook **SSRF-to-metadata** vector, a cross-tenant idempotency replay, an unenforced blacklist, mode-scoping leaks — all found, fixed, and tested. [→](/security/security-model)
* **Reliability in the runtime** — single-flight caching (no stampede), retries with backoff on every queue, the `in_flight` guard that prevents double-charges, graceful shutdown with a hard backstop.
* **Secrets done right** — keys and OTPs hashed at rest, timing-safe compares, HMAC-signed webhooks, real credentials only in gitignored env.

## Product UX & Clarity · 15%

Clarity for two audiences — the developer integrating, and the merchant operating.

<CardGroup cols={2}>
  <Card title="API ergonomics" icon="terminal" href="/api-reference/introduction">
    Prefixed IDs, integer minor-units, one error envelope, keyset pagination (page 500 = page 1), per-tenant idempotency, mode implied by the key — and an **interactive playground on every endpoint**.
  </Card>

  <Card title="Operator clarity" icon="gauge" href="/billing/dunning">
    The recovery command center renders "at risk → recovering → recovered," a per-failure breakdown, and a per-subscription retry timeline. The number that matters is the first thing the merchant sees.
  </Card>

  <Card title="Brand once, everywhere" icon="palette" href="/platform/appearance">
    A draft/publish appearance builder themes checkout, the popup, the portal, and emails from one token set.
  </Card>

  <Card title="Customer self-service" icon="user-gear" href="/identity/customer-portal">
    One WhatsApp login, every subscription across every merchant, pause/cancel/fix-card — with ownership enforced.
  </Card>
</CardGroup>

## Payment Integration Depth · 20%

Payments are modelled deeply, not as a single "charge" call.

* **Rails are first-class.** Card, bank transfer, USSD, virtual account, and direct-debit mandate are modelled as distinct rails — and the recovery engine **relays across them** when one fails, in a merchant-configurable order. [→](/billing/payday-and-rails)
* **A clean gateway boundary.** All charging goes through a single `ChargeGateway` interface, so the live rail drops in behind the same callers the simulator runs today. Tokenisation, charge, and transfer surfaces map onto it.
* **Tokens belong to the customer.** A saved card tokenises to a **phone-keyed identity**, reusable across every merchant — the integration is deep enough to power a cross-merchant wallet. [→](/identity/universal-identity)
* **Reconciliation is wired in.** A dedicated payouts/reconcile queue is already in the worker topology, ready for the live rail in July.

<Note>
  The live payment rail lands in the July window; everything charges through a deterministic simulator today so the full loop — renewal, decline, dunning, recovery, webhooks — is testable end-to-end right now.
</Note>

***

Start with [the thesis](/the-thesis), or jump straight to the [recovery engine](/billing/dunning) where the heaviest-weighted execution lives.
