clone

nostr relays on demand at <name>.bind.ws: claim one with your key, pay in zaps past the free allowance

docs: the architecture and the developer guide name the new modules and where a NIP is wired in

Dami committed 4249ffa
commit
4249ffa8c76c36e5f0e42581925fcfbca9ffd410
parent
b865a74eaeb1afb6a893a78fd65b8e78e6ffba5d
author
Dami <dami.etoile@gmail.com>
2 files changed, +17 -9
Mdocs/10-architecture.md7+++++--
Mdocs/12-develop-extend.md19++++++++++++-------
M docs/10-architecture.md +5 -2
@@ -40,12 +40,15 @@ Custom hostnames (`domains.ts`) are registered with Cloudflare for SaaS from the
4040 - **Settings** (`settings.ts`): policy, members, bans, kind rules, retention, invites, reports, blocked addresses, succession.4141 - **Fuel** (`fuel.ts`): usage meters, credits, prices.4242 - **Identity** (`identity.ts`): the relay's own keypair and everything it signs.43+- **Succession** (`succession.ts`): the heir and the dead-man's switch.44+45+What it does not own it reaches by one call: the gates (`gates.ts`), the HTTP doors (`routes.ts`), the information document (`nip11.ts`), and the feature modules below. The event kinds all of them name are in `kinds.ts`.4346 4447 The constructor runs schema setup inside `blockConcurrencyWhile`, then handles fetches. Websockets use the hibernation API. Per-connection state (NIP-42 challenge, authenticated pubkeys, open subscriptions, the filters of open syncs, the client's address) is stored on the socket with `serializeAttachment`, so it survives hibernation. A negentropy session's item list is in memory only; the next NEG-MSG after a wake reads it again from the store by the remembered filter, asking the read rule again first, so a sync carries on across a sleep. A socket whose attachment is over its limit keeps the session in memory alone, and that one ends with `closed:` when the object sleeps.4548 46-The write path is one gate plus the client policy. The gate refuses malformed, expired, banned and out-of-context events (an `h` tag for another group) and, for client writes, the unclaimed and expired-lease states, fuel and NIP-70. The client policy adds kind rules, retention windows, the write rule, proof of work and per-member caps. Host-side writes, such as pulls and the relay's own records, pass the gate only. Kind 24133, NIP-46 signer traffic, passes everything but bans and rate limits on the way in: it is ephemeral, never stored and encrypted end to end, so the relay can carry a remote signer's session for the console, including for someone about to claim it. On the way out it is a private kind, delivered to a socket authenticated as its sender or its `p` recipient, or to a subscription that names one of those keys in `#p` or `authors`, under any read rule and without AUTH: the payload is encrypted end to end, and signers and their clients hold no key the relay knows. Amber probes a relay this way before it will list it, and Amethyst's bunker listens under a transport key it never authenticates with. A bare subscription to the kind sees nothing, so a members-only relay reveals signer traffic only to someone who already holds the key it is addressed to. A subscription to 24133 alone may be opened under any read rule. The console's remote-signer client answers the challenge with the session's own key.49+The write path is one gate (`writeGate` in `gates.ts`) plus the client policy. The gate refuses malformed, expired, banned and out-of-context events (an `h` tag for another group) and, for client writes, the unclaimed and expired-lease states, fuel and NIP-70. The client policy adds kind rules, retention windows, the write rule, proof of work and per-member caps. Host-side writes, such as pulls and the relay's own records, pass the gate only. Kind 24133, NIP-46 signer traffic, passes everything but bans and rate limits on the way in: it is ephemeral, never stored and encrypted end to end, so the relay can carry a remote signer's session for the console, including for someone about to claim it. On the way out it is a private kind, delivered to a socket authenticated as its sender or its `p` recipient, or to a subscription that names one of those keys in `#p` or `authors`, under any read rule and without AUTH: the payload is encrypted end to end, and signers and their clients hold no key the relay knows. Amber probes a relay this way before it will list it, and Amethyst's bunker listens under a transport key it never authenticates with. A bare subscription to the kind sees nothing, so a members-only relay reveals signer traffic only to someone who already holds the key it is addressed to. A subscription to 24133 alone may be opened under any read rule. The console's remote-signer client answers the challenge with the session's own key.4750 48-The read path is one gate too, `Settings.mayRead`, given the pubkeys a caller has proved: on the socket the NIP-42 set, over HTTP whatever `whoAsks` (`auth.ts`) found in the Authorization header, a NIP-98 signature or a Blossom token. REQ, COUNT, NEG-OPEN, the bridge, blob downloads and listings, file reports, the same-host file copy and the members-only views all ask it; the directory switch adds `mayList` for names and counts. Changing the rule runs `enforceReads`, which closes every open subscription the rule no longer admits.51+The read path is one gate too (`readGate` in `gates.ts`, over `Settings.mayRead`), given the pubkeys a caller has proved: on the socket the NIP-42 set, over HTTP whatever `whoAsks` (`auth.ts`) found in the Authorization header, a NIP-98 signature or a Blossom token. REQ, COUNT, NEG-OPEN, the bridge, blob downloads and listings, file reports, the same-host file copy and the members-only views all ask it; the directory switch adds `mayList` for names and counts. Changing the rule runs `enforceReads`, which closes every open subscription the rule no longer admits.4952 5053 ## Storage and media5154
M docs/12-develop-extend.md +12 -7
@@ -14,7 +14,12 @@ src/
1414 names.ts valid names, reserved names, lease names1515 pull.ts copy another relay in: NIP-77 as the initiator, one round per connection1616 jobs.ts the alarm's job list: pulls, backfills, rebroadcasts, once or standing17- relay.ts the Durable Object: sockets, policy, fuel plumbing, NIP-1117+ relay.ts the Durable Object: sockets, the alarm, members and bans, jobs, usage18+ gates.ts the write gate and the read gate19+ routes.ts the HTTP doors, in the order they are tried, each saying whether a blocked address may use it20+ nip11.ts the information document and the supported-NIP list21+ succession.ts an heir and a dead-man's switch22+ kinds.ts every event kind the relay treats specially, by NIP1823 store.ts SQLite schema and queries1924 settings.ts policy, members, bans, kind rules, retention, export/import2025 roles.ts who may do what: owner, moderator; one table for NIP-86 and NIP-29
@@ -84,19 +89,19 @@ CI runs typecheck and the object tests on every push; the conformance suite agai
8489 8590 ## Add a NIP8691 87-Most NIPs land as their own module, wired in from `relay.ts` with one import and one route or one call. That is the pattern to follow:92+Most NIPs land as their own module, wired in with one import and one row in `routes.ts` or one call from `relay.ts`. That is the pattern to follow:8893 8994 | NIP | Module | Wired from |9095 |---|---|---|91-| 29 groups | `groups.ts` | the write gate in `relay.ts`, before the client policy |96+| 29 groups | `groups.ts` | `acceptGroup` in `relay.ts`, after the write gate (`gates.ts`) |9297 | 43 roster | `identity.ts` | `publishMembership` in `relay.ts` |9398 | 66 discovery | `nip66.ts` | `publishDiscovery` in `relay.ts`, from `publishMembership` and the alarm |94-| 46 transport | one kind in the write gate and the read gate | `relay.ts` |99+| 46 transport | one kind in the write gate and the read gate | `gates.ts` |95100 | 86 methods | `manage.ts` with `roles.ts` | the RPC route |96-| 96 files | `nip96.ts` over `blossom.ts` | one path line in `fetch` |97-| 11 extras | `settings.ts` fields, `info()` | `relay.ts` |101+| 96 files | `nip96.ts` over `blossom.ts` | one row in `routes.ts` |102+| 11 extras | `settings.ts` fields, `nip11.ts` | the NIP-11 row in `routes.ts` |98103 99-A NIP that changes the query surface touches `store.ts`. Add the number to `SUPPORTED_NIPS` only when the NIP says relays advertise it, with a word in the comment there for the less obvious ones. Add a file named after the NIP in `test/conformance` so the behavior is checked from outside, and a Durable Object test in `test/object`, named after the module it exercises; a NIP number names a test file only where the feature has no other name (`nip05`, `nip11`, `nip66`).104+A NIP that changes the query surface touches `store.ts`. Add the number to `SUPPORTED_NIPS` in `nip11.ts` only when the NIP says relays advertise it, with a word in the comment there for the less obvious ones. Add a file named after the NIP in `test/conformance` so the behavior is checked from outside, and a Durable Object test in `test/object`, named after the module it exercises; a NIP number names a test file only where the feature has no other name (`nip05`, `nip11`, `nip66`).100105 101106 ## The signer bundle102107