docs: specify response framing and superseded-key retention
This commit is contained in:
parent
6c76d1d6e9
commit
9a31607648
1 changed files with 28 additions and 2 deletions
30
SPEC.md
30
SPEC.md
|
|
@ -54,7 +54,7 @@ A client MUST NOT `REGISTER`, `FETCH` or `DELETE` against a server whose static
|
||||||
|
|
||||||
**Framing.** Each Noise message carries a 2-byte length prefix and is at most 65535 bytes. Application frames are `length (u32) || type (u8) || body`, split across Noise messages, with a default maximum of 1 MiB. Every field is length-prefixed; nothing on the wire requires text parsing or delimiter scanning.
|
**Framing.** Each Noise message carries a 2-byte length prefix and is at most 65535 bytes. Application frames are `length (u32) || type (u8) || body`, split across Noise messages, with a default maximum of 1 MiB. Every field is length-prefixed; nothing on the wire requires text parsing or delimiter scanning.
|
||||||
|
|
||||||
**Session authentication.** `FETCH` and `DELETE` require one `AUTH` frame after the handshake:
|
**Session authentication.** `FETCH` and `DELETE` require one `AUTH` frame — an application frame of type `0x00` — after the handshake:
|
||||||
|
|
||||||
```
|
```
|
||||||
username_len u8 || username || identity 32 || signature 64
|
username_len u8 || username || identity 32 || signature 64
|
||||||
|
|
@ -157,6 +157,30 @@ Because `esk` is wiped, a sender cannot decrypt what they sent. To keep a Sent f
|
||||||
|
|
||||||
`FETCH` has no cursors, flags or server-side read state; a client loops until it returns nothing. `REGISTER` without a certificate binds a free username, or returns code 9; with one, it rebinds an existing username when the chain validates against the currently bound key.
|
`FETCH` has no cursors, flags or server-side read state; a client loops until it returns nothing. `REGISTER` without a certificate binds a free username, or returns code 9; with one, it rebinds an existing username when the chain validates against the currently bound key.
|
||||||
|
|
||||||
|
### 6.1 Request and response bodies
|
||||||
|
|
||||||
|
A request body is the operation's payload. A response body begins with `status (u8)` from §12; on `0` the operation's payload follows, on anything else an optional UTF-8 reason string. A response reuses the request's type byte. `AUTH` is type `0x00` and its response carries a status and no payload.
|
||||||
|
|
||||||
|
```
|
||||||
|
RESOLVE → username_len u8 || username
|
||||||
|
← identity 32 || chain_len u8 || cert 136 × chain_len
|
||||||
|
|
||||||
|
SEND → envelope
|
||||||
|
← id 16
|
||||||
|
|
||||||
|
FETCH → (empty)
|
||||||
|
← count u16 || ( id 16 || received_at i64 || env_len u32 || envelope ) × count
|
||||||
|
|
||||||
|
DELETE → count u16 || id 16 × count
|
||||||
|
← removed u16
|
||||||
|
|
||||||
|
REGISTER → username_len u8 || username || identity 32
|
||||||
|
|| token_len u8 || token || cert_len u8 || cert
|
||||||
|
← (empty)
|
||||||
|
```
|
||||||
|
|
||||||
|
A zero length means the field is absent. `FETCH` returns records oldest first, up to a server byte budget which MUST be smaller than the maximum application frame; 512 KiB against the default 1 MiB frame is a reasonable choice.
|
||||||
|
|
||||||
## 7. Key rotation
|
## 7. Key rotation
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -166,6 +190,8 @@ signature = Ed25519 by old_pub over "smolmail/1 rotate" || old_pub || new_pub ||
|
||||||
|
|
||||||
A server keeps each username's ordered chain of certificates and returns it with every `RESOLVE`. A client holding a stale pinned key walks the chain forward from that key, verifying each link, and accepts the new key silently if the chain terminates at the key `RESOLVE` returned. A broken, absent or over-long chain — maximum 16 links — requires explicit user confirmation. Senders SHOULD also push their certificate to contacts as an ordinary message, so rotation propagates without depending on the old server.
|
A server keeps each username's ordered chain of certificates and returns it with every `RESOLVE`. A client holding a stale pinned key walks the chain forward from that key, verifying each link, and accepts the new key silently if the chain terminates at the key `RESOLVE` returned. A broken, absent or over-long chain — maximum 16 links — requires explicit user confirmation. Senders SHOULD also push their certificate to contacts as an ordinary message, so rotation propagates without depending on the old server.
|
||||||
|
|
||||||
|
A server MUST retain every key ever bound to a username, MUST accept `SEND` addressed to any of them, and MUST return messages addressed to any of them on `FETCH`. Without this, mail from a contact who has not yet seen a rotation is addressed to a superseded key and becomes unreachable.
|
||||||
|
|
||||||
**Rotation is not revocation.** An attacker holding a stolen identity key can rotate to their own key and the chain will validate. Clients MUST surface rotations in the interface rather than applying them invisibly; out-of-band re-verification is the only defence against a compromised identity key. There is no revocation mechanism in version 1.
|
**Rotation is not revocation.** An attacker holding a stolen identity key can rotate to their own key and the chain will validate. Clients MUST surface rotations in the interface rather than applying them invisibly; out-of-band re-verification is the only defence against a compromised identity key. There is no revocation mechanism in version 1.
|
||||||
|
|
||||||
## 8. Trust model
|
## 8. Trust model
|
||||||
|
|
@ -213,7 +239,7 @@ A conforming server is a single binary over an embedded key-value store.
|
||||||
2 bad version 5 auth failed 8 rate limited
|
2 bad version 5 auth failed 8 rate limited
|
||||||
```
|
```
|
||||||
|
|
||||||
A response MAY carry a UTF-8 reason string. Clients MUST NOT parse it.
|
A status is the first byte of every response body (§6.1), which MAY be followed by a UTF-8 reason string. Clients MUST NOT parse the reason.
|
||||||
|
|
||||||
## 13. Out of scope for version 1
|
## 13. Out of scope for version 1
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue