-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Summary
Add an optional subscription model for paid Archon access using Archon's own verifiable credentials as auth tokens. Customers subscribe (e.g., $1/month, $10/year), receive a SubscriptionCredential issued to a group DID, and use the credential DID as their auth token for API requests.
A new optional service called Drawbridge handles subscription auth, proxies requests to backend services, and manages resource-consuming operations like IPFS uploads.
Motivation
Per-operation micropayments (#75) are elegant but impractical for most customers. Real users want predictable pricing — subscribe once, use the API freely for the subscription period.
Rather than building a separate auth system, this uses Archon's own credential infrastructure: a verifiable credential proves the holder has an active subscription. The credential DID serves as the API auth token. This dogfoods Archon's core technology and requires no new auth mechanisms beyond credential verification.
Deployment Model
Drawbridge is entirely optional. Running your own Archon node for personal use requires no changes — the core services (gatekeeper, keymaster, hyperswarm, mediators) work exactly as they do today with no auth gateway.
Drawbridge is for operators who want to offer paid access to others. It follows the same opt-in pattern as cl-hive — a separate compose file included only when needed:
# docker-compose.yml
include:
- docker-compose.btc-mainnet.yml
- docker-compose.btc-signet.yml
- docker-compose.cln-mainnet.yml
- docker-compose.drawbridge.yml # opt-in: adds subscription-based accessWhen Drawbridge is not included, clients talk directly to gatekeeper/keymaster as they do today. When included, Drawbridge sits in front as the customer-facing entry point.
Architecture
Gatekeeper-Compatible Interface
Drawbridge implements the same API interface as the Gatekeeper. Wallets already know the Gatekeeper API, so Drawbridge is a drop-in replacement — clients point at a Drawbridge URL instead of a Gatekeeper URL with zero code changes, just a config change.
This means:
- Existing wallet code works unmodified — swap the URL, get subscription auth transparently
- Drawbridge proxies standard Gatekeeper endpoints (DID create/resolve/update/delete, IPFS) to the actual Gatekeeper behind it
- Drawbridge extends the interface with additional endpoints for registration, payment, and subscription management
- The
GatekeeperClientTypeScript class can target either a plain Gatekeeper or a Drawbridge — the caller doesn't need to know which
Service Responsibilities
Drawbridge orchestrates across multiple backend services:
- Gatekeeper — DID resolution, group membership verification
- Keymaster — credential verification (validity, expiry, revocation)
- CLN — payment handling (Lightning invoices for subscription purchases)
- IPFS — data uploads (delegated from gatekeeper to Drawbridge)
- Redis — usage tracking and rate limiting
Client → Drawbridge → Gatekeeper (DID resolution, group membership)
→ Keymaster (credential verification)
→ CLN (subscription payments)
→ IPFS (data uploads, metered by subscription tier)
→ Redis (usage counters, rate limiting)
Drawbridge is the customer-facing API entry point. It handles subscription auth, enforces tier-based resource limits, and proxies authorized requests to the appropriate backend service.
Group-Based Subscription Auth
A wallet holds multiple DIDs (identities). Rather than requiring a subscription per DID, the subscription credential is issued to a group DID. The wallet automatically manages group membership — adding new DIDs when created, removing them when deleted.
This means:
- One subscription per wallet, not per identity
- Auth is tied to identity, not a bearer token — Drawbridge verifies the requesting DID is a member of the subscription group
- A leaked credential DID is useless without a DID that's actually in the group
- The user never thinks about subscription management — the wallet handles group membership transparently
Usage Tracking (Redis)
Drawbridge uses Redis (already in the stack) to track per-subscription usage:
drawbridge:usage:{credentialDid}:dids:{month}— DIDs created this monthdrawbridge:usage:{credentialDid}:uploads:{month}— bytes uploaded this monthdrawbridge:ratelimit:{credentialDid}— sliding window request counter
Usage is tracked per subscription credential DID (shared across all DIDs in the group), not per individual identity DID. Keys use TTL-based expiry aligned to billing periods.
IPFS Delegation
When Drawbridge is deployed, IPFS upload handling moves from the gatekeeper to Drawbridge. Storage has real costs (disk, bandwidth, pinning), so routing uploads through Drawbridge makes them subscription-gated and metered by tier.
The gatekeeper retains IPFS read access (resolving CIDs for DID documents). Without Drawbridge, the gatekeeper handles uploads directly as it does today — no behavior change for personal nodes.
Wallet Bootstrap Flow
New wallets connecting to a Drawbridge-protected node need zero prior state. The bootstrap is a single round-trip:
- Wallet connects to the Drawbridge URL, makes a request
- Drawbridge returns HTTP 402 with subscription info (available tiers, pricing, payment methods)
- Wallet has no subscription credential — requests a free-tier registration from Drawbridge's unauthenticated registration endpoint
- Drawbridge bootstraps everything in one operation:
a. Creates a new DID for the wallet
b. Creates a group DID owned by the new DID
c. Adds the new DID to the group
d. Issues a free-tierSubscriptionCredentialto the group DID - Wallet receives the credential — everything it needs is derivable from that single credential: its DID, the group DID (credential holder), and the subscription credential DID
- Subsequent requests include the credential DID + requesting DID, normal auth flow takes over
For existing wallets (already have DIDs from another node), the flow skips step 4a — the wallet presents its existing DID, Drawbridge creates the group and credential around it.
Adding future DIDs to the subscription is automatic — the wallet adds new DIDs to the group it already owns. No re-registration needed.
Upgrade Flow
- Wallet requests an upgrade (e.g., free → pro)
- Drawbridge returns a Lightning invoice for the subscription price
- Wallet pays the invoice
- Drawbridge updates the
SubscriptionCredentialwith the new tier and expiry - Higher limits take effect immediately
Subscription Lifecycle
| Action | Mechanism |
|---|---|
| Register | Unauthenticated bootstrap: create DID + group + free-tier credential |
| Add identity | Wallet adds new DID to the subscription group (group owner controls membership) |
| Remove identity | Wallet removes DID from the subscription group |
| Upgrade/downgrade | Update the credential with new tier and scope |
| Renew | Update the credential with a new expiry date |
| Cancel | Revoke the credential |
SubscriptionCredential Schema
{
"$credentialType": ["VerifiableCredential", "SubscriptionCredential"],
"properties": {
"tier": { "type": "string", "enum": ["free", "basic", "pro"] },
"scope": { "type": "array", "items": { "type": "string" } },
"registries": { "type": "array", "items": { "type": "string" } },
"maxDidsPerMonth": { "type": "number" },
"maxUploadBytes": { "type": "number" },
"subscribedAt": { "type": "string", "format": "date-time" }
},
"required": ["tier", "scope", "subscribedAt"]
}Example tiers:
- free — hyperswarm operations only, no IPFS uploads, rate-limited (e.g., 10 DIDs/month)
- basic — hyperswarm + BTC:signet, limited IPFS storage quota, higher rate limits
- pro — all registries including BTC:mainnet, generous/unlimited IPFS uploads
Drawbridge Auth Middleware
- Extract credential DID and requesting DID from the request
- Resolve the credential via gatekeeper — verify it's a valid
SubscriptionCredential - Verify the credential via keymaster — check not expired, not revoked
- Verify group membership via gatekeeper — confirm the requesting DID is a member of the credential's holder (group DID)
- Check usage counters in Redis against tier limits (rate limits, DID quotas, upload quotas)
- Proxy the request to the backend service, or return 401 (not a group member) / 403 (insufficient scope) / 429 (rate limited)
- On success, increment usage counters in Redis
Relationship to L402 (#75)
L402 and subscriptions are complementary, not competing:
- Subscriptions — ongoing access for regular customers
- L402 — pay-as-you-go for one-off operations, anonymous access, or agent-to-agent commerce
- L402 could be the payment mechanism for purchasing a subscription (pay Lightning invoice → receive credential)
Prerequisites
- feat: Add @didcid/cl-hive client package #120 —
@didcid/cl-hiveclient package (for Lightning payment handling) - Group DID support (create group, add/remove members, check membership)
- Credential update support for renewals and tier changes
- A credential schema for
SubscriptionCredential
Enables
- Paid Archon deployments with tiered access (opt-in, personal nodes unaffected)
- Zero-friction onboarding (free tier in one round-trip, no prior state needed)
- Rate-limited free tier (prevents spam without blocking access entirely)
- Metered IPFS storage by subscription tier
- Tiered registry access (free hyperswarm vs paid BTC:mainnet)
- Self-sustaining node economics (subscription revenue covers on-chain TX fees and IPFS storage costs)