Unseenet Working Group A. Lorensen
UN-RFC: 0004 October 2026
Category: Standards Track
Status: Draft
Unseenet: Groups, Manifests and Access Control
Abstract¶
This document defines Unseenet groups: how they are named, how they are created and changed through signed manifests, the four group types and their posting rules, end-to-end encryption of closed groups with epoch-based key rotation, and cancellation.
1. Group IDs¶
A Group ID is
group-id = name "@" fingerprint
name = component *( "." component )
component= ( a-z / 0-9 ) *( a-z / 0-9 / "+" / "_" / "-" )
where fingerprint is the owner's key fingerprint (UN-RFC 0003, 16
characters). name is at most 128 octets.
Example: dk.snak@ab3k5x7qwe2rtz4m.
Because the fingerprint is part of the ID, anybody can create
dk.snak, but only one owner can own dk.snak@ab3k5x7qwe2rtz4m.
Clients SHOULD display the short form dk.snak@ab3k and MUST warn when
a user subscribes to a group whose name equals that of another
subscribed group with a different fingerprint.
The first name component conventionally names a hierarchy as on Usenet
(comp, sci, alt, dk, ...). There is no authority over
hierarchies; they are only a convention for browsing.
2. Group Types¶
| Type | Who may post | Readable by |
|---|---|---|
open |
any identity | anyone |
moderated |
owner, moderators; others only with a valid approval | anyone |
channel |
owner, moderators, and listed posters | anyone |
closed |
holders of the current group secret | members only |
The type is fixed at creation. A later manifest MUST NOT change it; nodes MUST reject a manifest that does.
3. Manifests¶
A manifest is an article (UN-RFC 0002) with:
Control: manifestNewsgroups:the Group IDAuthor-Key:the owner's key, whose fingerprint MUST equal the fingerprint in the Group IDContent-Type: application/json- a body that is a single JSON object in canonical JSON: UTF-8, object keys sorted by code point, no insignificant whitespace, followed by CRLF.
3.1 Fields¶
| Field | Type | Req. | Meaning |
|---|---|---|---|
v |
integer | yes | 1 |
name |
string | yes | The name part of the Group ID |
type |
string | yes | open, moderated, channel, closed |
owner |
key string | yes | Owner key; MUST equal Author-Key |
serial |
integer | yes | Starts at 1, increases with each change |
title |
string | no | Short title (max 128 characters) |
description |
string | no | Description (max 2048 characters) |
moderators |
array of keys | no | Moderators |
posters |
array of keys | no | Extra posters (channel groups) |
min_pow |
integer | no | Minimum postage bits (UN-RFC 0006), default 0 |
retention_days |
integer | no | Suggested retention, default 90 |
sealed |
b64 string | no | Closed groups: encrypted private info (6.6) |
Unknown fields MUST be preserved (they are inside the signed body) and ignored.
3.2 Which Manifest Is Current¶
Of all valid manifests for a Group ID, the one with the highest
serial is current. If two valid manifests have the same serial, the
one with the lexicographically lowest Message-ID wins. This makes the
choice deterministic on every node without coordination.
3.3 Creating a Group¶
A group is created by posting its first manifest (serial 1) to a node. Whether a node carries a new group is the operator's decision. A node SHOULD support at least these policies: accept all new groups; accept groups from a list of trusted owner keys; hold new groups for manual approval.
Manifests are replicated like any other article and are exempt from the
group's own min_pow, but not from the node's minimum postage.
4. Manifest Validation¶
In addition to UN-RFC 0002 section 5, a node MUST check that:
- The body parses as JSON and is in canonical form.
vis 1;namematches the Group ID; the owner fingerprint matches.ownerequalsAuthor-Key.- If a previous manifest is known,
typeis unchanged andowneris unchanged, except by a transfer (UN-RFC 0015).
5. Posting Rules¶
A node MUST reject an ordinary (non-control) article that does not satisfy the rule for the group's type under the current manifest:
- open: no additional rule.
- channel:
Author-Keyis the owner, a moderator or a poster. - moderated:
Author-Keyis the owner or a moderator, or the article carries Approved-By:a moderator's (or the owner's) key, andApproval:a signature by that key, purposeUNSEENET-APPROVAL-1, overgroup-id || 0x00 || message-id(the Message-ID including angle brackets, as ASCII).
Because Approved-By and Approval are outside the canonical form,
approving an article does not change its Message-ID. How an
unapproved article reaches a moderator is not specified in this
version (reserved: UN-RFC 0009); clients MAY hand it over out of band.
- closed: see section 6.5.
6. Closed Groups¶
6.1 Epochs and the Group Secret¶
A closed group's lifetime is divided into epochs numbered from 1.
Each epoch has a random 32-octet group secret S_e. From it,
enc_key_e and the epoch's member key are derived as in UN-RFC
0003 section 4.3.
6.2 Key Updates¶
An epoch begins with a key-update control article by the owner:
Control: key-update <epoch>Content-Type: application/json- canonical JSON body:
{"envelopes":{"<tag>":"<b64 sealed box>", ...},"epoch":2,"member_key":"ed25519:...","v":1}
Each envelope is a sealed box (UN-RFC 0003 section 4.1) to one member,
containing S_e (32 octets). The tag lets a member find their envelope
without revealing who they are:
tag = first 16 chars of b32( H( DS("UNSEENET-RECIPIENT-1") ||
group-id || 0x00 || epoch-as-text || 0x00 || member_pk ) )
Tags differ between groups and between epochs, so they cannot be used to link a member across groups.
The owner MUST include an envelope for themself. A new epoch MUST be started whenever a member is removed.
6.3 Adding Members Without Rotation¶
To add a member without starting a new epoch, the owner posts
Control: key-grant <epoch> with the same body format but without
member_key. Nodes validate only that the author is the owner.
6.4 Joining¶
How a prospective member communicates their public key to the owner is outside the protocol (e.g. an invitation link or a message in another group). A client SHOULD support invitation URIs of the form
unseenet:join?g=<group-id>&n=<node-onion-address>
which tell the client which group to subscribe to and which node to ask.
6.5 Encrypted Articles¶
An ordinary article in a closed group MUST:
- have
Encrypted: xchacha20poly1305; epoch=<e>; - NOT have
FromorSubjectin the outer header block; - have as body the b64 encoding (lines of at most 76 characters) of
nonce || ciphertext, encrypted withenc_key_eand associated datagroup-id || 0x00 || epoch-as-text; - carry
Member-Signature:, a signature with the epoch's member key, purposeUNSEENET-MEMBER-1, over the canonical formCof the article.
The plaintext is an inner block in article syntax: inner headers
(at least From and Subject; optionally Content-Type and others),
an empty line, and the inner body.
A node MUST reject the article unless Member-Signature verifies with
the member key of epoch e, and e is the current epoch or the one
before it (to tolerate replication delay). Thus only holders of the
group secret can post, and nodes enforce this without being able to
read anything.
6.6 Sealed Manifest Information¶
The manifest of a closed group is public. Its title and description
SHOULD therefore be omitted or generic. Private information MAY be put
in sealed: the b64 of nonce || ciphertext of a canonical JSON
object, encrypted with enc_key_1 and associated data
group-id || 0x00 || "manifest".
7. Cancellation¶
Control: cancel <message-id> withdraws an article. It is valid when
its author is the author of the target article, or the owner or a
moderator of the group. A node that accepts a valid cancel SHOULD
delete the target and MUST NOT forward the target afterwards. The
cancel itself is forwarded like any article. A node that has not seen
the target yet SHOULD remember the cancel so it can refuse the target.
Old Usenet's forged cancels are impossible because cancels are signed and checked against the target.
8. Security and Privacy Considerations¶
- Removed members keep everything they already received. Rotation only protects future content. There is no forward secrecy within an epoch. A stronger scheme (e.g. MLS, RFC 9420) may be specified later.
- Metadata visible to nodes for closed groups: Group ID, manifest, number of envelopes (≈ member count), article sizes, approximate dates and author keys.
- Owner key loss means the group can no longer be changed. Owners SHOULD keep an offline backup of the owner key.
- Nodes enforce posting rules, but a malicious node can still drop articles. Clients SHOULD read from more than one node.
Copyright Notice¶
Copyright (c) 2026 the persons identified as the document authors.
This document is licensed under CC BY 4.0, see rfc/LICENSE.md.