> ## Documentation Index
> Fetch the complete documentation index at: https://shinydapps-bd9fa40b.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Системные потоки

> Визуальные диаграммы всех потоков платформы l402-kit — платёж, аутентификация, подписка и инфраструктура.

На этой странице задокументированы все основные потоки платформы l402-kit в виде диаграмм последовательностей и блок-схем. Каждый раздел содержит визуализацию и краткое объяснение того, что происходит и почему это работает именно так. Начните с Потока 1 (основной L402), чтобы понять криптографическую основу, затем изучите потоки, актуальные для вашей интеграции.

***

## 1. Основной поток платежей L402

Фундаментальный цикл запросов. Никаких аккаунтов, никаких паролей — только криптографическая квитанция.

Когда клиент впервые обращается к защищённому эндпоинту, он получает ответ HTTP 402, содержащий два элемента: BOLT11 Lightning-инвойс и macaroon. Клиент оплачивает инвойс через Lightning Network (как правило, менее чем за секунду), получает 32-байтовый preimage в качестве доказательства и повторяет запрос с заголовком `Authorization: L402 <macaroon>:<preimage>`. Сервер верифицирует токен локально, используя `SHA256(preimage) === macaroon.hash` — без обращения к базе данных, без сетевого запроса, с задержкой менее миллисекунды. После верификации токен действителен до истечения срока. Последующие запросы повторно используют тот же заголовок.

```mermaid theme={null}
sequenceDiagram
    participant C as Client / AI Agent
    participant S as Your API Server
    participant L as Lightning Network
    participant B as Blink (provider)

    C->>S: GET /api/data (no token)
    S-->>C: 402 Payment Required<br/>WWW-Authenticate: L402 macaroon="...", invoice="lnbc..."

    Note over C,L: Client pays the Lightning invoice
    C->>L: pay(invoice)
    L-->>C: preimage (32-byte proof of payment)

    C->>S: GET /api/data<br/>Authorization: L402 <macaroon>:<preimage>
    Note over S: SHA256(preimage) === macaroon.hash?<br/>Verified in <1ms locally. No DB call.
    S-->>C: 200 OK + data
```

**Ключевые свойства:**

* Верификация полностью локальная — без сетевого запроса, без обращения к базе данных
* `preimage` = криптографическое доказательство оплаты (Lightning-квитанция)
* `macaroon` = base64 JSON `{hash, exp}`, подписанный с помощью SHA-256

***

## 2. Анатомия токена

Заголовок `Authorization` содержит два компонента, разделённых двоеточием. **Macaroon** — это JSON-объект в кодировке base64 `{hash, exp}` — он сообщает серверу, какой хеш платежа ожидать и когда истекает срок действия токена. **Preimage** — это 32-байтовый секрет, который Lightning Network вернула плательщику. Вместе они образуют неподдельный, самодостаточный токен, который любой сервер может верифицировать офлайн.

```mermaid theme={null}
flowchart LR
    T["Authorization: L402 &lt;macaroon&gt;:&lt;preimage&gt;"]
    T --> M["macaroon\nbase64({ hash, exp })\nSigned by SHA-256"]
    T --> P["preimage\n32-byte hex secret\nSHA256(preimage) = hash"]
    M --> V["Server verifies:\nSHA256(preimage) === hash\nexp > now()"]
```

***

## 3. Управляемый режим — поток разделения комиссии

При использовании `ManagedProvider` сайт l402kit.com создаёт инвойс, получает оплату и автоматически перечисляет 99,7% на ваш Lightning-адрес. Комиссия платформы 0,3% покрывает маршрутизацию Lightning и инфраструктуру API. Ваш кошелёк никогда не взаимодействует с Cloudflare Worker напрямую — разделение представляет собой серверный Lightning-платёж, отправляемый после верификации запроса клиента, с использованием вашего Lightning-адреса для генерации нового BOLT11-инвойса на лету.

```mermaid theme={null}
sequenceDiagram
    participant C as Client
    participant V as Cloudflare Worker<br/>/api/invoice
    participant B as Blink API<br/>(ShinyDapps wallet)
    participant S as Supabase
    participant O as Owner wallet<br/>(you@yourdomain.com)

    C->>V: POST /api/invoice<br/>{priceSats, ownerAddress}
    V->>B: lnInvoiceCreate(priceSats)
    B-->>V: {paymentRequest, paymentHash}
    V-->>C: 402 + invoice

    Note over C,B: Client pays invoice
    C->>B: pay(invoice)
    B-->>C: preimage

    C->>V: GET /api/data + L402 token
    V->>S: INSERT payments<br/>{payment_hash, endpoint, amount_sats}
    V->>V: POST /api/split<br/>(fire-and-forget)
    V->>B: sendPayment(owner, 99.7%)
    B-->>O: ⚡ sats received
    V-->>C: 200 OK + data
```

***

## 4. Поток Pro-подписки

Pro-подписки следуют аналогичной схеме L402, но добавляют постоянное состояние. Клиент оплачивает единовременный инвойс и получает 30-дневную запись о подписке в Supabase. Подтверждение платежа поступает либо через Blink-вебхук (быстрый путь, \~2 секунды), либо через опрос (резервный вариант для кошельков, которые не инициируют вебхуки). Последующие вызовы `/api/pro-check` проверяют временную метку `expires_at` без повторной оплаты.

```mermaid theme={null}
sequenceDiagram
    participant U as User (VS Code)
    participant V as Cloudflare Worker
    participant B as Blink API
    participant S as Supabase
    participant W as Blink Webhook

    U->>V: POST /api/pro-subscribe<br/>{lightningAddress, tier}
    V->>B: lnInvoiceCreate(amountSats)
    B-->>V: {paymentRequest, paymentHash}
    V->>S: INSERT pro_access<br/>{address, payment_hash, expires_at: null}
    V-->>U: {paymentRequest, paymentHash}

    Note over U,B: User pays invoice in their wallet
    U->>B: pay(invoice)

    alt Webhook path (fast)
        B->>W: POST /api/blink-webhook<br/>{type: "transaction.ln.invoice.paid"}
        W->>S: PATCH pro_access<br/>SET expires_at = now + 30d
    else Poll path (fallback)
        U->>V: GET /api/pro-poll?paymentHash=...
        V->>B: lnInvoice(paymentHash) → status
        V->>S: PATCH pro_access SET expires_at
        V-->>U: {active: true, expires_at}
    end

    U->>V: GET /api/pro-check?address=...
    V->>S: SELECT expires_at WHERE address=?
    V-->>U: {active: true, tier: "pro"}
```

***

## 5. LNURL-auth — Подтверждение владения кошельком (удаление данных)

Подтверждает, что вы являетесь владельцем Lightning-кошелька, без пароля. Требуется перед удалением данных аккаунта.

```mermaid theme={null}
sequenceDiagram
    participant U as User (VS Code)
    participant V as Cloudflare<br/>/api/lnurl-auth
    participant W as Lightning Wallet<br/>(Phoenix, Blink…)
    participant S as Supabase<br/>lnurl_challenges
    participant D as Cloudflare<br/>/api/delete-data

    U->>V: GET /api/lnurl-auth<br/>?lightningAddress=you@yourdomain.com
    V->>V: k1 = randomBytes(32)
    V->>S: INSERT {k1, lightning_address, expires_at: +5min}
    V-->>U: {k1, lnurl} — show as QR code

    Note over U,W: User scans QR with Lightning wallet
    W->>W: Sign k1 with secp256k1<br/>key derived for this domain
    W->>V: GET /api/lnurl-auth<br/>?tag=login&k1=…&sig=…&key=…
    V->>V: secp256k1.verify(sig, k1, pubkey)
    V->>V: token = randomBytes(32), TTL 10min
    V->>S: PATCH {verified: true, pubkey, token}
    V-->>W: {status: "OK"}

    loop Poll every 2s
        U->>V: GET /api/lnurl-auth?poll=<k1>
        V->>S: SELECT verified, token WHERE k1=?
        V-->>U: {verified: true, token: "abc…"}
    end

    U->>D: POST /api/delete-data<br/>{lightningAddress, token}
    D->>S: SELECT WHERE token=? → verified? expired?
    D->>S: PATCH token = null (revoke — single use)
    D->>S: DELETE payments WHERE owner_address=?
    D->>S: DELETE pro_access WHERE address=?
    D-->>U: {deleted: {payments: N, proAccess: true}}
```

***

