mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-09-10 19:26:00 +00:00
* Add pay2seed to the OpenSwarm family: consent at upload and a paid seed market OpenSwarm pays a seeder per verified piece served, and nothing pays anyone to stay. An archive, a backup, a dataset waiting for its buyer or a podcast's back catalogue earns nothing the month nobody downloads it, so it dies the way every swarm always has. And nothing in BitTorrent says who put a swarm there or whether they were allowed to, which is why a seeder is presumed to be doing something wrong. pay2seed is the member document for both halves. An attestation, signed at upload with a fixed basis (own, licensed, open-license, public-domain, personal) and a notice endpoint, is what a hub requires before it will list anything; public claims get a claim window and a standing, and a notice voids them. An offer escrows a budget at an ippay hub for a swarm, public or private, to be held by M seeders for N days at a price per GiB-month, bought over x402 exactly as a pass is. Seeders take leases, prove each period by storage challenge or by a probe over the ordinary wire, and are paid through the payee they already have. Public feeds ride on ipdb; ipfile.pin on c0mpute is the same offer on the auction. Also: the family table, stack diagram and registry rows; the ip seed command group; PRD 0006; the protocol row on /openswarm. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKAohrRkqLKVQL2cGCAkR5 * Split pay2seed into client and server halves, and add pay2stream and paid2stream The rule is now in the names. pay2* is the client protocol: the side that pays, over HTTPS, and plays. paid2* is the server protocol: the BitTorrent side that earns. One hub implements both halves of a pair; a requester or viewer implements only pay2*; a seeder, relay or gateway only paid2*. pay2seed keeps consent, offers, the requester's market and notices. paid2seed takes leases, storage challenges and probes over the wire, GiB-month accrual and receipts, the seeder client, and the ipfile.pin mapping. pay2stream and paid2stream do the same for a live channel over iplive. A broadcaster attests the channel (with the two rules that separate a licensed rebroadcast from a stolen feed), buys relays by the hour, and publishes listings; viewers buy tickets. Relays take leases and are proven present by a verifier that pulls segments as a peer; a gateway is a relay that also serves standard HLS, clear or sealed, with the M3U and XMLTV pair every IPTV app asks for, so VLC, TiviMate, Kodi and a television play a paid swarm with nothing installed. Ace Stream showed BitTorrent can carry live TV to millions; this is that with consent, payment and an open spec. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKAohrRkqLKVQL2cGCAkR5 * pay2seed: encrypted by default, access as the product, a README in every swarm The client encrypts by default and the hub never does: what the hub manages is who may decrypt. A team is a named set of member keys with a scope over the owner's swarms; the hub, as keeper, issues grants to members when the owner is offline, with invitations that expire, roles, an audit trail, and re-encryption on removal so the next version is closed to whoever left. A few seats are free; above that the hub charges per seat and per organisation, settled through the same pay plugins as everything else. Seeding is priced at disk; access is where a hub earns, and both sides earn: seeders rent disk, requesters sell access. Public is not a fallback. Encryption off is an explicit act, and a public swarm is attested, listed, kept and rendered exactly as a private one is; the only difference is who can read it. Every swarm on the market carries a README.md at its root, no exceptions, and the attestation carries its Markdown and the hash of the copy inside the swarm, so the hub renders it as the swarm's page without a key. Relative links resolve into the swarm and are gated the way the files are. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKAohrRkqLKVQL2cGCAkR5 * pay2seed: 1 percent, ads on the free tier, and agents as sellers Three things the specs did not say. The reference hub takes 1 percent of any payment that crosses it, charged to whoever is paying and never deducted from a seeder or a relay, so a quoted price is what the publisher gets and a promised floor is what the seeder is paid. Public swarms are free to fetch and free to list, and an advertisement on the swarm README page is what pays for that. The ad is on the hub page and nowhere else: never inside a swarm, never injected into a file, a segment or a playlist, and never in the catalogue or the market API. A requester who wants no ad buys a seat instead. A free-to-watch channel works the same way. And a requester is a key, not a person. An agent can attest what it made, price access, sell tickets, take payment through its own payee and spend what it earns keeping its own work online. The consent rules do not soften because a machine signed them, and the reference hub asks an agent public attestation to name a responsible operator key so somebody is reachable when a notice arrives. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKAohrRkqLKVQL2cGCAkR5 * Fix CI: number the PRD requirements and advance the next-id assertion Two checks the new PRD tripped, both by existing rather than by being wrong. The collection validator wants requirements as numbered R# entries and 0006 used a plain ordered list, so it reported OP-L-NO-REQUIREMENTS. Rewritten as R1 to R7 with priorities, one capability per entry, and the implementation tracking moved to a paragraph under them where it is not pretending to be a requirement. The MCP standards test asserts what the next free PRD id is, and its own comment says that advances with every PRD added. Adding 0006 makes it 0007. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKAohrRkqLKVQL2cGCAkR5 --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
208 lines
8.9 KiB
Markdown
208 lines
8.9 KiB
Markdown
# The `ip` CLI (proposed)
|
|
|
|
Version: **0.1** (draft)
|
|
Status: proposal. No binary exists. Names and flags here are the contract
|
|
an implementation would meet; they are not a promise that this is the
|
|
final surface.
|
|
|
|
## 1. Shape
|
|
|
|
One binary, `ip`, with a noun-verb tree. Every command accepts `--json`
|
|
for machine output and returns exit code 0 on success, 2 on a usage error,
|
|
3 on a verification failure (signature, hash, chain), 4 on a payment
|
|
failure (no pass, cap reached, hub refused), 5 on a network failure.
|
|
|
|
Configuration lives at `~/.config/ip/config.json`; the keystore at
|
|
`~/.config/ip/keys/` with mode 0600, or in an OpenCreds vault when
|
|
`ip init --vault` is used. The local `ipdb` replica is
|
|
`~/.local/share/ip/db.sqlite`.
|
|
|
|
## 2. Commands
|
|
|
|
### 2.1 Identity
|
|
|
|
```
|
|
ip init [--vault] [--name <label>]
|
|
ip key show [--box]
|
|
ip key export --out <file> # the seed, encrypted with a passphrase
|
|
ip key import <file>
|
|
ip key rotate # mints a new seed, revises every file (core §4.5)
|
|
ip key bind-pq <mldsa65 key file> # publishes an openswarm.binding
|
|
```
|
|
|
|
### 2.2 Files
|
|
|
|
```
|
|
ip file add <path> [--per-gib <usd>] [--key-price <usd>] [--public] [--private]
|
|
[--standalone-key] [--piece-length <bytes>] [--tracker <url>]... [--webseed <url>]...
|
|
[--hub <url>]... [--pay-to <network>:<address>] [--split <pub>,<seed>,<hub>]
|
|
[--keeper <ed25519:...>]... [--meta.<k> <v>]... [--feed <name>]
|
|
ip file get <file key | infohash | ip:// url | magnet> --out <path> [--pass <file>] [--tunnel mtp] [--stream]
|
|
ip file revise <file key> [--per-gib ...] [--tracker ...] [--pay-to ...] # metadata-only revision
|
|
ip file reencrypt <file key> # new content key, new swarm
|
|
ip file rotate <file key> # successor file key
|
|
ip file seed [<file key>... | --all] [--vanilla ciphertext|deny]
|
|
ip file share <file key> --to <ip:// name | x25519 key> [--grant] [--delegate --expires <days>]
|
|
ip file pin <file key> --days <n> [--min-peers <n>] [--erasure <k>,<p>] [--max-price <usd>]
|
|
ip file keep-hire <file key> --days <n> [--max-price <usd>]
|
|
ip file status <file key> # manifest, revs, peers seen, bytes served, earnings
|
|
```
|
|
|
|
`ip file add` prints the file key, both infohashes, the manifest id and
|
|
the `magnet:` and `ip://` forms. With `--json` it prints the manifest.
|
|
|
|
### 2.3 Payment
|
|
|
|
```
|
|
ip pass buy --hub <url> (--file <key> | --publisher <key>) --cap <usd> [--grant] [--days <n>]
|
|
ip pass list
|
|
ip pass show <pass id>
|
|
ip payee register --hub <url> --pay-to <network>:<address>
|
|
ip payee balance [--hub <url>]
|
|
ip voucher redeem [--all | --swarm <infohash>] # normally automatic; manual for audit
|
|
ip hub info <url>
|
|
```
|
|
|
|
`ip pass buy` performs the x402 exchange with the key from
|
|
`X402_PRIVATE_KEY` or `--key-file`, the same as `x402 pay`.
|
|
|
|
### 2.4 Audio
|
|
|
|
```
|
|
ip audio publish <track.json | source files...> [--release <release.json>] [--renditions <ids>]
|
|
[--on c0mpute --max-price <usd>] [--royalty <address>:<bps>]... [file add flags]
|
|
ip audio play <track id | ip:// url> [--rendition <id>]
|
|
ip audio rss <release id> --gateway <url> --out <feed.xml>
|
|
```
|
|
|
|
### 2.5 Video
|
|
|
|
```
|
|
ip video publish <source> [--ladder default | <ids>] [--subtitle <lang>:<file.vtt>]...
|
|
[--thumbnails] [--chapters <file>] [--on c0mpute --max-price <usd>] [file add flags]
|
|
ip video play <title id | ip:// url>
|
|
ip video hls <title id> --gateway <url> # prints the master playlist URL
|
|
```
|
|
|
|
### 2.6 Live
|
|
|
|
```
|
|
ip live create <name> [--latency normal|low] [--segment-ms <n>] [--per-gib <usd>] [--key-price <usd>]
|
|
[--rendition <id>:<codecs>:<w>x<h>:<kbps>]... [--relays any | <keys>]
|
|
ip live start <name> --input <rtmp:// | srt:// | file> [--record] [--max-downstream <n>]
|
|
ip live stop <name>
|
|
ip live watch <channel key | ip:// url> [--rendition <id>] [--out <file>]
|
|
ip live relay <channel key> [--max-downstream <n>]
|
|
ip live relay-hire <channel key> --hours <n> --relays <n> [--max-downstream <n>] [--max-price <usd>]
|
|
```
|
|
|
|
### 2.7 Catalogue
|
|
|
|
```
|
|
ip db put <key> <record.json> [--feed <name>]
|
|
ip db del <key> [--feed <name>]
|
|
ip db get <ip:// url | feed/key>
|
|
ip db query [--type <t>] [--feed <ref>]... [--where '<path> <op> <value>']... [--order <path>:asc|desc] [--limit <n>]
|
|
ip db follow <feed ref>
|
|
ip db unfollow <feed ref>
|
|
ip db head [<feed ref>]
|
|
ip db segment [--feed <name>] # seal a segment now
|
|
ip db index-hire <feed ref>... --days <n> [--max-price <usd>]
|
|
```
|
|
|
|
`--where` takes one clause per flag; the value is JSON (`'"Ada"'`, `120000`).
|
|
|
|
### 2.8 Names
|
|
|
|
```
|
|
ip name set <name> [--gateway <url>] [--hub <url>]... [--mtp-pin <pin>] [--feed <ref>]...
|
|
ip name resolve <name>
|
|
ip name pin <name> # prints the registry pin value and the TXT record
|
|
```
|
|
|
|
### 2.9 Node
|
|
|
|
```
|
|
ip node status
|
|
ip node hello <peer address> # diagnostic: handshake and print the peer's hello
|
|
```
|
|
|
|
A c0mpute worker embeds the same library; `c0mpute worker start --openswarm`
|
|
is the daemon form and `ip` is the operator's tool.
|
|
|
|
### 2.10 Seed and stream markets
|
|
|
|
```
|
|
ip seed attest (<file key> | <infohash> | <magnet>) --basis own|licensed|open-license|public-domain|personal
|
|
[--license <spdx>] [--notice <url|mailto>] [--description <text>] [--public | --private]
|
|
ip seed offer (<file key> | <infohash> | --feed <feed key>) --hub <url> --days <n> --seeders <min>[,<max>]
|
|
[--price <usd per GiB-month>] [--proof-hours <n>] [--tracker <url>]...
|
|
ip seed offers [--hub <url>] [--public | --private] [--basis <b>] [--min-price <usd>] [--max-size <bytes>]
|
|
ip seed take <offer id> --hub <url> # take a lease, fetch, seed until it ends
|
|
ip seed leases [--hub <url>] [--status proven|fetching|lapsed|ended]
|
|
ip seed status <offer id | lease id>
|
|
ip seed void <offer id> # requester: void and refund the unearned budget
|
|
ip seed notice <attestation id> --kind rights|illegal|personal-data|other --statement <text>
|
|
ip team create <name> --hub <url> [--scope <file key>|--publisher <key>]...
|
|
ip team invite <team> --to <email|ipname|key> [--role admin|member|readonly] [--expires <days>]
|
|
ip team accept <invite id>
|
|
ip team remove <team> <key> [--no-rotate]
|
|
ip team grant <team> --file <file key> # a member fetching their sealed grant
|
|
ip team audit <team> [--since <time>]
|
|
```
|
|
|
|
```
|
|
ip stream offer <channel key> --hub <url> --from <time> --to <time> --relays <min>[,<max>]
|
|
[--price <usd per relay-hour>] [--gateway-bonus <bps>] [--region <r>]...
|
|
ip stream ticket <channel key> --hub <url> --hours <n> [--gateway <url>] # prints the HLS, M3U and EPG URLs
|
|
ip stream listing <channel key> --title <text> --from <time> --to <time> [--price <usd>]
|
|
ip stream relay <offer id> --hub <url> [--gateway --base <url> --mode clear|sealed]
|
|
ip stream relays [--hub <url>]
|
|
```
|
|
|
|
`ip seed attest` is the consent step and is what `ip file add --public`,
|
|
`ip file pin` and `ip live create` call first; `ip seed offer` on a private file key includes a
|
|
pass for the seeders when the manifest charges per GiB. `ip seed take` is
|
|
what a torlink daemon does on its own from `ip seed offers`; here it is the
|
|
manual form, and it sets the swarm's seed time to the lease's end so the
|
|
client's reaper cannot drop it early. Everything returns the record ids
|
|
(`pay2seed` §7.2) and, for `offers`, the projected `earnedUsd` per lease.
|
|
|
|
## 3. Output examples
|
|
|
|
```
|
|
$ ip file add ./interview.flac --per-gib 0.01 --key-price 0.50
|
|
file ed25519:0d87e09c7fea3ad6ba6c2f3e027ea47f5b245452899910948470906704c5295d
|
|
manifest sha256:41d10f45e705e0526c9eeedf62b32dda3daaf552dd9b6a7b09e01776b05813bb
|
|
infohash v1 a3ce2180413415d7cf4268fb892b8ffd539e8459
|
|
v2 4b74eb43677e4d03af5fb0856333f9aa21d9a5a3bbf944b13aa7eef379c7a342
|
|
size 734003200 (700 pieces of 1048576)
|
|
magnet magnet:?xs=urn:btpk:0d87e09c7fea3ad6ba6c2f3e027ea47f5b245452899910948470906704c5295d&s=ipfile
|
|
url ip://ed25519:0d87e09c7fea3ad6ba6c2f3e027ea47f5b245452899910948470906704c5295d?file
|
|
seeding yes (2 trackers, dht)
|
|
```
|
|
|
|
```
|
|
$ ip file get ed25519:0d87e0...295d --out ./interview.flac
|
|
pass reused sha256:39655d...02fd (cap 2.000000, spent 0.000000)
|
|
peers 3 (2 paid, 1 gateway)
|
|
progress 734003200 / 734003200 verified plainRoot ok
|
|
vouchers 3 signed, 0.006836 USD
|
|
key granted by ed25519:d2d05f...6c94 (keeper)
|
|
```
|
|
|
|
## 4. Environment
|
|
|
|
| Variable | Meaning |
|
|
| --- | --- |
|
|
| `IP_HOME` | Overrides the config directory. |
|
|
| `IP_HUB` | Default hub URL. |
|
|
| `X402_PRIVATE_KEY` | EVM key used to buy passes, shared with `x402-client`. |
|
|
| `IP_TRACKERS` | Comma list of default trackers for `file add`. |
|
|
| `MOSHPIT_RESOLVE_MODE` | Passed through to name resolution (`ipname` §4.2). |
|
|
|
|
## 5. Conformance
|
|
|
|
A CLI claiming this contract implements every command in §2 with these
|
|
exit codes, prints the fields in §3 for `add` and `get`, and never writes a
|
|
seed or a content key to stdout unless asked with an explicit `--reveal`.
|