> ## 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 の 2 つが含まれています。クライアントは Lightning Network を通じてインボイスを支払い（通常 1 秒未満）、支払い証明として 32 バイトの preimage を受け取り、`Authorization: L402 <macaroon>:<preimage>` を付けてリクエストを再試行します。サーバーは `SHA256(preimage) === macaroon.hash` を使ってローカルでトークンを検証します — データベース呼び出しも、ネットワークのラウンドトリップも不要で、1 ミリ秒未満のレイテンシです。検証されると、トークンは有効期限まで有効です。以降のリクエストでは同じヘッダーが再利用されます。

```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` = SHA-256 で署名された base64 JSON `{hash, exp}`

***

## 2. トークンの構造

`Authorization` ヘッダーはコロンで区切られた 2 つのコンポーネントを持ちます。**macaroon** は base64 エンコードされた JSON オブジェクト `{hash, exp}` です — サーバーに対して、どの支払いハッシュを期待するか、そしてトークンの有効期限を伝えます。**preimage** は Lightning Network が支払者に返した 32 バイトのシークレットです。この 2 つが組み合わさることで、どのサーバーもオフラインで検証できる、偽造不可能な自己完結型の認証情報を形成します。

```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 Address に自動的に転送します。0.3% のプラットフォーム手数料は Lightning ルーティングと API インフラストラクチャをカバーします。あなたのウォレットは Cloudflare Worker に直接触れることはありません — 分配はクライアントのリクエストが検証された後にサーバー側で発火する Lightning 支払いであり、あなたの Lightning Address を使ってオンザフライで新しい 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 パターンに従いますが、永続的な状態を追加します。クライアントは一度限りのインボイスを支払い、Supabase に 30 日間のサブスクリプションレコードを受け取ります。支払いの確認は 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["外部サービス"]
        BLINK["Blink Lightning\napi.blink.sv"]
    end

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

***

## 8. SHA-256 Preimage のセキュリティ

生の preimage ではなく `SHA256(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` だけです。ハッシュを保存することで、追加のリスクなしにリプレイ保護が実現できます。
