Skip to content

Commit 513fd07

Browse files
authored
Merge branch 'main' into feat/nip66-publish-events
2 parents 79d04f9 + 3690bd8 commit 513fd07

49 files changed

Lines changed: 2273 additions & 215 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.changeset/codeql-admin-rate-limit-models.md‎

Lines changed: 0 additions & 5 deletions
This file was deleted.

‎.changeset/disable-codeql.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"nostream": patch
3+
---
4+
5+
ci: disable CodeQL workflow
6+
7+
Removes the CodeQL Advanced GitHub Actions workflow, custom query pack, config,
8+
and route suppression comments to stop false-positive security alerts on admin
9+
routes that already use custom auth and rate limiting.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
"nostream": minor
3+
---
4+
5+
feat(nip43): issue kind 28935 invite codes on request
6+
7+
NIP-43 kind 28935 is not an event clients publish — it is a REQ the relay answers by
8+
minting an invite code on the fly and returning a relay-signed ephemeral event. Nostream
9+
now serves those subscriptions, completing the membership flow: request a claim, join with
10+
kind 28934, publish.
11+
12+
Off by default. It requires `nip43.enabled` and the new `nip43.allowInviteRequests`, a
13+
NIP-42 authenticated requester, an `info.self` consistent with the relay signing key, and a
14+
per-pubkey budget under the new `limits.invite.rateLimits` (5/hour by default). This also
15+
makes the previously inert `nip43.inviteRequestWhitelist` setting take effect. The minted
16+
event is never persisted and never broadcast: the claim tag is a bearer secret and is sent
17+
only to the socket that asked for it.
18+
19+
Two fixes the flow depended on. The relay signs its own events with a key derived from
20+
`SECRET`, but `info.self` was a hand-edited string that nothing validated — by default it
21+
was a placeholder that is not a pubkey at all, so any NIP-43 client verifying a relay-signed
22+
event against `self` would reject it. `info.self` is now optional: when unset or unparseable,
23+
NIP-11 advertises the derived signing pubkey instead, and `nostream info` prints that pubkey
24+
so operators can pin it.
25+
26+
Kind 28935 also sits in the ephemeral range, so a client-published one fell through to
27+
`EphemeralEventStrategy` and was broadcast to every subscriber — including everyone
28+
subscribed to kind 28935 waiting for a real invite. Anyone could inject a forged `claim` tag
29+
into that subscription. It is now rejected with an `OK` false and never broadcast, and
30+
bypasses the NIP-43 admission gate so that rejection actually reaches non-members, who are
31+
the ones most likely to publish it by mistake while trying to obtain a code.
32+
33+
CLI.md and README.md now describe the request flow. CLI.md previously claimed the relay
34+
"does not yet generate kind 28935 on `REQ`", and never mentioned that `nostream info`
35+
prints the signing pubkey that CONFIGURATION.md tells operators to pin.

‎.changeset/readyz-endpoint.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"nostream": minor
3+
---
4+
5+
feat(ops): add /readyz readiness probe for Postgres and Redis
6+
7+
Adds a public readiness endpoint for zero-downtime deploy workflows. HAProxy (or similar) can use `/readyz` to confirm an instance can serve traffic before cutover, while `/healthz` remains a lightweight liveness check.

‎.changeset/wot-graph-service.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
"nostream": minor
3+
---
4+
5+
feat: add a Web of Trust graph service that tracks NIP-02 follow distance from an operator-configured seed pubkey
6+
7+
Adds a `WotGraphService` that builds a trust graph rooted at `wot.seedPubkey`, updated in real
8+
time as kind-3 contact list events are ingested, with configurable depth (`wot.maxDepth`) and a
9+
minimum-followers threshold for 2+ hop trust (`wot.minimumFollowers`). Exposes `getDistance()` and
10+
`isTrusted()` for other parts of the relay to query. Disabled by default (`wot.enabled: false`).

‎.github/codeql/codeql-config.yml‎

Lines changed: 0 additions & 8 deletions
This file was deleted.

‎.github/codeql/extensions/nostream-javascript-models/NostreamRateLimitingMiddleware.qll‎

Lines changed: 0 additions & 50 deletions
This file was deleted.

‎.github/codeql/extensions/nostream-javascript-models/codeql-pack.yml‎

Lines changed: 0 additions & 5 deletions
This file was deleted.

‎.github/workflows/codeql.yml‎

Lines changed: 0 additions & 111 deletions
This file was deleted.

‎CLI.md‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,20 @@ docker compose exec nostream node src/cli/index.js invite create
4646

4747
`--uses` defaults to `nip43.defaultMaxUses` (1). `--expires-in` defaults to `nip43.inviteCodeExpirySeconds` (600 = 10 minutes). `--expires-in` must be a positive integer; never-expiring codes are a yaml policy (`nip43.inviteCodeExpirySeconds: 0`), not a CLI flag. The printed code is the first line of human output so scripts can capture it. If `info.self` is a hex pubkey or `npub1…`, it is stored as `created_by`.
4848

49-
This does not yet generate kind 28935 on `REQ` or publish membership list events.
49+
The relay also answers `REQ`s for kind 28935 by minting a code on the fly and returning it as a relay-signed ephemeral event, so users can obtain a claim string without an operator handing one out. It is off by default and requires `nip43.enabled`, `nip43.allowInviteRequests` and a NIP-42 authenticated client — see [CONFIGURATION.md](CONFIGURATION.md). Membership list events (kind 13534) are not published yet.
50+
51+
Invites minted over `REQ` record the requesting pubkey as `created_by`; `nostream invite create` records `info.self`.
52+
53+
### Relay signing pubkey
54+
55+
NIP-43 clients verify relay-signed events against the `self` field of the NIP-11 document, so `self` must match the key the relay actually signs with. That key is derived from `SECRET` and is otherwise invisible, so `nostream info` prints it:
56+
57+
```bash
58+
nostream info | grep 'Signing pubkey'
59+
nostream info --json # same value under relay.signingPubkey
60+
```
61+
62+
Leave `info.self` unset in settings to have this value advertised automatically. Set it only if you want to pin it explicitly, and set it to exactly this value — a mismatch disables kind 28935 invite requests.
5063

5164
## Removed Legacy Wrappers
5265

0 commit comments

Comments
 (0)