## 6. Поток входа в дашборд через LNURL-auth

Аутентификация в дашборде только для владельца — DASHBOARD\_SECRET хранится в секретах Cloudflare Workers.

```mermaid theme={null}
sequenceDiagram
    participant O as Owner browser
    participant V as Cloudflare<br/>/api/lnurl-auth
    participant W as Owner Lightning Wallet
    participant S as Supabase<br/>lnurl_challenges
    participant D as Cloudflare<br/>/api/stats

    O->>V: GET /api/lnurl-auth?dashboard=1
    V->>V: k1 = randomBytes(32)
    V->>S: INSERT {k1, lightning_address: "__dashboard__", expires_at: +5min}
    V-->>O: {k1, lnurl} — show QR code

    Note over O,W: Owner scans QR with their Lightning wallet
    W->>W: Sign k1 with secp256k1 key
    W->>V: GET /api/lnurl-auth<br/>?tag=login&k1=…&sig=…&key=…
    V->>V: key === OWNER_PUBKEY? ✓
    V->>V: secp256k1.verify(sig, k1, key)
    V->>V: token = randomBytes(32), TTL 24h
    V->>S: PATCH {verified: true, pubkey, token, token_expires_at}
    V-->>W: {status: "OK"}

    loop Poll every 2s
        O->>V: GET /api/lnurl-auth?poll=<k1>
        V->>S: SELECT verified, token WHERE k1=?
        V-->>O: {verified: true, token: "abc…"}
    end

    O->>D: GET /api/stats<br/>x-lnurl-token: <token>
    D->>S: SELECT verified, pubkey, token_expires_at WHERE token=?
    D->>D: pubkey === OWNER_PUBKEY? ✓ not expired? ✓
    D-->>O: {totalPayments, totalSats, byDay, trend, recent…}
```

***

## 7. Обзор инфраструктуры

```mermaid theme={null}
flowchart TB
    subgraph CF["Cloudflare DNS (l402kit.com)"]
        DNS["l402kit.com\nCNAME → l402kit-pages.pages.dev"]
    end

    subgraph VCL["Cloudflare (Workers + Pages)"]
        LAND["Landing Page\nbackend/index.html"]
        API["Backend API\n/api/invoice → Edge Function\n/api/delete-data\n/api/lnurl-auth\n/api/pro-subscribe\n/api/stats (LNURL-auth)"]
        HOOK["Webhooks\n/api/blink-webhook"]
    end

    subgraph SB["Supabase (PostgreSQL + Edge Functions)"]
        PAY["payments\npayment_hash · amount_sats\nowner_address · endpoint"]
        PRO["pro_access\naddress · tier\nexpires_at · payment_hash"]
        LNURL["lnurl_challenges\nk1 · verified · token\ntoken_expires_at · pubkey"]
        EF["Edge Function: create-invoice\nBLINK_API_KEY (Supabase Secret)\nBLINK_WALLET_ID (Supabase Secret)"]
    end

    subgraph EXT["External Services"]
        BLINK["Blink Lightning\napi.blink.sv"]
    end

    CF --> VCL
    API --> SB
    HOOK --> SB
    EF --> BLINK
    BLINK --> HOOK
```

***

## 8. Безопасность preimage на основе SHA-256

Почему мы храним `SHA256(preimage)` вместо исходного preimage:

```mermaid theme={null}
flowchart LR
    subgraph Lightning["Lightning Network (public)"]
        INV["BOLT11 Invoice\ncontains payment_hash = SHA256(preimage)"]
    end

    subgraph Client["Client (private)"]
        PRE["preimage\n32-byte secret\nproof of payment"]
    end

    subgraph DB["Supabase payments table"]
        STORED["payment_hash\n= SHA256(preimage)\nsafe to store"]
    end

    PRE -->|"SHA256()"| STORED
    INV -->|"already public"| STORED
    PRE -.->|"❌ never store raw"| DB

    style PRE fill:#ff4444,color:#fff
    style STORED fill:#22c55e,color:#fff
```

**Почему это безопасно:** `payment_hash` уже встроен в каждый BOLT11-инвойс — он публичен по своей природе. Секретным является только `preimage`. Хранение хеша обеспечивает защиту от повторных атак без какого-либо дополнительного раскрытия данных.
