implement nip4e interop tags

This commit is contained in:
2026-11-04 08:42:18 +07:00
parent 198f13bd1d
commit 029ab21983
5 changed files with 350 additions and 31 deletions
+29 -3
View File
@@ -89,8 +89,9 @@ with a documented [client profile](https://github.com/CodyTseng/psstpsst/blob/ma
## Status
Section A (items 1-5) is implemented in `crates/nip4e/src/lib.rs` and
`crates/state/src/credentials.rs`:
### Section A (items 1-5) — implemented
Implemented in `crates/nip4e/src/lib.rs` and `crates/state/src/credentials.rs`:
- Ephemeral per-request client key, held in memory for the lifetime of one
request (retries reuse it so an open approval sheet keeps targeting a key the
@@ -105,4 +106,29 @@ Section A (items 1-5) is implemented in `crates/nip4e/src/lib.rs` and
- An open approval is withdrawn when a `4455` addressed to the same client key
arrives (another device already answered).
Items 6-12 remain open.
### Section B (items 6-8) — implemented
- **Interop tags on `4454`** (`crates/nip4e/src/lib.rs`): requests now carry
the draft's `P` tag plus the `pubkey` compatibility alias, `relay` hints (the
requester's NIP-65 write relays), and an optional `n` tag pinning the exact
encryption key the requester observed in its announcement. Responder readers
accept `P` or `pubkey` on both `4454` and `4455`.
- **Responder honors the request** (`approve`): the identity `p` tag is added
to `4455` for account inbox routing; the response is published to the union
of the responder's NIP-65 write relays and the request's normalized `relay`
hints (each hint parsed as untrusted input), falling back to the NIP-65
policy when no relays are known; when the request pins an `n` key this device
no longer holds, the transfer is refused instead of sending a key the
requester would reject.
- **Peer announcement ordering** (`crates/state/src/nip4e.rs`,
`crates/person/src/person.rs`): `Announcement` now carries the event id and
creation time, and `is_newer_than` implements the psstpsst ordering (newer
`created_at` wins, ties go to the lexicographically smaller event id).
`Person::set_announcement` only replaces an existing announcement with a
newer one, so delayed or out-of-order `10044` events cannot roll a peer's
key back. Freshness remains subscription-based: peer `10044` is re-subscribed
whenever a room opens, over the connected relay set that includes
discovery/bootstrap relays — push-based and stronger than psstpsst's one-day
TTL polling, so no separate announcement cache was added.
Items 9-12 remain open.