# How Satshoal-style swarms work

**Working names:** satshoal · flock · shoal  
Code and folders may still say “Open Swarm.” Treat that as an internal label, not a hard public brand.

*Keep open models and open datasets alive with Lightning. Not piracy.*

---

## Three lanes

| Lane | Job | Tool |
|------|-----|------|
| Discovery | Who has what, at what price | Nostr events |
| Money | Pay the seeder | Lightning (lud16 → BOLT11) |
| Bytes | Move the payload | BitTorrent / WebTorrent |

Nostr never carries file bytes. Invoices never embed the payload. Torrents never settle sats. Keeping those lanes apart is the whole design.

---

## Legal shelf, not a pirate index

Hosted catalogs use a hard SPDX allowlist:

`MIT` · `Apache-2.0` · `BSD-2-Clause` · `BSD-3-Clause` · `CC0-1.0` · `CC-BY-4.0` · `Unlicense`

Intended indexed content: open weights, open datasets, and the tiny demo fixtures in this repo.

Out of scope for the **hosted** shelf: copyrighted movies, commercial music, TV, games, warez, or anything without an allowlisted license.

Clients **may** seed user-chosen magnets on a local machine. The site catalog API **must not** ingest those magnets. That split is intentional.

---

## Catalog allowlist

Every public listing carries `license_spdx`. Before publish, seeder register, retainer, or mediated piece pay, the hosted index runs a license gate. Missing or unknown licenses are rejected. The bouncer is boring on purpose. Boring is how you stay legal.

---

## Earn as a seeder (lud16)

A Lightning address (lud16) looks like `name@domain`. It is where sats land.

Flow:

1. Choose an allowlisted fixture or listing.
2. Paste your lud16 and set a rate (sats per piece or whole file).
3. Register. The demo helps you seed (WebTorrent in the browser, local BT where configured).
4. Copy a Nostr **seeder ad** (draft kind in the 39000 range). Peers learn you are online and how to pay you.

Downloads pay **your** address. The demo default lud16 is only a fallback for show-and-tell.

---

## Get-file: paywall, then unlock

1. Pick a file.
2. Pay for the next piece, or buy the whole remaining file in one invoice.
3. Invoice memo binds payment to content id and expected hash (`infohash|piece|hash|nonce`, or whole-file forms).
4. You pay with WebLN (e.g. Alby), QR, or a browser-pasted Hub NWC. The main Get-file path does not silently spend a server wallet for you.
5. After settle, claim unlock. Held bytes stay locked until unlock succeeds.
6. Verify SHA-256 locally. Mismatch means discard.

Unpaid means locked. Paid and verified means unlocked.

---

## Bytes on BitTorrent / WebTorrent

Legal fixtures include tiny real payloads. Some ship `.torrent` / magnet metadata for open content only.

- Browser WebTorrent can seed for demos.
- A box-local seeder can announce and serve pieces.
- Protocol piece-pay still settles on Lightning. BT is the byte pipe.

---

## Thick client CLI

`thick-client/seed_cli.py` is a Python CLI for humans and agents. Not Electron.

It can poll the catalog, register seeders, emit invoices without paying, optionally pay via a local NWC file, claim and hash-check pieces, and prove that arbitrary magnets stay local (`seed-local` / prove-blocked). Exit codes distinguish success, usage/block, and pay/claim failure.

---

## Nostr seeder ads

Draft event kinds (experimental private range):

| Kind | Role |
|------|------|
| 39000 | Content listing |
| 39001 | Seeder ad + rate card + lud16 |
| 39002–39004 | Retainer bounty / fund / challenge result |
| 39005 | Attestation stub |

The demo stores events in local SQLite so everything works offline. Publishing to a public relay is optional.

---

## What is real vs what is demo

**Real today**

- Piece and file SHA-256
- SPDX allowlist enforcement on the hosted catalog
- Tiny MIT / Apache / BSD / CC0 / Unlicense fixtures
- Real LNURL invoices when `OPEN_SWARM_LN_MODE=nwc` (user pays)
- Local Nostr-like event store
- WebTorrent / BT seeding for legal fixtures

**Demo or unfinished**

- Simulated Lightning when mode is `sim`
- Optional public Nostr relay (not required for the UI)
- Hold invoices / HTLC-preimage binding (prefer tiny amounts until this exists)
- Full attested retainer markets

**Never**

- A hosted pirate magnet index

---

## Where this can go (ideas from Napstr)

[Napstr](https://napstr.net) rebuilt peer music sharing with Nostr for discovery and Tor for private transfers. It is **not** a Lightning value-for-value client today. The architecture still teaches useful patterns for an open-license satshoal product:

1. **Catalogue ≠ heartbeat.** Publish metadata once (Napstr kind 30421). Publish short-lived “I am seeding these ids” heartbeats (30422) so dead peers expire.
2. **Negotiate in private.** Use encrypted DMs (NIP-17 style) for capability tickets or peer intro; keep public relays free of transfer secrets. Map that to BT peer exchange or webseed tickets while lud16 stays public on the seeder ad.
3. **Content id is the hash.** Aggregate many authors per file id. Rank by live availability, not by who shouted first.
4. **Thick desktop + thin companion.** Phone or CLI pairs to your seeder (Napstrfy uses Iroh). Secrets and Tor/BT stay on the always-on box.
5. **Explicit withdrawal.** Replace catalogue events when files leave the share folder so the graph does not lie.

Our money lane stays Lightning. Our byte lane stays BitTorrent for redistributable open files. Our discovery lane stays Nostr. The SPDX gate stays non-negotiable for anything the hosted index will show.

---

## Further reading

- Protocol draft: [`../SPEC.md`](../SPEC.md) and `/workspace/open-swarm-protocol`
- Agent commands: [`AGENT.md`](./AGENT.md)
- Demo evidence: [`DEMOS.md`](./DEMOS.md)
- Plain ELI5 twin: [`ELI5.md`](./ELI5.md)

One line: **discover on Nostr, pay on Lightning, fetch on BitTorrent, index only what you may redistribute.**
